--- /dev/null
+<AVRStudio><MANAGEMENT><ProjectName>bc100_master</ProjectName><Created>28-Mar-2008 10:14:10</Created><LastEdit>02-Apr-2008 16:36:02</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>28-Mar-2008 10:14:10</Created><Version>4</Version><Build>4, 13, 0, 557</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile>default\bc100_master.elf</ObjectFile><EntryFile></EntryFile><SaveFolder>D:\EigenMT\develop\uProz\bc100\bcc100_gcc\BaseMegaFirmware\GCC\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET>JTAGICE mkII</CURRENT_TARGET><CURRENT_PART>ATmega644.xml</CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM>Auto</COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>uart.c</SOURCEFILE><SOURCEFILE>main.c</SOURCEFILE><SOURCEFILE>mystdio.c</SOURCEFILE><SOURCEFILE>spi.c</SOURCEFILE><SOURCEFILE>bc100_slave.c</SOURCEFILE><SOURCEFILE>port_ext.c</SOURCEFILE><SOURCEFILE>timebase.c</SOURCEFILE><SOURCEFILE>key_io.c</SOURCEFILE><HEADERFILE>uart.h</HEADERFILE><HEADERFILE>mystdio.h</HEADERFILE><HEADERFILE>spi.h</HEADERFILE><HEADERFILE>bc100_slave.h</HEADERFILE><HEADERFILE>D:\EigenMT\develop\uProz\bc100\bcc100_gcc\BaseTinyFirmware\GCC\enums.h</HEADERFILE><HEADERFILE>D:\EigenMT\develop\uProz\bc100\bcc100_gcc\BaseTinyFirmware\GCC\structs.h</HEADERFILE><HEADERFILE>port_ext.h</HEADERFILE><HEADERFILE>timebase.h</HEADERFILE><HEADERFILE>key_io.h</HEADERFILE><OTHERFILE>default\bc100_master.lss</OTHERFILE><OTHERFILE>default\bc100_master.map</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>default</NAME><USESEXTERNALMAKEFILE>NO</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE></EXTERNALMAKEFILE><PART>atmega644</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>bc100_master.elf</OUTPUTFILENAME><OUTPUTDIR>default\</OUTPUTDIR><ISDIRTY>1</ISDIRTY><OPTIONS><OPTION><FILE>main.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>mystdio.c</FILE><OPTIONLIST></OPTIONLIST></OPTION><OPTION><FILE>uart.c</FILE><OPTIONLIST></OPTIONLIST></OPTION></OPTIONS><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -DF_CPU=7372800UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums</OPTIONSFORALL><LINKEROPTIONS>-Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm</LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>default</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><IOView><usergroups/></IOView><Files></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio>\r
--- /dev/null
+<AVRWorkspace><IOSettings><CurrentRegisters/></IOSettings><part name="ATMEGA644"/><Files/></AVRWorkspace>\r
--- /dev/null
+// Martin Thomas 3/2008\r
+\r
+#include <stdint.h>\r
+#include <stdlib.h>\r
+#include <avr/io.h>\r
+\r
+#include "../../BaseTinyFirmware/GCC/enums.h"\r
+#include "../../BaseTinyFirmware/GCC/structs.h"\r
+\r
+#include "spi.h"\r
+#include "bc100_slave.h"\r
+\r
+#ifdef BC100_SLAVE_TEST\r
+#include "mystdio.h"\r
+#endif\r
+\r
+#define dummy 0x00\r
+\r
+void bc100_slave_init( void )\r
+{\r
+}\r
+\r
+uint8_t bc100_slave_read( uint8_t cmd, size_t size, void *buf )\r
+{\r
+ uint8_t err = 0;\r
+\r
+ return err;\r
+}\r
+\r
+#ifdef BC100_SLAVE_TEST\r
+\r
+uint8_t bc100_slave_test(void)\r
+{\r
+ uint8_t err = 0;\r
+ uint8_t in, out, i;\r
+ uint32_t timevals[TIMERS];\r
+\r
+ SPI_init();\r
+\r
+ SPI_rw( dummy );\r
+ myprintf_P("Timers:\n");\r
+ out = BC100_SLAVE_READ | BC100_SLAVE_SRAM | sizeof(timevals);\r
+ SPI_rw( out );\r
+ out = ADR_TIMERS;\r
+ in = SPI_rw( out );\r
+ myprintf_P("In1 : 0x%02x (expected 0xcc)\n", in );\r
+ in = SPI_rw( dummy );\r
+ myprintf_P("In2 : 0x%02x (expected 0xbb)\n", in );\r
+#if 0\r
+ uint8_t tmp\r
+ for ( i = TIMERS; i > 0; i-- ) {\r
+ tmp = (uint32_t)(SPI_rw(dummy)) << 24;\r
+ tmp |= (uint32_t)(SPI_rw(dummy)) << 16;\r
+ tmp |= (uint32_t)(SPI_rw(dummy)) << 8;\r
+ tmp |= (uint32_t)(SPI_rw(dummy)) << 0;\r
+ timevals[i-1] = tmp;\r
+ }\r
+#else\r
+ i = sizeof(timevals);\r
+ while ( i-- > 0 ) {\r
+ *( (unsigned char*)&timevals + i ) = SPI_rw(dummy);\r
+ }\r
+#endif\r
+ for ( i=0; i<TIMERS; i++ ) {\r
+ myprintf_P("Timer #%d = %lu (0x%08lx)\n", i, timevals[i], timevals[i] );\r
+ }\r
+\r
+\r
+ ADC_Status_t ADCS;\r
+ myprintf_P("ADC-Status:\n");\r
+ out = BC100_SLAVE_READ | BC100_SLAVE_SRAM | sizeof(ADCS);\r
+ SPI_rw( out );\r
+ out = ADR_ADCS;\r
+ in = SPI_rw( out );\r
+ myprintf_P("In1 : 0x%02x (expected 0xcc)\n", in );\r
+ in = SPI_rw( dummy );\r
+ myprintf_P("In2 : 0x%02x (expected 0xbb)\n", in );\r
+ i = sizeof(ADCS);\r
+ while ( i-- > 0 ) {\r
+ *( (unsigned char*)&ADCS + i ) = SPI_rw(dummy);\r
+ }\r
+ myprintf_P("ADC-MUX %d\n", ADCS.MUX );\r
+ myprintf_P("Cycle complete %d\n", ADCS.Flag);\r
+ myprintf_P("Mains OK %d\n", ADCS.Mains);\r
+ myprintf_P("A/D halt %d\n", ADCS.Halt);\r
+ myprintf_P("Offs ADC3 g20 %d\n", ADCS.ADC3_G20_OS);\r
+ myprintf_P("Offs ADC5 g20 %d\n", ADCS.ADC5_G20_OS);\r
+ myprintf_P("rawRID %d\n", ADCS.rawRID);\r
+ myprintf_P("rawNTC %d\n", ADCS.rawNTC);\r
+ myprintf_P("rawVBAT %d\n", ADCS.rawVBAT);\r
+ myprintf_P("Supply %d [mV]\n", ADCS.VIN);\r
+ myprintf_P("Batt. Voltage %d [mV]\n", ADCS.VBAT);\r
+ myprintf_P("Batt. Current %d [mA]\n", ADCS.IBAT);\r
+ for ( i=0; i<4; i++ ) {\r
+ myprintf_P("DiscIBAT[%d] %d [mA]\n", i, ADCS.discIBAT[i] );\r
+ }\r
+ myprintf_P("average IBAT %d [mA]\n", ADCS.avgIBAT);\r
+\r
+ SPI_release();\r
+\r
+ return err;\r
+}\r
+\r
+#endif /* BC100_SLAVE_TEST */\r
+\r
--- /dev/null
+// Martin Thomas 3/2008\r
+#ifndef BC100_SLAVE_H\r
+#define BC100_SLAVE_H\r
+\r
+#define BC100_SLAVE_TEST\r
+\r
+#include <stdint.h>\r
+#include <stdlib.h>\r
+\r
+#define BC100_SLAVE_READ 0x00\r
+#define BC100_SLAVE_WRITE 0x40\r
+#define BC100_SLAVE_EEPROM 0x80\r
+#define BC100_SLAVE_SRAM 0x00\r
+\r
+\r
+void bc100_slave_init( void );\r
+uint8_t bc100_slave_read( uint8_t cmd, size_t size, void *buf );\r
+\r
+#ifdef BC100_SLAVE_TEST\r
+uint8_t bc100_slave_test(void);\r
+#endif\r
+\r
+#endif\r
--- /dev/null
+###############################################################################\r
+# Makefile for the project bc100_master\r
+###############################################################################\r
+\r
+## General Flags\r
+PROJECT = bc100_master\r
+MCU = atmega644\r
+TARGET = bc100_master.elf\r
+CC = avr-gcc.exe\r
+\r
+## Options common to compile, link and assembly rules\r
+COMMON = -mmcu=$(MCU)\r
+\r
+## Compile options common for all C compilation units.\r
+CFLAGS = $(COMMON)\r
+CFLAGS += -Wall -gdwarf-2 -std=gnu99 -DF_CPU=7372800UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums\r
+CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d \r
+\r
+## Assembly specific flags\r
+ASMFLAGS = $(COMMON)\r
+ASMFLAGS += $(CFLAGS)\r
+ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2\r
+\r
+## Linker flags\r
+LDFLAGS = $(COMMON)\r
+LDFLAGS += -Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscanf -lscanf_flt -lm -Wl,-Map=bc100_master.map\r
+\r
+\r
+## Intel Hex file production flags\r
+HEX_FLASH_FLAGS = -R .eeprom\r
+\r
+HEX_EEPROM_FLAGS = -j .eeprom\r
+HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"\r
+HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings\r
+\r
+\r
+## Objects that must be built in order to link\r
+OBJECTS = uart.o main.o mystdio.o spi.o bc100_slave.o port_ext.o timebase.o key_io.o \r
+\r
+## Objects explicitly added by the user\r
+LINKONLYOBJECTS = \r
+\r
+## Build\r
+all: $(TARGET) bc100_master.hex bc100_master.eep bc100_master.lss size\r
+\r
+## Compile\r
+uart.o: ../uart.c\r
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<\r
+\r
+main.o: ../main.c\r
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<\r
+\r
+mystdio.o: ../mystdio.c\r
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<\r
+\r
+spi.o: ../spi.c\r
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<\r
+\r
+bc100_slave.o: ../bc100_slave.c\r
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<\r
+\r
+port_ext.o: ../port_ext.c\r
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<\r
+\r
+timebase.o: ../timebase.c\r
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<\r
+\r
+key_io.o: ../key_io.c\r
+ $(CC) $(INCLUDES) $(CFLAGS) -c $<\r
+\r
+##Link\r
+$(TARGET): $(OBJECTS)\r
+ $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)\r
+\r
+%.hex: $(TARGET)\r
+ avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@\r
+\r
+%.eep: $(TARGET)\r
+ -avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0\r
+\r
+%.lss: $(TARGET)\r
+ avr-objdump -h -S $< > $@\r
+\r
+size: ${TARGET}\r
+ @echo\r
+ @avr-size -C --mcu=${MCU} ${TARGET}\r
+\r
+## Clean target\r
+.PHONY: clean\r
+clean:\r
+ -rm -rf $(OBJECTS) bc100_master.elf dep/* bc100_master.hex bc100_master.eep bc100_master.lss bc100_master.map\r
+\r
+\r
+## Other dependencies\r
+-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)\r
+\r
--- /dev/null
+// M. Thomas 11/2007\r
+\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+#include "key_io.h"\r
+\r
+/* define externs */\r
+// debounced and inverted key state, bit = 1: key pressed\r
+volatile uint8_t key_io_state; \r
+// key press detect\r
+volatile uint8_t key_io_press;\r
+// key long press and repeat\r
+volatile uint8_t key_io_rpt;\r
+\r
+void key_io_init(void)\r
+{\r
+ KEY_IO_KEYSA_DDR &= ~( \r
+ (1<<KEY_IO_KEYA1_BIT) | (1<<KEY_IO_KEYA2_BIT) |\r
+ (1<<KEY_IO_KEYA3_BIT) | (1<<KEY_IO_KEYA4_BIT) );\r
+ KEY_IO_KEYSB_DDR &= ~(1<<KEY_IO_KEYB1_BIT);\r
+ // external pull-ups avail. for all keys -> no init here\r
+ key_io_state = key_io_state_hardware();\r
+}\r
+\r
+uint8_t key_io_get_press( uint8_t key_mask )\r
+{\r
+ uint8_t sreg;\r
+\r
+ sreg = SREG;\r
+ cli();\r
+\r
+ key_mask &= key_io_press; // read key(s)\r
+ key_io_press ^= key_mask; // clear key(s)\r
+\r
+ SREG = sreg;\r
+\r
+ return key_mask;\r
+}\r
+\r
+uint8_t key_io_get_rpt( uint8_t key_mask )\r
+{\r
+ uint8_t sreg;\r
+\r
+ sreg = SREG;\r
+ cli();\r
+\r
+ key_mask &= key_io_rpt; // read key(s)\r
+ key_io_rpt ^= key_mask; // clear key(s)\r
+ \r
+ SREG = sreg;\r
+\r
+ return key_mask;\r
+}\r
+\r
+uint8_t key_io_get_was_short( uint8_t key_mask )\r
+{\r
+ uint8_t sreg, ret;\r
+\r
+ sreg=SREG;\r
+ // read key state and key press atomic !\r
+ cli();\r
+\r
+ ret = key_io_get_press( ~key_io_state & key_mask );\r
+\r
+ SREG = sreg;\r
+\r
+ return ret;\r
+\r
+}\r
+\r
+uint8_t key_io_get_longpress( uint8_t key_mask )\r
+{\r
+ return key_io_get_press( key_io_get_rpt( key_mask ));\r
+}\r
+\r
+\r
--- /dev/null
+/* Copyright (c)2007, 2008 Martin Thomas, BSD license */\r
+\r
+#ifndef KEY_IO_H_\r
+#define KEY_IO_H_\r
+\r
+#include <stdint.h>\r
+#include <avr/io.h>\r
+\r
+#include "timebase.h" /* for TIMEBASE_DELTAT_MS */\r
+\r
+#define KEY_IO_KEYSA_DDR DDRC\r
+#define KEY_IO_KEYSA_PORT PORTC\r
+#define KEY_IO_KEYSA_PIN PINC\r
+#define KEY_IO_KEYA1_BIT PC0 /* SW0 */\r
+#define KEY_IO_KEYA2_BIT PC1 /* SW1 */\r
+#define KEY_IO_KEYA3_BIT PC6 /* SW2 */\r
+#define KEY_IO_KEYA4_BIT PC7 /* SW3 */\r
+#define KEY_IO_KEYSB_DDR DDRD\r
+#define KEY_IO_KEYSB_PORT PORTD\r
+#define KEY_IO_KEYSB_PIN PIND\r
+#define KEY_IO_KEYB1_BIT PD5 /* Power button */\r
+\r
+#define KEY_IO_KEY_SW0 (1<<0)\r
+#define KEY_IO_KEY_SW1 (1<<1)\r
+#define KEY_IO_KEY_SW2 (1<<2)\r
+#define KEY_IO_KEY_SW3 (1<<3)\r
+#define KEY_IO_KEY_POWER (1<<4)\r
+#define KEY_IO_KEY_ALL \\r
+ ( KEY_IO_KEY_SW0 | \\r
+ KEY_IO_KEY_SW1 | \\r
+ KEY_IO_KEY_SW2 | \\r
+ KEY_IO_KEY_SW3 | \\r
+ KEY_IO_KEY_POWER )\r
+\r
+\r
+static inline uint8_t key_io_state_hardware(void)\r
+{\r
+ uint8_t tmp1, tmp2, tmp3;\r
+ tmp1 = KEY_IO_KEYSA_PIN & ( (1<<KEY_IO_KEYA1_BIT) | (1<<KEY_IO_KEYA2_BIT) );\r
+ tmp2 = KEY_IO_KEYSA_PIN & ( (1<<KEY_IO_KEYA3_BIT) | (1<<KEY_IO_KEYA4_BIT) );\r
+ tmp2 >>= 4;\r
+ tmp3 = KEY_IO_KEYSB_PIN & (1<<KEY_IO_KEYB1_BIT);\r
+ tmp3 >>= 1;\r
+ return ( tmp1 | tmp2 | tmp3 );\r
+}\r
+\r
+/* debounce/repeat code based on an example from Peter Dannegger,\r
+ modified for better integration and volatiles added */\r
+\r
+//#define KEY_IO_REPEAT_MASK ( KEY_IO_KEY_DOWN | KEY_IO_KEY_UP )\r
+#define KEY_IO_REPEAT_MASK ( KEY_IO_KEY_ALL )\r
+#define KEY_IO_REPEAT_START ( 500/*ms*/ / TIMEBASE_DELTAT_MS )\r
+#define KEY_IO_REPEAT_NEXT ( 100/*ms*/ / TIMEBASE_DELTAT_MS )\r
+\r
+// debounced and inverted key state, bit = 1: key pressed\r
+extern volatile uint8_t key_io_state; \r
+// key press detect\r
+extern volatile uint8_t key_io_press;\r
+// key long press and repeat\r
+extern volatile uint8_t key_io_rpt;\r
+\r
+/* The following callback-function has to be \r
+ called frequently from timer-ISR. Implemented \r
+ in this header-file as static inline to \r
+ indicate to the compiler that the function \r
+ should be inlined into the ISR-code. Tested with \r
+ avr-gcc 4.2.1: inlined - o.k. */\r
+static inline void key_io_callback(void)\r
+{\r
+ static uint8_t ct0, ct1, rpt;\r
+ uint8_t i, mystate;\r
+\r
+ mystate = key_io_state;\r
+\r
+ i = mystate ^ ~( key_io_state_hardware() ); // keys changed ?\r
+ ct0 = ~(ct0 & i); // reset or count ct0\r
+ ct1 = ct0 ^ (ct1 & i); // reset or count ct1\r
+ i &= ct0 & ct1; // count until roll over ?\r
+ mystate ^= i; // then toggle debounced state\r
+ key_io_press |= mystate & i; // 0->1: key press detect\r
+\r
+ if( (mystate & KEY_IO_REPEAT_MASK) == 0 ) { // check repeat function\r
+ rpt = KEY_IO_REPEAT_START; // start delay\r
+ }\r
+ if( --rpt == 0 ) {\r
+ rpt = KEY_IO_REPEAT_NEXT; // repeat delay\r
+ key_io_rpt |= mystate & KEY_IO_REPEAT_MASK;\r
+ }\r
+\r
+ key_io_state = mystate;\r
+}\r
+\r
+void key_io_init(void);\r
+\r
+uint8_t key_io_get_press( uint8_t key_mask );\r
+uint8_t key_io_get_rpt( uint8_t key_mask );\r
+uint8_t key_io_get_longpress( uint8_t key_mask );\r
+/* only returns "true" after key has been released: */\r
+uint8_t key_io_get_was_short( uint8_t key_mask );\r
+\r
+#endif\r
--- /dev/null
+/* Copyright (c) 2008 Martin Thomas\r
+ All rights reserved.\r
+\r
+ Redistribution and use in source and binary forms, with or without\r
+ modification, are permitted provided that the following conditions are met:\r
+\r
+ * Redistributions of source code must retain the above copyright\r
+ notice, this list of conditions and the following disclaimer.\r
+\r
+ * Redistributions in binary form must reproduce the above copyright\r
+ notice, this list of conditions and the following disclaimer in\r
+ the documentation and/or other materials provided with the\r
+ distribution.\r
+\r
+ * Neither the name of the copyright holders nor the names of\r
+ contributors may be used to endorse or promote products derived\r
+ from this software without specific prior written permission.\r
+\r
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ POSSIBILITY OF SUCH DAMAGE.\r
+*/\r
+\r
+#define VERSION_STRING "V0.1 4/2008"\r
+\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <stdint.h>\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+#include <avr/pgmspace.h>\r
+#include <util/delay.h>\r
+\r
+#include "uart.h"\r
+#include "mystdio.h"\r
+#include "bc100_slave.h"\r
+#include "port_ext.h"\r
+#include "timebase.h"\r
+#include "key_io.h"\r
+\r
+#ifndef F_CPU\r
+#warning "F_CPU not defined - will do now"\r
+#define F_CPU 7372800UL\r
+#endif\r
+\r
+#define UART_BAUD_RATE 115200\r
+\r
+static void fun_delay()\r
+{\r
+ uint8_t i;\r
+ for (i=0;i<10;i++) _delay_ms(10);\r
+}\r
+\r
+static void fun(void)\r
+{\r
+ uint8_t i, j;\r
+\r
+ for ( i=0; i<5; i++) {\r
+ port_ext_set( 1, 0x0f );\r
+ port_ext_update();\r
+ fun_delay();\r
+ port_ext_set( 1, 0xf0 );\r
+ port_ext_update();\r
+ fun_delay();\r
+ }\r
+ port_ext_set( 1, 0x00 );\r
+ port_ext_update();\r
+\r
+ for ( i=0; i<2; i++) {\r
+ for ( j=0; j<4; j++ ) {\r
+ port_ext_bit_set( 1, j );\r
+ port_ext_bit_set( 1, j+4 );\r
+ port_ext_update();\r
+ fun_delay();\r
+ }\r
+ for ( j=4; j>0; j-- ) {\r
+ port_ext_bit_clear( 1, j-1 );\r
+ port_ext_bit_clear( 1, j-1+4 );\r
+ port_ext_update();\r
+ fun_delay();\r
+ }\r
+ }\r
+ port_ext_set( 1, 0x00 );\r
+ port_ext_update();\r
+}\r
+\r
+static void slave_run(void)\r
+{\r
+ port_ext_bit_set( 0, 0 );\r
+ port_ext_bit_set( 0, 1 );\r
+ port_ext_update();\r
+}\r
+\r
+static void slave_stop(void)\r
+{\r
+ port_ext_bit_clear( 0, 0 );\r
+ port_ext_bit_clear( 0, 1 );\r
+ port_ext_update();\r
+}\r
+\r
+int main(void)\r
+{\r
+ uint16_t ui_input, tick_local, tick_now;\r
+ uint8_t c, show_menu;\r
+\r
+ // wait for power-button release (paranoia?)\r
+ while ( !( PIND & ( 1 << PD5 ) ) ) { ; }\r
+ key_io_init();\r
+\r
+ uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); \r
+ mystdio_init();\r
+\r
+ timebase_init();\r
+\r
+ sei();\r
+\r
+ myprintf_P("\n\nBC100 Master Firmware, (C) Martin Thomas " VERSION_STRING "\n");\r
+ \r
+\r
+ bc100_slave_init();\r
+\r
+ port_ext_init();\r
+ fun();\r
+ slave_run();\r
+\r
+ show_menu = 1;\r
+ tick_local = timebase_get_tick();\r
+\r
+ while ( 1 ) {\r
+ if ( show_menu ) {\r
+ myprintf_P("(1) 0x55 to LEDs\n");\r
+ myprintf_P("(2) 0xAA to LEDs\n");\r
+ myprintf_P("(3) MASTER_INT low\n");\r
+ myprintf_P("(4) MASTER_INT high\n");\r
+ myprintf_P("(f) Power Off\n");\r
+ myprintf_P("(t) Test Slave Comm\n");\r
+ myprintf_P("(r) Reset Slave\n");\r
+ myprintf_P("(h) Show this again\n");\r
+ myprintf_P("Select > ");\r
+ show_menu = 0;\r
+ }\r
+\r
+ ui_input = uart_getc();\r
+ if ( ui_input & UART_NO_DATA ) { \r
+ /* not data */ \r
+ }\r
+ else {\r
+ if ( ui_input & UART_FRAME_ERROR ) {\r
+ uart_puts_P("UART Frame Error: ");\r
+ }\r
+ if ( ui_input & UART_OVERRUN_ERROR ) {\r
+ uart_puts_P("UART Overrun Error: ");\r
+ }\r
+ if ( ui_input & UART_BUFFER_OVERFLOW ) {\r
+ uart_puts_P("Buffer overflow error: ");\r
+ }\r
+\r
+ c = (uint8_t)ui_input;\r
+ myprintf_P("%c\n", c);\r
+ switch ( c ) {\r
+#ifdef BC100_SLAVE_TEST\r
+ case 't' :\r
+ if ( ( PORTD & (1<<PD4) ) ||\r
+ !( DDRD & (1<<PD4) ) ) {\r
+ myprintf_P("MASTER_INT should be low\n");\r
+ }\r
+ bc100_slave_test();\r
+ break;\r
+#endif\r
+ case '1' :\r
+ port_ext_set( 1, 0x55 );\r
+ port_ext_update();\r
+ break;\r
+ case '2' :\r
+ port_ext_set( 1, 0xAA );\r
+ port_ext_update();\r
+ break;\r
+ case '3' :\r
+ PORTD &= ~(1<<PD4);\r
+ DDRD |= (1<<PD4);\r
+ break;\r
+ case '4' :\r
+ PORTD |= (1<<PD4);\r
+ DDRD |= (1<<PD4);\r
+ break;\r
+ case 'f' :\r
+ myprintf_P("Byebye");\r
+ _delay_ms(5);\r
+ slave_stop();\r
+ port_ext_bit_clear( 0, 2 );\r
+ port_ext_update();\r
+ while (1) { ; }\r
+ break;\r
+ case 'r' :\r
+ slave_stop();\r
+ _delay_ms(5);\r
+ slave_run();\r
+ break;\r
+ case 'h' :\r
+ show_menu = 1;\r
+ break;\r
+ default :\r
+ break;\r
+ } /* switch */\r
+ if ( !show_menu ) {\r
+ myprintf_P("Select (h=help) > ");\r
+ }\r
+ } /* key detected */\r
+\r
+ tick_now = timebase_get_tick();\r
+ if ( (uint16_t)( tick_now - tick_local ) > 200 ) {\r
+ // myprintf_P("Keys: %02x", key_io_state_hardware() );\r
+ tick_local = tick_now;\r
+ }\r
+\r
+ if ( key_io_get_press( KEY_IO_KEY_SW0 ) ) {\r
+ myprintf_P("SW0 press\n");\r
+ }\r
+ if( key_io_get_longpress( KEY_IO_KEY_SW1 ) ) {\r
+ myprintf_P("SW1 long\n");\r
+ }\r
+ if( key_io_get_was_short( KEY_IO_KEY_SW2 ) ) {\r
+ myprintf_P("SW2 was short\n");\r
+ }\r
+ if( key_io_get_rpt( KEY_IO_KEY_SW2 ) ) {\r
+ myprintf_P("SW2 repeat/long\n");\r
+ }\r
+ if ( key_io_get_press( KEY_IO_KEY_SW3 ) ) {\r
+ myprintf_P("SW3 pres\n");\r
+ }\r
+\r
+ if( key_io_get_press( KEY_IO_KEY_POWER ) ) {\r
+ myprintf_P("POWER Key hit -> Power off\n");\r
+ while ( !( PIND & (1 << PD5) ) ) { ; }\r
+ slave_stop();\r
+ port_ext_bit_clear( 0, 2 );\r
+ port_ext_update();\r
+ }\r
+\r
+\r
+ } /* main-loop */\r
+}\r
--- /dev/null
+// Martin Thomas 3/2008\r
+\r
+#include <avr/io.h>\r
+#include "uart.h"\r
+#include "mystdio.h"\r
+\r
+static int uart_putchar( char c, FILE *stream )\r
+{\r
+ if ( c == '\n' ) {\r
+ uart_putc( '\r' );\r
+ }\r
+ uart_putc( c );\r
+\r
+ return 0;\r
+}\r
+\r
+static FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);\r
+\r
+void mystdio_init(void)\r
+{\r
+ stdout = &uart_stream;\r
+}\r
--- /dev/null
+#ifndef MYSTDIO_H\r
+#define MYSTDIO_H\r
+\r
+#include <stdio.h>\r
+#include <avr/io.h>\r
+#include <avr/pgmspace.h>\r
+\r
+\r
+#define myprintf_P( printf_ctrl_, args_...) printf_P( PSTR(printf_ctrl_), ## args_ )\r
+\r
+void mystdio_init(void);\r
+\r
+#endif /* MYSTDIO_H */\r
--- /dev/null
+// Martin Thomas 4/2008\r
+\r
+#include <stdint.h>\r
+#include <avr/io.h>\r
+#include <util/delay.h>\r
+#include "port_ext.h"\r
+\r
+// #include "mystdio.h"\r
+\r
+static uint8_t virtports[PORT_EXT_OUTPORTS] = { \r
+ PORT_EXT_INIT0, \r
+ PORT_EXT_INIT1, \r
+ PORT_EXT_INIT2 \r
+};\r
+\r
+static inline void strobe_delay(void)\r
+{\r
+#if 0\r
+ // delay ca. 100ns @ 2V for 74x595, 1us for tests \r
+ _delay_us(1);\r
+#else\r
+ // 1 cycle ca 130ns at 7,3MHz\r
+ asm volatile("nop"::);\r
+#endif\r
+}\r
+\r
+static inline void output_disable(void)\r
+{\r
+ PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_OE );\r
+}\r
+\r
+static inline void output_enable(void)\r
+{\r
+ PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_OE );\r
+}\r
+\r
+static inline void pulse_latch(void)\r
+{\r
+ PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_LATCH );\r
+ strobe_delay();\r
+ PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_LATCH );\r
+ strobe_delay();\r
+}\r
+\r
+static inline void pulse_clock(void)\r
+{\r
+ PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_CLK );\r
+ strobe_delay();\r
+ PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_CLK );\r
+ strobe_delay();\r
+}\r
+\r
+static void shift_out(void)\r
+{\r
+ uint8_t i, bit;\r
+\r
+ // first bit shifted out is bit7 in virtports[PORT_EXT_OUTPORTS-1]\r
+ // - on BC100 this is for U205 Q7\r
+ // last bit shifted out is bit 0 in virtports[0]\r
+ // - on BC100 this is for U202 Q0\r
+ for ( i = PORT_EXT_OUTPORTS; i > 0; i-- ) {\r
+ // myprintf_P("Port %d = %d\n", i-1, virtports[i-1] );\r
+ for ( bit = 8; bit > 0; bit-- ) {\r
+ if ( virtports[i-1] & ( 1 << (bit-1) ) ) {\r
+ PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_DIN );\r
+ }\r
+ else {\r
+ PORT_EXT_PORT &= ~( 1 << PORT_EXT_PIN_DIN );\r
+ }\r
+ pulse_clock();\r
+ }\r
+ }\r
+ pulse_latch();\r
+}\r
+\r
+void port_ext_init(void) \r
+{\r
+ PORT_EXT_PORT &= ~( \r
+ ( 1 << PORT_EXT_PIN_CLK ) |\r
+ ( 1 << PORT_EXT_PIN_DIN) |\r
+ ( 1 << PORT_EXT_PIN_LATCH ) );\r
+ PORT_EXT_PORT |= ( 1 << PORT_EXT_PIN_OE );\r
+ PORT_EXT_DDR |= (\r
+ ( 1 << PORT_EXT_PIN_OE) |\r
+ ( 1 << PORT_EXT_PIN_CLK ) |\r
+ ( 1 << PORT_EXT_PIN_DIN) |\r
+ ( 1 << PORT_EXT_PIN_LATCH ) );\r
+ // set inititial values before enabling outputs\r
+ // - on BC100 this is just for U202 since it's\r
+ // the only 74x595 with switchable /OE\r
+ shift_out();\r
+ output_enable();\r
+ // since Q7' is low while output is disabled (low)\r
+ // (Philips 74HC(T)595 datasheet) another shift- \r
+ // out has to be done to set the cascaded outputs\r
+ // - on BC100 this will set U201, U202 and U205 outputs\r
+ shift_out();\r
+}\r
+\r
+void port_ext_update(void)\r
+{\r
+ shift_out();\r
+}\r
+\r
+void port_ext_bit_clear( uint8_t port, uint8_t bit )\r
+{\r
+ if ( ( port < PORT_EXT_OUTPORTS ) && ( bit < 8 ) ) {\r
+ virtports[port] &= ~( 1 << bit );\r
+ }\r
+}\r
+\r
+void port_ext_bit_set( uint8_t port, uint8_t bit )\r
+{\r
+ if ( ( port < PORT_EXT_OUTPORTS ) && ( bit < 8 ) ) {\r
+ virtports[port] |= ( 1 << bit );\r
+ }\r
+}\r
+\r
+void port_ext_set( uint8_t port, uint8_t val )\r
+{\r
+ if ( port < PORT_EXT_OUTPORTS ) {\r
+ virtports[port] = val;\r
+ }\r
+}\r
+\r
+\r
--- /dev/null
+// Martin Thomas 4/2008\r
+\r
+#ifndef PORT_EXT_H\r
+#define PORT_EXT_H\r
+\r
+#define PORT_EXT_OUTPORTS 3 /* num. of 74x595 */\r
+\r
+/* BC100 U202:\r
+ reset ATtinyx61 (Q0)\r
+ reset ATtinyx5 (Q1)\r
+ power-off = 1 = disabled (Q2)\r
+ electronic load- off (Q4)\r
+ electronic load+ off (Q6) */\r
+#define PORT_EXT_INIT0 ( (1<<0)|(1<<1)|(1<<2)|(1<<4)|(1<<6) )\r
+#define PORT_EXT_INIT1 0x00\r
+#define PORT_EXT_INIT2 0x00\r
+\r
+#define PORT_EXT_PORT PORTB\r
+#define PORT_EXT_DDR DDRB\r
+#define PORT_EXT_PIN PINB\r
+#define PORT_EXT_PIN_OE PB0 /* = /OE */\r
+#define PORT_EXT_PIN_LATCH PB1 /* = ST_CP */\r
+#define PORT_EXT_PIN_DIN PB2 /* = DS */\r
+#define PORT_EXT_PIN_CLK PB3 /* = SH_CP */\r
+\r
+void port_ext_init(void);\r
+void port_ext_update(void);\r
+void port_ext_bit_clear( uint8_t port, uint8_t bit );\r
+void port_ext_bit_set( uint8_t port, uint8_t bit );\r
+void port_ext_set( uint8_t port, uint8_t val );\r
+\r
+#endif\r
--- /dev/null
+// Martin Thomas 3/2008\r
+\r
+#include <stdint.h>\r
+#include <avr/io.h>\r
+#include <util/delay.h>\r
+\r
+#include "spi.h"\r
+\r
+void SPI_init( void )\r
+{\r
+ SPI_PORT |= (1<<SPI_MISO_BIT) | ( 1<<SPI_SS_BIT); // enable pull-up input and SS default high\r
+ SPI_PORT &= ~( (1<<SPI_SCK_BIT) | (1<<SPI_MOSI_BIT) ); // output-inits\r
+ SPI_DDR &= ~(1<<SPI_MISO_BIT);\r
+ SPI_DDR |= (1<<SPI_MOSI_BIT) | (1<<SPI_SCK_BIT) | (1<<SPI_SS_BIT); //Set MOSI, SCK AND SS as outputs\r
+ // SPSR = (1<<SPI2X);\r
+ SPCR = (1<<SPE) | (1<<MSTR) | ( 1<<SPR1) | ( 1<<SPR0 );\r
+}\r
+\r
+void SPI_release( void )\r
+{\r
+ SPCR = 0;\r
+ SPI_DDR &= ~( (1<<SPI_MOSI_BIT) | (1<<SPI_SCK_BIT) | (1<<SPI_SS_BIT ) );\r
+ SPI_PORT &= ~( (1<<SPI_MISO_BIT) | ( 1<<SPI_SS_BIT) );\r
+}\r
+\r
+uint8_t SPI_rw( uint8_t out )\r
+{\r
+ uint8_t in;\r
+\r
+ _delay_ms(1); // slow down to give slave time to process\r
+\r
+#if defined(SPDR0)\r
+ SPDR0 = out;\r
+ while( !(SPSR0 & (1<<SPIF0)) ) { ; }\r
+ in = SPDR0;\r
+#else\r
+ SPDR = out;\r
+ while( !(SPSR & (1<<SPIF)) ) { ; }\r
+ in = SPDR;\r
+#endif\r
+ return in;\r
+}\r
+\r
--- /dev/null
+// Martin Thomas 3/2008\r
+\r
+#ifndef SPI_H\r
+#define SPI_H\r
+\r
+#include <stdint.h>\r
+\r
+#if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__)\r
+#define SPI_PORT PORTB\r
+#define SPI_DDR DDRB\r
+#define SPI_PIN PINB\r
+#define SPI_SS_BIT PB4\r
+#define SPI_MOSI_BIT PB5\r
+#define SPI_MISO_BIT PB6\r
+#define SPI_SCK_BIT PB7\r
+#else\r
+#error "no SPI definitions for this device"\r
+#endif\r
+\r
+void SPI_init( void );\r
+void SPI_release( void );\r
+uint8_t SPI_rw( uint8_t output );\r
+\r
+#endif /* SPI_H */\r
+\r
--- /dev/null
+// Copyright (c) 2007, 2008 Martin Thomas - BSD-license\r
+// 10 ms timebase with \r
+// 8bit timer-counter #0 in CTC-mode on ATmega644\r
+\r
+#include <stdint.h>\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+#include "timebase.h"\r
+\r
+#include "key_io.h" /* keys callback/debouce */\r
+\r
+#define COUNTER_IS_16BIT 0\r
+#define PRESCALER 1024UL\r
+\r
+#if TIMEBASE_DELTAT_MS != 10\r
+#warning "code prepared for 10ms tick"\r
+#endif\r
+\r
+#define TIMERFREQ (1000/TIMEBASE_DELTAT_MS) /* Hz */\r
+#define OCRMATCHVAL ( (F_CPU*10/PRESCALER/TIMERFREQ+5)/10 - 1 )\r
+\r
+#if COUNTER_IS_16BIT\r
+ /* 16 bit counter */\r
+#define OCR_MATCH_MAX 0xfffe\r
+#else\r
+/* 8 bit counter */\r
+#define OCR_MATCH_MAX 0xfe\r
+#endif /* COUNTER_IS_16BIT */\r
+#define OCR_MATCH_MIN 0x02\r
+\r
+#if ( OCRMATCHVAL > OCR_MATCH_MAX )\r
+#error "PRESCALER too small or F_CPU too high"\r
+#endif\r
+#if ( OCRMATCHVAL < 2 )\r
+#error "PRESCALER too large or F_CPU too low"\r
+#endif\r
+\r
+volatile uint16_t timebase_tick;\r
+\r
+ISR(TIMER0_COMPA_vect)\r
+{\r
+ timebase_tick++;\r
+\r
+ key_io_callback();\r
+}\r
+\r
+void timebase_init(void)\r
+{\r
+ uint8_t sreg;\r
+\r
+ sreg=SREG;\r
+ cli();\r
+\r
+ // init Timer 0 Mode 4 - CTC with interrupt on compare-match \r
+ \r
+ TCCR0A = (1<<WGM01);\r
+#if (PRESCALER == 1024)\r
+ TCCR0B = (1<<CS02) | (1<<CS00);\r
+#else\r
+#error "PRESCALER settings not available"\r
+#endif\r
+ \r
+ OCR0A = OCRMATCHVAL; // match-value\r
+ \r
+ TCNT0 = 0; // reset timer-counter\r
+ TIFR0 = (1<<OCF0A); // clear interrupt\r
+ TIMSK0 = (1<<OCIE0A); // enabled matchA interrupt\r
+\r
+ timebase_tick = 0;\r
+\r
+ SREG=sreg;\r
+}\r
+\r
+uint16_t timebase_get_tick(void)\r
+{\r
+ uint8_t sreg;\r
+ uint16_t res;\r
+\r
+ sreg = SREG;\r
+ cli();\r
+\r
+ res = timebase_tick;\r
+\r
+ SREG=sreg;\r
+\r
+ return res;\r
+}\r
--- /dev/null
+#ifndef TIMEBASE_H_\r
+#define TIMEBASE_H_\r
+\r
+#include <stdint.h>\r
+\r
+#define TIMEBASE_DELTAT_MS 10 /* ms */\r
+\r
+void timebase_init(void);\r
+uint16_t timebase_get_tick(void);\r
+\r
+#endif\r
--- /dev/null
+/*************************************************************************\r
+Title: Interrupt UART library with receive/transmit circular buffers\r
+Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury\r
+File: $Id: uart.c,v 1.5.2.10 2005/11/15 19:49:12 peter Exp $\r
+Software: AVR-GCC 3.3 \r
+Hardware: any AVR with built-in UART, \r
+ tested on AT90S8515 at 4 Mhz and ATmega at 1Mhz\r
+\r
+DESCRIPTION:\r
+ An interrupt is generated when the UART has finished transmitting or\r
+ receiving a byte. The interrupt handling routines use circular buffers\r
+ for buffering received and transmitted data.\r
+ \r
+ The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define\r
+ the buffer size in bytes. Note that these variables must be a \r
+ power of 2.\r
+ \r
+USAGE:\r
+ Refere to the header file uart.h for a description of the routines. \r
+ See also example test_uart.c.\r
+\r
+NOTES:\r
+ Based on Atmel Application Note AVR306\r
+ \r
+*************************************************************************/\r
+#include <avr/io.h>\r
+#include <avr/interrupt.h>\r
+// #include <avr/signal.h>\r
+#include <avr/pgmspace.h>\r
+#include "uart.h"\r
+\r
+\r
+/*\r
+ * constants and macros\r
+ */\r
+\r
+/* size of RX/TX buffers */\r
+#define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1)\r
+#define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1)\r
+\r
+#if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK )\r
+#error RX buffer size is not a power of 2\r
+#endif\r
+#if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK )\r
+#error TX buffer size is not a power of 2\r
+#endif\r
+\r
+#if defined(__AVR_AT90S2313__) \\r
+ || defined(__AVR_AT90S4414__) || defined(__AVR_AT90S4434__) \\r
+ || defined(__AVR_AT90S8515__) || defined(__AVR_AT90S8535__) \\r
+ || defined(__AVR_ATmega103__)\r
+ /* old AVR classic or ATmega103 with one UART */\r
+ #define AT90_UART\r
+ #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV\r
+ #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA\r
+ #define UART0_STATUS USR\r
+ #define UART0_CONTROL UCR\r
+ #define UART0_DATA UDR \r
+ #define UART0_UDRIE UDRIE\r
+#elif defined(__AVR_AT90S2333__) || defined(__AVR_AT90S4433__)\r
+ /* old AVR classic with one UART */\r
+ #define AT90_UART\r
+ #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV\r
+ #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA\r
+ #define UART0_STATUS UCSRA\r
+ #define UART0_CONTROL UCSRB\r
+ #define UART0_DATA UDR \r
+ #define UART0_UDRIE UDRIE\r
+#elif defined(__AVR_ATmega8__) || defined(__AVR_ATmega16__) || defined(__AVR_ATmega32__) \\r
+ || defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) \\r
+ || defined(__AVR_ATmega323__)\r
+ /* ATmega with one USART */\r
+ #define ATMEGA_USART\r
+ #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV\r
+ #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA\r
+ #define UART0_STATUS UCSRA\r
+ #define UART0_CONTROL UCSRB\r
+ #define UART0_DATA UDR\r
+ #define UART0_UDRIE UDRIE\r
+#elif defined(__AVR_ATmega163__) \r
+ /* ATmega163 with one UART */\r
+ #define ATMEGA_UART\r
+ #define UART0_RECEIVE_INTERRUPT SIG_UART_RECV\r
+ #define UART0_TRANSMIT_INTERRUPT SIG_UART_DATA\r
+ #define UART0_STATUS UCSRA\r
+ #define UART0_CONTROL UCSRB\r
+ #define UART0_DATA UDR\r
+ #define UART0_UDRIE UDRIE\r
+#elif defined(__AVR_ATmega162__)\r
+ /* ATmega with two USART */\r
+ #define ATMEGA_USART0\r
+ #define ATMEGA_USART1\r
+ #define UART0_RECEIVE_INTERRUPT SIG_USART0_RECV\r
+ #define UART1_RECEIVE_INTERRUPT SIG_USART1_RECV\r
+ #define UART0_TRANSMIT_INTERRUPT SIG_USART0_DATA\r
+ #define UART1_TRANSMIT_INTERRUPT SIG_USART1_DATA\r
+ #define UART0_STATUS UCSR0A\r
+ #define UART0_CONTROL UCSR0B\r
+ #define UART0_DATA UDR0\r
+ #define UART0_UDRIE UDRIE0\r
+ #define UART1_STATUS UCSR1A\r
+ #define UART1_CONTROL UCSR1B\r
+ #define UART1_DATA UDR1\r
+ #define UART1_UDRIE UDRIE1\r
+#elif defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) \r
+ /* ATmega with two USART */\r
+ #define ATMEGA_USART0\r
+ #define ATMEGA_USART1\r
+ #define UART0_RECEIVE_INTERRUPT SIG_UART0_RECV\r
+ #define UART1_RECEIVE_INTERRUPT SIG_UART1_RECV\r
+ #define UART0_TRANSMIT_INTERRUPT SIG_UART0_DATA\r
+ #define UART1_TRANSMIT_INTERRUPT SIG_UART1_DATA\r
+ #define UART0_STATUS UCSR0A\r
+ #define UART0_CONTROL UCSR0B\r
+ #define UART0_DATA UDR0\r
+ #define UART0_UDRIE UDRIE0\r
+ #define UART1_STATUS UCSR1A\r
+ #define UART1_CONTROL UCSR1B\r
+ #define UART1_DATA UDR1\r
+ #define UART1_UDRIE UDRIE1\r
+#elif defined(__AVR_ATmega161__)\r
+ /* ATmega with UART */\r
+ #error "AVR ATmega161 currently not supported by this libaray !"\r
+#elif defined(__AVR_ATmega169__) \r
+ /* ATmega with one USART */\r
+ #define ATMEGA_USART\r
+ #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV\r
+ #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA\r
+ #define UART0_STATUS UCSRA\r
+ #define UART0_CONTROL UCSRB\r
+ #define UART0_DATA UDR\r
+ #define UART0_UDRIE UDRIE\r
+#elif defined(__AVR_ATmega48__) ||defined(__AVR_ATmega88__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega644__)\r
+ #define ATMEGA_USART0\r
+ #define UART0_RECEIVE_INTERRUPT SIG_USART_RECV\r
+ #define UART0_TRANSMIT_INTERRUPT SIG_USART_DATA\r
+ #define UART0_STATUS UCSR0A\r
+ #define UART0_CONTROL UCSR0B\r
+ #define UART0_DATA UDR0\r
+ #define UART0_UDRIE UDRIE0\r
+#elif defined(__AVR_ATtiny2313__)\r
+ #define ATMEGA_USART\r
+ #define UART0_RECEIVE_INTERRUPT SIG_USART0_RX \r
+ #define UART0_TRANSMIT_INTERRUPT SIG_USART0_UDRE\r
+ #define UART0_STATUS UCSRA\r
+ #define UART0_CONTROL UCSRB\r
+ #define UART0_DATA UDR\r
+ #define UART0_UDRIE UDRIE\r
+#else\r
+ #error "no UART definition for MCU available"\r
+#endif\r
+\r
+\r
+/*\r
+ * module global variables\r
+ */\r
+static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE];\r
+static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE];\r
+static volatile unsigned char UART_TxHead;\r
+static volatile unsigned char UART_TxTail;\r
+static volatile unsigned char UART_RxHead;\r
+static volatile unsigned char UART_RxTail;\r
+static volatile unsigned char UART_LastRxError;\r
+\r
+#if defined( ATMEGA_USART1 )\r
+static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE];\r
+static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE];\r
+static volatile unsigned char UART1_TxHead;\r
+static volatile unsigned char UART1_TxTail;\r
+static volatile unsigned char UART1_RxHead;\r
+static volatile unsigned char UART1_RxTail;\r
+static volatile unsigned char UART1_LastRxError;\r
+#endif\r
+\r
+\r
+\r
+SIGNAL(UART0_RECEIVE_INTERRUPT)\r
+/*************************************************************************\r
+Function: UART Receive Complete interrupt\r
+Purpose: called when the UART has received a character\r
+**************************************************************************/\r
+{\r
+ unsigned char tmphead;\r
+ unsigned char data;\r
+ unsigned char usr;\r
+ unsigned char lastRxError;\r
+ \r
+ \r
+ /* read UART status register and UART data register */ \r
+ usr = UART0_STATUS;\r
+ data = UART0_DATA;\r
+ \r
+ /* */\r
+#if defined( AT90_UART )\r
+ lastRxError = (usr & (_BV(FE)|_BV(DOR)) );\r
+#elif defined( ATMEGA_USART )\r
+ lastRxError = (usr & (_BV(FE)|_BV(DOR)) );\r
+#elif defined( ATMEGA_USART0 )\r
+ lastRxError = (usr & (_BV(FE0)|_BV(DOR0)) );\r
+#elif defined ( ATMEGA_UART )\r
+ lastRxError = (usr & (_BV(FE)|_BV(DOR)) );\r
+#endif\r
+ \r
+ /* calculate buffer index */ \r
+ tmphead = ( UART_RxHead + 1) & UART_RX_BUFFER_MASK;\r
+ \r
+ if ( tmphead == UART_RxTail ) {\r
+ /* error: receive buffer overflow */\r
+ lastRxError = UART_BUFFER_OVERFLOW >> 8;\r
+ }else{\r
+ /* store new index */\r
+ UART_RxHead = tmphead;\r
+ /* store received data in buffer */\r
+ UART_RxBuf[tmphead] = data;\r
+ }\r
+ UART_LastRxError = lastRxError; \r
+}\r
+\r
+\r
+SIGNAL(UART0_TRANSMIT_INTERRUPT)\r
+/*************************************************************************\r
+Function: UART Data Register Empty interrupt\r
+Purpose: called when the UART is ready to transmit the next byte\r
+**************************************************************************/\r
+{\r
+ unsigned char tmptail;\r
+\r
+ \r
+ if ( UART_TxHead != UART_TxTail) {\r
+ /* calculate and store new buffer index */\r
+ tmptail = (UART_TxTail + 1) & UART_TX_BUFFER_MASK;\r
+ UART_TxTail = tmptail;\r
+ /* get one byte from buffer and write it to UART */\r
+ UART0_DATA = UART_TxBuf[tmptail]; /* start transmission */\r
+ }else{\r
+ /* tx buffer empty, disable UDRE interrupt */\r
+ UART0_CONTROL &= ~_BV(UART0_UDRIE);\r
+ }\r
+}\r
+\r
+\r
+/*************************************************************************\r
+Function: uart_init()\r
+Purpose: initialize UART and set baudrate\r
+Input: baudrate using macro UART_BAUD_SELECT()\r
+Returns: none\r
+**************************************************************************/\r
+void uart_init(unsigned int baudrate)\r
+{\r
+ UART_TxHead = 0;\r
+ UART_TxTail = 0;\r
+ UART_RxHead = 0;\r
+ UART_RxTail = 0;\r
+ \r
+#if defined( AT90_UART )\r
+ /* set baud rate */\r
+ UBRR = (unsigned char)baudrate; \r
+\r
+ /* enable UART receiver and transmmitter and receive complete interrupt */\r
+ UART0_CONTROL = _BV(RXCIE)|_BV(RXEN)|_BV(TXEN);\r
+\r
+#elif defined (ATMEGA_USART)\r
+ /* Set baud rate */\r
+ if ( baudrate & 0x8000 )\r
+ {\r
+ UART0_STATUS = (1<<U2X); //Enable 2x speed \r
+ baudrate &= ~0x8000;\r
+ }\r
+ UBRRH = (unsigned char)(baudrate>>8);\r
+ UBRRL = (unsigned char) baudrate;\r
+ \r
+ /* Enable USART receiver and transmitter and receive complete interrupt */\r
+ UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);\r
+ \r
+ /* Set frame format: asynchronous, 8data, no parity, 1stop bit */\r
+ #ifdef URSEL\r
+ UCSRC = (1<<URSEL)|(3<<UCSZ0);\r
+ #else\r
+ UCSRC = (3<<UCSZ0);\r
+ #endif \r
+ \r
+#elif defined (ATMEGA_USART0 )\r
+ /* Set baud rate */\r
+ if ( baudrate & 0x8000 ) \r
+ {\r
+ UART0_STATUS = (1<<U2X0); //Enable 2x speed \r
+ baudrate &= ~0x8000;\r
+ }\r
+ UBRR0H = (unsigned char)(baudrate>>8);\r
+ UBRR0L = (unsigned char) baudrate;\r
+\r
+ /* Enable USART receiver and transmitter and receive complete interrupt */\r
+ UART0_CONTROL = _BV(RXCIE0)|(1<<RXEN0)|(1<<TXEN0);\r
+ \r
+ /* Set frame format: asynchronous, 8data, no parity, 1stop bit */\r
+ #ifdef URSEL0\r
+ UCSR0C = (1<<URSEL0)|(3<<UCSZ00);\r
+ #else\r
+ UCSR0C = (3<<UCSZ00);\r
+ #endif \r
+\r
+#elif defined ( ATMEGA_UART )\r
+ /* set baud rate */\r
+ if ( baudrate & 0x8000 ) \r
+ {\r
+ UART0_STATUS = (1<<U2X); //Enable 2x speed \r
+ baudrate &= ~0x8000;\r
+ }\r
+ UBRRHI = (unsigned char)(baudrate>>8);\r
+ UBRR = (unsigned char) baudrate;\r
+\r
+ /* Enable UART receiver and transmitter and receive complete interrupt */\r
+ UART0_CONTROL = _BV(RXCIE)|(1<<RXEN)|(1<<TXEN);\r
+\r
+#endif\r
+\r
+}/* uart_init */\r
+\r
+\r
+/*************************************************************************\r
+Function: uart_getc()\r
+Purpose: return byte from ringbuffer \r
+Returns: lower byte: received byte from ringbuffer\r
+ higher byte: last receive error\r
+**************************************************************************/\r
+unsigned int uart_getc(void)\r
+{ \r
+ unsigned char tmptail;\r
+ unsigned char data;\r
+\r
+\r
+ if ( UART_RxHead == UART_RxTail ) {\r
+ return UART_NO_DATA; /* no data available */\r
+ }\r
+ \r
+ /* calculate /store buffer index */\r
+ tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK;\r
+ UART_RxTail = tmptail; \r
+ \r
+ /* get data from receive buffer */\r
+ data = UART_RxBuf[tmptail];\r
+ \r
+ return (UART_LastRxError << 8) + data;\r
+\r
+}/* uart_getc */\r
+\r
+\r
+/*************************************************************************\r
+Function: uart_putc()\r
+Purpose: write byte to ringbuffer for transmitting via UART\r
+Input: byte to be transmitted\r
+Returns: none \r
+**************************************************************************/\r
+void uart_putc(unsigned char data)\r
+{\r
+ unsigned char tmphead;\r
+\r
+ \r
+ tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK;\r
+ \r
+ while ( tmphead == UART_TxTail ){\r
+ ;/* wait for free space in buffer */\r
+ }\r
+ \r
+ UART_TxBuf[tmphead] = data;\r
+ UART_TxHead = tmphead;\r
+\r
+ /* enable UDRE interrupt */\r
+ UART0_CONTROL |= _BV(UART0_UDRIE);\r
+\r
+}/* uart_putc */\r
+\r
+\r
+/*************************************************************************\r
+Function: uart_puts()\r
+Purpose: transmit string to UART\r
+Input: string to be transmitted\r
+Returns: none \r
+**************************************************************************/\r
+void uart_puts(const char *s )\r
+{\r
+ while (*s) \r
+ uart_putc(*s++);\r
+\r
+}/* uart_puts */\r
+\r
+\r
+/*************************************************************************\r
+Function: uart_puts_p()\r
+Purpose: transmit string from program memory to UART\r
+Input: program memory string to be transmitted\r
+Returns: none\r
+**************************************************************************/\r
+void uart_puts_p(const char *progmem_s )\r
+{\r
+ register char c;\r
+ \r
+ while ( (c = pgm_read_byte(progmem_s++)) ) \r
+ uart_putc(c);\r
+\r
+}/* uart_puts_p */\r
+\r
+\r
+/*\r
+ * these functions are only for ATmegas with two USART\r
+ */\r
+#if defined( ATMEGA_USART1 )\r
+\r
+SIGNAL(UART1_RECEIVE_INTERRUPT)\r
+/*************************************************************************\r
+Function: UART1 Receive Complete interrupt\r
+Purpose: called when the UART1 has received a character\r
+**************************************************************************/\r
+{\r
+ unsigned char tmphead;\r
+ unsigned char data;\r
+ unsigned char usr;\r
+ unsigned char lastRxError;\r
+ \r
+ \r
+ /* read UART status register and UART data register */ \r
+ usr = UART1_STATUS;\r
+ data = UART1_DATA;\r
+ \r
+ /* */\r
+ lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) );\r
+ \r
+ /* calculate buffer index */ \r
+ tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK;\r
+ \r
+ if ( tmphead == UART1_RxTail ) {\r
+ /* error: receive buffer overflow */\r
+ lastRxError = UART_BUFFER_OVERFLOW >> 8;\r
+ }else{\r
+ /* store new index */\r
+ UART1_RxHead = tmphead;\r
+ /* store received data in buffer */\r
+ UART1_RxBuf[tmphead] = data;\r
+ }\r
+ UART1_LastRxError = lastRxError; \r
+}\r
+\r
+\r
+SIGNAL(UART1_TRANSMIT_INTERRUPT)\r
+/*************************************************************************\r
+Function: UART1 Data Register Empty interrupt\r
+Purpose: called when the UART1 is ready to transmit the next byte\r
+**************************************************************************/\r
+{\r
+ unsigned char tmptail;\r
+\r
+ \r
+ if ( UART1_TxHead != UART1_TxTail) {\r
+ /* calculate and store new buffer index */\r
+ tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK;\r
+ UART1_TxTail = tmptail;\r
+ /* get one byte from buffer and write it to UART */\r
+ UART1_DATA = UART1_TxBuf[tmptail]; /* start transmission */\r
+ }else{\r
+ /* tx buffer empty, disable UDRE interrupt */\r
+ UART1_CONTROL &= ~_BV(UART1_UDRIE);\r
+ }\r
+}\r
+\r
+\r
+/*************************************************************************\r
+Function: uart1_init()\r
+Purpose: initialize UART1 and set baudrate\r
+Input: baudrate using macro UART_BAUD_SELECT()\r
+Returns: none\r
+**************************************************************************/\r
+void uart1_init(unsigned int baudrate)\r
+{\r
+ UART1_TxHead = 0;\r
+ UART1_TxTail = 0;\r
+ UART1_RxHead = 0;\r
+ UART1_RxTail = 0;\r
+ \r
+\r
+ /* Set baud rate */\r
+ if ( baudrate & 0x8000 ) \r
+ {\r
+ UART1_STATUS = (1<<U2X1); //Enable 2x speed \r
+ baudrate &= ~0x8000;\r
+ }\r
+ UBRR1H = (unsigned char)(baudrate>>8);\r
+ UBRR1L = (unsigned char) baudrate;\r
+\r
+ /* Enable USART receiver and transmitter and receive complete interrupt */\r
+ UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1);\r
+ \r
+ /* Set frame format: asynchronous, 8data, no parity, 1stop bit */ \r
+ #ifdef URSEL1\r
+ UCSR1C = (1<<URSEL1)|(3<<UCSZ10);\r
+ #else\r
+ UCSR1C = (3<<UCSZ10);\r
+ #endif \r
+}/* uart_init */\r
+\r
+\r
+/*************************************************************************\r
+Function: uart1_getc()\r
+Purpose: return byte from ringbuffer \r
+Returns: lower byte: received byte from ringbuffer\r
+ higher byte: last receive error\r
+**************************************************************************/\r
+unsigned int uart1_getc(void)\r
+{ \r
+ unsigned char tmptail;\r
+ unsigned char data;\r
+\r
+\r
+ if ( UART1_RxHead == UART1_RxTail ) {\r
+ return UART_NO_DATA; /* no data available */\r
+ }\r
+ \r
+ /* calculate /store buffer index */\r
+ tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK;\r
+ UART1_RxTail = tmptail; \r
+ \r
+ /* get data from receive buffer */\r
+ data = UART1_RxBuf[tmptail];\r
+ \r
+ return (UART1_LastRxError << 8) + data;\r
+\r
+}/* uart1_getc */\r
+\r
+\r
+/*************************************************************************\r
+Function: uart1_putc()\r
+Purpose: write byte to ringbuffer for transmitting via UART\r
+Input: byte to be transmitted\r
+Returns: none \r
+**************************************************************************/\r
+void uart1_putc(unsigned char data)\r
+{\r
+ unsigned char tmphead;\r
+\r
+ \r
+ tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK;\r
+ \r
+ while ( tmphead == UART1_TxTail ){\r
+ ;/* wait for free space in buffer */\r
+ }\r
+ \r
+ UART1_TxBuf[tmphead] = data;\r
+ UART1_TxHead = tmphead;\r
+\r
+ /* enable UDRE interrupt */\r
+ UART1_CONTROL |= _BV(UART1_UDRIE);\r
+\r
+}/* uart1_putc */\r
+\r
+\r
+/*************************************************************************\r
+Function: uart1_puts()\r
+Purpose: transmit string to UART1\r
+Input: string to be transmitted\r
+Returns: none \r
+**************************************************************************/\r
+void uart1_puts(const char *s )\r
+{\r
+ while (*s) \r
+ uart1_putc(*s++);\r
+\r
+}/* uart1_puts */\r
+\r
+\r
+/*************************************************************************\r
+Function: uart1_puts_p()\r
+Purpose: transmit string from program memory to UART1\r
+Input: program memory string to be transmitted\r
+Returns: none\r
+**************************************************************************/\r
+void uart1_puts_p(const char *progmem_s )\r
+{\r
+ register char c;\r
+ \r
+ while ( (c = pgm_read_byte(progmem_s++)) ) \r
+ uart1_putc(c);\r
+\r
+}/* uart1_puts_p */\r
+\r
+\r
+#endif\r
--- /dev/null
+#ifndef UART_H\r
+#define UART_H\r
+/************************************************************************\r
+Title: Interrupt UART library with receive/transmit circular buffers\r
+Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury\r
+File: $Id: uart.h,v 1.7.2.5 2005/08/14 11:25:41 Peter Exp $\r
+Software: AVR-GCC 3.3\r
+Hardware: any AVR with built-in UART, tested on AT90S8515 at 4 Mhz\r
+Usage: see Doxygen manual\r
+************************************************************************/\r
+\r
+/** \r
+ * @defgroup pfleury_uart UART Library\r
+ * @code #include <uart.h> @endcode\r
+ * \r
+ * @brief Interrupt UART library using the built-in UART with transmit and receive circular buffers. \r
+ *\r
+ * This library can be used to transmit and receive data through the built in UART. \r
+ *\r
+ * An interrupt is generated when the UART has finished transmitting or\r
+ * receiving a byte. The interrupt handling routines use circular buffers\r
+ * for buffering received and transmitted data.\r
+ *\r
+ * The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define\r
+ * the size of the circular buffers in bytes. Note that these constants must be a power of 2.\r
+ * You may need to adapt this constants to your target and your application by adding \r
+ * CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_RX_BUFFER_SIZE=nn to your Makefile.\r
+ *\r
+ * @note Based on Atmel Application Note AVR306\r
+ * @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury\r
+ */\r
+ \r
+/**@{*/\r
+\r
+\r
+#if (__GNUC__ * 100 + __GNUC_MINOR__) < 304\r
+#error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !"\r
+#endif\r
+\r
+\r
+/*\r
+** constants and macros\r
+*/\r
+\r
+/** @brief UART Baudrate Expression\r
+ * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz \r
+ * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 \r
+ */\r
+#define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1)\r
+\r
+/** @brief UART Baudrate Expression for ATmega double speed mode\r
+ * @param xtalcpu system clock in Mhz, e.g. 4000000L for 4Mhz \r
+ * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 \r
+ */\r
+#define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) (((xtalCpu)/((baudRate)*8l)-1)|0x8000)\r
+\r
+\r
+/** Size of the circular receive buffer, must be power of 2 */\r
+#ifndef UART_RX_BUFFER_SIZE\r
+#define UART_RX_BUFFER_SIZE 32\r
+#endif\r
+/** Size of the circular transmit buffer, must be power of 2 */\r
+#ifndef UART_TX_BUFFER_SIZE\r
+#define UART_TX_BUFFER_SIZE 32\r
+#endif\r
+\r
+/* test if the size of the circular buffers fits into SRAM */\r
+#if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) )\r
+#error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM"\r
+#endif\r
+\r
+/* \r
+** high byte error return code of uart_getc()\r
+*/\r
+#define UART_FRAME_ERROR 0x0800 /* Framing Error by UART */\r
+#define UART_OVERRUN_ERROR 0x0400 /* Overrun condition by UART */\r
+#define UART_BUFFER_OVERFLOW 0x0200 /* receive ringbuffer overflow */\r
+#define UART_NO_DATA 0x0100 /* no receive data available */\r
+\r
+\r
+/*\r
+** function prototypes\r
+*/\r
+\r
+/**\r
+ @brief Initialize UART and set baudrate \r
+ @param baudrate Specify baudrate using macro UART_BAUD_SELECT()\r
+ @return none\r
+*/\r
+extern void uart_init(unsigned int baudrate);\r
+\r
+\r
+/**\r
+ * @brief Get received byte from ringbuffer\r
+ *\r
+ * Returns in the lower byte the received character and in the \r
+ * higher byte the last receive error.\r
+ * UART_NO_DATA is returned when no data is available.\r
+ *\r
+ * @param void\r
+ * @return lower byte: received byte from ringbuffer\r
+ * @return higher byte: last receive status\r
+ * - \b 0 successfully received data from UART\r
+ * - \b UART_NO_DATA \r
+ * <br>no receive data available\r
+ * - \b UART_BUFFER_OVERFLOW \r
+ * <br>Receive ringbuffer overflow.\r
+ * We are not reading the receive buffer fast enough, \r
+ * one or more received character have been dropped \r
+ * - \b UART_OVERRUN_ERROR \r
+ * <br>Overrun condition by UART.\r
+ * A character already present in the UART UDR register was \r
+ * not read by the interrupt handler before the next character arrived,\r
+ * one or more received characters have been dropped.\r
+ * - \b UART_FRAME_ERROR \r
+ * <br>Framing Error by UART\r
+ */\r
+extern unsigned int uart_getc(void);\r
+\r
+\r
+/**\r
+ * @brief Put byte to ringbuffer for transmitting via UART\r
+ * @param data byte to be transmitted\r
+ * @return none\r
+ */\r
+extern void uart_putc(unsigned char data);\r
+\r
+\r
+/**\r
+ * @brief Put string to ringbuffer for transmitting via UART\r
+ *\r
+ * The string is buffered by the uart library in a circular buffer\r
+ * and one character at a time is transmitted to the UART using interrupts.\r
+ * Blocks if it can not write the whole string into the circular buffer.\r
+ * \r
+ * @param s string to be transmitted\r
+ * @return none\r
+ */\r
+extern void uart_puts(const char *s );\r
+\r
+\r
+/**\r
+ * @brief Put string from program memory to ringbuffer for transmitting via UART.\r
+ *\r
+ * The string is buffered by the uart library in a circular buffer\r
+ * and one character at a time is transmitted to the UART using interrupts.\r
+ * Blocks if it can not write the whole string into the circular buffer.\r
+ *\r
+ * @param s program memory string to be transmitted\r
+ * @return none\r
+ * @see uart_puts_P\r
+ */\r
+extern void uart_puts_p(const char *s );\r
+\r
+/**\r
+ * @brief Macro to automatically put a string constant into program memory\r
+ */\r
+#define uart_puts_P(__s) uart_puts_p(PSTR(__s))\r
+\r
+\r
+\r
+/** @brief Initialize USART1 (only available on selected ATmegas) @see uart_init */\r
+extern void uart1_init(unsigned int baudrate);\r
+/** @brief Get received byte of USART1 from ringbuffer. (only available on selected ATmega) @see uart_getc */\r
+extern unsigned int uart1_getc(void);\r
+/** @brief Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_putc */\r
+extern void uart1_putc(unsigned char data);\r
+/** @brief Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts */\r
+extern void uart1_puts(const char *s );\r
+/** @brief Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts_p */\r
+extern void uart1_puts_p(const char *s );\r
+/** @brief Macro to automatically put a string constant into program memory */\r
+#define uart1_puts_P(__s) uart1_puts_p(PSTR(__s))\r
+\r
+/**@}*/\r
+\r
+#endif // UART_H \r
+\r
+++ /dev/null
-2008-03-30 Kevin Rosenberg <kevin@rosenberg.net>\r
- * GCC Makefile's improved with more listing output as well as\r
- added -Wl,-gc-sections option which stops crashes using linker\r
- relaxation [thanks to Eric Weddington]\r
-\r
-2008-03-28 Kevin Rosenberg <kevin@rosenberg.net>\r
- * BaseTinyFirmware/GCC/avr463/Makefile: Added -Wl,-relax to linker\r
- flags. On my system this crashes avr-ld.exe, but others have reported\r
- a large reduction in firmware size with this option. I added this\r
- option for others to try.\r
- * BaseTinyFirmware/GCC/avr458/Makefile: Added missing file\r
- \r
-2008-03-14 Martin Thomas <mthomas@rhrk.uni-kl.de>\r
- * added "volatile" to structure object and array declarations for\r
- objects sed in main-thread and ISRs. I'm not sure about the\r
- current state of implicitly "guaranteed" accesses in (avr-)gcc but\r
- it should be a "better safe than sorry" extension.\r
- * enveloped access to timer-values in timer.c to make them\r
- "atomic" since they are unsigned long\r
- * "atomic" access to singned int and unsigned int members of ADCS\r
- * it maybe better to have one place to globally enable\r
- interrupts ("sei"). Done in "initialize" now and not several\r
- times in the driver init-functions.\r
- * changed some space to tab as in the original code\r
- * added header files to the AVR-Studio project workspace\r
- * added -lm to the linker-options in the AVR Studio gcc-plugin,\r
- not important for the basic application but might be good if\r
- someone uses the ode as a base for own developments\r
-\r
-2008-03-12 Kevin Rosenberg <kevin@rosenberg.net>\r
- * Initial GCC port performed and compiles without error\r
- * Warning: Not yet tested on BC100 hardware!\r
* AVR463: Charging NiMH Batteries with BC100\r
*\r
* \par Documentation\r
- * For comprehensive code documentation, supported compilers, compiler \r
+ * For comprehensive code documentation, supported compilers, compiler\r
* settings and supported devices see readme.html\r
*\r
* \author\r
* Atmel Corporation: http://www.atmel.com \n\r
* Support email: avr@atmel.com\r
*\r
- * \r
+ *\r
* $Name$\r
* $Revision: 2299 $\r
* $RCSfile$\r
{\r
// Clear OC1B on compare match, enable PWM on comparator OCR1B.\r
TCCR1A = (1<<COM1B1)|(0<<COM1B0)|(1<<PWM1B);\r
- \r
+\r
// Non-inverted PWM, T/C stopped.\r
TCCR1B = 0;\r
- \r
+\r
// Copy shadow bits, disconnect OC1D.\r
TCCR1C = (TCCR1A & 0xF0);\r
- \r
+\r
// No fault protection, use phase & frequency correct PWM.\r
TCCR1D = (0<<WGM11)|(1<WGM10);\r
- \r
+\r
// Does not matter -- PWM6 mode not used.\r
TCCR1E = 0;\r
- \r
+\r
// Does not matter -- OC1A is disabled.\r
OCR1A = 0;\r
- \r
+\r
// Set reset compare level. (Offset is used, or JumperCheck() will fail.)\r
OCR1B = PWM_OFFSET;\r
- \r
+\r
// TOP value for PWM, f(PWM) = 64MHz / 255 = 251kHz.\r
OCR1C = 0xFF;\r
- \r
+\r
// Does not matter -- OC1D is disabled.\r
OCR1D = 0;\r
- \r
+\r
// No dead time values.\r
DT1 = 0;\r
- \r
+\r
// Set PWM port pin to output.\r
DDRB |= (1<<PB3);\r
- \r
+\r
// Enable PLL, use full speed mode.\r
PLLCSR = (0<<LSM) | (1<<PLLE);\r
- \r
+\r
// Use general timer and wait 1 ms for PLL lock to settle.\r
Time_Set(TIMER_GEN,0,0,1);\r
- do{ \r
+ do{\r
}while(Time_Left(TIMER_GEN));\r
- \r
+\r
// Now wait for PLL to lock.\r
- do{ \r
+ do{\r
}while((PLLCSR & (1<<PLOCK)) == 0);\r
\r
// Use PLL as clock source.\r
PLLCSR |= (1<<PCKE);\r
- \r
+\r
// CLK PCK = 64MHz / 1 = 64MHz.\r
TCCR1B |= (0<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);\r
}\r
* \retval TRUE Success, duty cycle could be decremented.\r
* \retval FALSE Failure, duty cycle already at zero.\r
*/\r
-unsigned char PWM_DecrementDutyCycle(void){\r
- \r
- if (OCR1B > 0) {\r
+unsigned char PWM_DecrementDutyCycle(void) {\r
+\r
+ if (OCR1B > 0) {\r
OCR1B -= 1;\r
return(TRUE);\r
} else {\r
\r
## Compile options common for all C compilation units.\r
CFLAGS = $(COMMON)\r
-CFLAGS += -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ffunction-sections\r
+CFLAGS += -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums\r
CFLAGS += -Wall -Wstrict-prototypes -Wundef -Wa,-adhlns=./$(*F).lst\r
CFLAGS += -MMD -MP -MF dep/$(@F).d \r
CFLAGS += -DLIION\r
\r
## Linker flags\r
LDFLAGS = $(COMMON)\r
-LDFLAGS += -Wl,-Map=$(PROJECT).map,--cref -Wl,-gc-sections -Wl,-relax\r
+LDFLAGS += -Wl,-Map=$(PROJECT).map,--cref -Wl,-relax\r
\r
## Intel Hex file production flags\r
HEX_FLASH_FLAGS = -R .eeprom\r
* AVR463: Charging NiMH Batteries with BC100\r
*\r
* \par Documentation\r
- * For comprehensive code documentation, supported compilers, compiler \r
+ * For comprehensive code documentation, supported compilers, compiler\r
* settings and supported devices see readme.html\r
*\r
* \author\r
* Atmel Corporation: http://www.atmel.com \n\r
* Support email: avr@atmel.com\r
*\r
- * \r
+ *\r
* $Name$\r
* $Revision: 2299 $\r
* $RCSfile$\r
//! \note See menu.h for definitions of states.\r
unsigned char ErrorState;\r
\r
+//! \brief Set to 1 by the watchdog-timeout-ISR\r
+//! \note added by Martin Thomas\r
+volatile unsigned char WatchdogFlag;\r
\r
//******************************************************************************\r
// Functions\r
\r
// Disable interrupts while setting prescaler.\r
cli();\r
- \r
+\r
CLKPR = (1<<CLKPCE); // Enable CLKPS bit modification.\r
CLKPR = 0; // Set prescaler 1 => 8 MHz clock frequency.\r
- \r
+\r
// Init 1-Wire(R) interface.\r
OWI_Init(OWIBUS);\r
- \r
+\r
// Clear on-chip EEPROM.\r
- for (page = 0; page < 4; page++) {\r
+ for (page = 0; page < 4; page++) {\r
for (i = 0; i < 32; i++) {\r
- eeprom_write_byte(&BattEEPROM[page][i], 0);\r
+ // mthomas: avoid unneeded writes\r
+ if ( eeprom_read_byte( &BattEEPROM[page][i] ) != 0 ) {\r
+ eeprom_write_byte( &BattEEPROM[page][i], 0 );\r
+ }\r
}\r
}\r
\r
}\r
\r
DisableBatteries();\r
- \r
+\r
BattActive = 0; // We have to start somewhere..\r
ErrorFlags = 0;\r
- \r
+\r
// Init complete! Go to ST_BATCON next.\r
return(ST_BATCON);\r
}\r
unsigned char BatteryControl(unsigned char inp)\r
{\r
unsigned char i;\r
- \r
+\r
// Make sure ADC inputs are configured properly! (Will disables batteries.)\r
if (!JumperCheck()) {\r
return(ST_ERROR); // Error. Exit before damage is done!\r
}\r
- \r
+\r
// If neither battery is valid, flag error and go to error state\r
if (!(eeprom_read_byte(&BattControl[0]) & BIT_BATTERY_ENABLED) && (!eeprom_read_byte(&BattControl[1]) & BIT_BATTERY_ENABLED)) {\r
SetErrorFlag(ERR_NO_BATTERIES_ENABLED);\r
- \r
+\r
return(ST_ERROR);\r
}\r
\r
return(ST_BATCON);\r
}\r
}\r
- \r
+\r
DisableBatteries(); // Disable both batteries before Doze()!\r
} while (TRUE);\r
}\r
\r
+/*! \brief Watchdog interrupt-service-routine\r
+ *\r
+ * Called on watchdog timeout, added by Martin Thomas\r
+ */\r
+ISR(WDT_vect)\r
+{\r
+ WatchdogFlag = 1;\r
+}\r
+\r
\r
/*! \brief Doze off for approx. 8 seconds (Vcc = 5 V)\r
*\r
* Waits for ADC-cycles to complete, disables the ADC, then sleeps for\r
* approx. 8 seconds (Vcc = 5 V) using the watchdog timer.\r
* On wakeup, ADC is re-enabled.\r
+ * Modification by Martin Thomas:\r
+ * Do not enter standby mode if PB6 is low (MASTER_INT on BC100)\r
+ * so SPI communication with the master-controller is still possible\r
+ * during "doze".\r
*/\r
void Doze(void)\r
{\r
+ uint8_t sreg_saved;\r
// Wait for this ADC cycle to complete, then halt after the next one.\r
ADC_Wait();\r
ADCS.Halt = TRUE;\r
ADCS.Flag = FALSE;\r
- \r
+\r
do {\r
} while (ADCS.Flag == FALSE);\r
- \r
+\r
WDTCR = (1<<WDP3)|(1<<WDP0); // 8.0 seconds at 5 volts VCC.\r
WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE); // Clear flag and enable watchdog.\r
- MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0); // Sleep enable, mode = standby.\r
- sleep_cpu(); // Go to sleep, wake up by WDT.\r
- \r
- wdt_reset(); // Clear watchdog reset flag.\r
- MCUSR &= ~(1<<WDRF); \r
+\r
+ DDRB &= ~(1<<PB6); // MASTER_INT as input\r
+ PORTB |= (1<<PB6); // enabled internal pullup\r
+ WatchdogFlag = 0;\r
+ if ( PINB & (1<<PB6) ) {\r
+ MCUCR |= (1<<SE) | (1<<SM1) | (1<<SM0); // Sleep enable, mode = standby.\r
+ sleep_cpu(); // Go to sleep, wake up by WDT.\r
+ }\r
+ else {\r
+ do {\r
+ } while ( !(WatchdogFlag) );\r
+ }\r
+\r
+ wdt_reset(); // Clear watchdog reset flag.\r
+ PORTB &= ~(1<<PB6); // disabled internal pullup\r
+ MCUSR &= ~(1<<WDRF);\r
+\r
+ sreg_saved = SREG;\r
+ cli();\r
WDTCR |= (1<<WDCE)|(1<<WDE); // Watchdog change enable.\r
WDTCR = 0; // Turn off watchdog.\r
- \r
+ SREG = sreg_saved;\r
+\r
ADCS.Halt = FALSE; // Enable consecutive runs of ADC.\r
ADCSRA |= (1<<ADEN)|(1<<ADSC); // Enable ADC & start conversion.\r
- \r
+\r
// Wait for this cycle to complete.\r
- ADC_Wait(); \r
+ ADC_Wait();\r
}\r
\r
\r
unsigned char Error(unsigned char inp)\r
{\r
unsigned char i;\r
- \r
+\r
PWM_Stop(); // Stop charging.\r
DisableBatteries(); // Disable all loads.\r
- \r
+\r
do {\r
Doze(); // Take a nap.\r
\r
for (i = 0x01; i!=0; i<<=1) {\r
if(i & ErrorFlags) {\r
switch (i) {\r
- \r
+\r
case ERR_JUMPER_MISMATCH:\r
// Clear flag & recheck.\r
ErrorFlags &= ~i;\r
ErrorFlags &= ~i;\r
break;\r
\r
- \r
+\r
default:\r
break;\r
}\r
signed int adcs_IBAT_tmp;\r
\r
DisableBatteries(); // Disconnect, or loads may be destroyed!\r
- \r
+\r
PWM_Start(); // Start PWM (controls the buck charger).\r
- \r
+\r
// Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.\r
Time_Set(TIMER_GEN,0,1,0);\r
- \r
+\r
do {\r
// If the PWM output voltage saturates the ADC, stop PWM output and\r
// report a failure.\r
// typical value are below our set maximum, everything is OK.\r
if (abs((signed int)(adcs_VIN_tmp - VIN_VBAT_DIFF_TYP - adcs_VBAT_tmp)) <\r
VIN_VBAT_DIFF_MAX ) {\r
- \r
+\r
PWM_Stop();\r
return(TRUE);\r
}\r
PWM_Stop();\r
return(FALSE);\r
}\r
- \r
+\r
// Wait for ADC conversions to complete\r
ADC_Wait();\r
} while (Time_Left(TIMER_GEN));\r
- \r
+\r
\r
// If we end up here, the measurements took too long.\r
PWM_Stop();\r
unsigned char Charged : 1; //!< Battery fully charged. (TRUE/FALSE)\r
unsigned char Low : 1; //!< Battery low voltage. (TRUE/FALSE)\r
unsigned char Exhausted : 1; //!< Battery exhausted. (TRUE/FALSE)\r
- unsigned char HasRID : 1; //!< Battery has resistor ID. (TRUE/FALSE)\r
+ unsigned char HasRID : 1; //!< Battery has resistor ID. (TRUE/FALSE)\r
unsigned char Circuit; //!< Battery safety circuit (family id).\r
signed char Temperature; //!< Battery temperature, in centigrade.\r
unsigned char ADCSteps; //!< ADC steps per half degree.\r
* AVR463: Charging NiMH Batteries with BC100\r
*\r
* \par Documentation\r
- * For comprehensive code documentation, supported compilers, compiler \r
+ * For comprehensive code documentation, supported compilers, compiler\r
* settings and supported devices see readme.html\r
*\r
* \author\r
* Atmel Corporation: http://www.atmel.com \n\r
* Support email: avr@atmel.com\r
*\r
- * \r
+ *\r
* $Name$\r
* $Revision: 2299 $\r
* $RCSfile$\r
//! \note See menu.h for definitions of states.\r
unsigned char ErrorState;\r
\r
+//! \brief Set to 1 by the watchdog-timeout-ISR\r
+//! \note added by Martin Thomas\r
+volatile unsigned char WatchdogFlag;\r
\r
//******************************************************************************\r
// Functions\r
\r
// Disable interrupts while setting prescaler.\r
__disable_interrupt();\r
- \r
+\r
CLKPR = (1<<CLKPCE); // Enable CLKPS bit modification.\r
CLKPR = 0; // Set prescaler 1 => 8 MHz clock frequency.\r
- \r
+\r
// Init 1-Wire(R) interface.\r
OWI_Init(OWIBUS);\r
- \r
+\r
// Clear on-chip EEPROM.\r
- for (page = 0; page < 4; page++) {\r
+ for (page = 0; page < 4; page++) {\r
for (i = 0; i < 32; i++) {\r
- BattEEPROM[page][i] = 0;\r
+ // From mthomas GCC addition\r
+ if (BattEEPROM[page][i] != 0) {\r
+ BattEEPROM[page][i] = 0;\r
+ }\r
}\r
}\r
\r
ADC_Wait();\r
BatteryStatusRefresh();\r
}\r
- \r
+\r
DisableBatteries();\r
- \r
+\r
BattActive = 0; // We have to start somewhere..\r
ErrorFlags = 0;\r
- \r
+\r
// Init complete! Go to ST_BATCON next.\r
return(ST_BATCON);\r
}\r
unsigned char BatteryControl(unsigned char inp)\r
{\r
unsigned char i;\r
- \r
+\r
// Make sure ADC inputs are configured properly! (Will disables batteries.)\r
if (!JumperCheck()) {\r
return(ST_ERROR); // Error. Exit before damage is done!\r
}\r
- \r
+\r
// If neither battery is valid, flag error and go to error state\r
if ((!BattControl[0].Enabled) && (!BattControl[1].Enabled)) {\r
SetErrorFlag(ERR_NO_BATTERIES_ENABLED);\r
- \r
+\r
return(ST_ERROR);\r
}\r
\r
// Get ADC-readings, try to read EPROM, and start prequalification\r
// of any uncharged battery.\r
for (i = 0; i < 2; i++) {\r
- if (BattControl[i].Enabled) { \r
+ if (BattControl[i].Enabled) {\r
EnableBattery(i);\r
ADC_Wait();\r
\r
if (!BattData.Charged) {\r
BatteryDataRefresh();\r
\r
- return(ST_PREQUAL); \r
+ return(ST_PREQUAL);\r
}\r
}\r
}\r
return(ST_BATCON);\r
}\r
}\r
- \r
+\r
DisableBatteries(); // Disable both batteries before Doze()!\r
} while (TRUE);\r
}\r
\r
+/*! \brief Watchdog interrupt-service-routine\r
+ *\r
+ * Called on watchdog timeout, added by Martin Thomas\r
+ */\r
+#pragma vector = WDT_vect\r
+__interrupt void WDT_ISR(void)\r
+{\r
+ WatchdogFlag = 1;\r
+}\r
+\r
\r
/*! \brief Doze off for approx. 8 seconds (Vcc = 5 V)\r
*\r
* Waits for ADC-cycles to complete, disables the ADC, then sleeps for\r
* approx. 8 seconds (Vcc = 5 V) using the watchdog timer.\r
* On wakeup, ADC is re-enabled.\r
+ * Modification by Martin Thomas:\r
+ * Do not enter standby mode if PB6 is low (MASTER_INT on BC100)\r
+ * so SPI communication with the master-controller is still possible\r
+ * during "doze".\r
*/\r
void Doze(void)\r
{\r
+ uint8_t sreg_saved;\r
// Wait for this ADC cycle to complete, then halt after the next one.\r
ADC_Wait();\r
ADCS.Halt = TRUE;\r
ADCS.Flag = FALSE;\r
- \r
+\r
do {\r
- } while (ADCS.Flag == FALSE); \r
- \r
+ } while (ADCS.Flag == FALSE);\r
+\r
WDTCR = (1<<WDP3)|(1<<WDP0); // 8.0 seconds at 5 volts VCC.\r
WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE); // Clear flag and enable watchdog.\r
- MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0); // Sleep enable, mode = standby.\r
- __sleep(); // Go to sleep, wake up by WDT.\r
- \r
+\r
+ DDRB &= ~(1<<PB6); // MASTER_INT as input\r
+ PORTB |= (1<<PB6); // enabled internal pullup\r
+ WatchdogFlag = 0;\r
+ if ( PINB & (1<<PB6) ) {\r
+ MCUCR |= (1<<SE) | (1<<SM1) | (1<<SM0); // Sleep enable, mode = standby.\r
+ __sleep(); // Go to sleep, wake up by WDT.\r
+ }\r
+ else {\r
+ do {\r
+ } while ( !(WatchdogFlag) );\r
+ }\r
+\r
__watchdog_reset(); // Clear watchdog reset flag.\r
- MCUSR &= ~(1<<WDRF); \r
+ PORTB &= ~(1<<PB6); // disabled internal pullup\r
+ MCUSR &= ~(1<<WDRF);\r
+\r
+ sreg_saved = SREG;\r
+ cli();\r
WDTCR |= (1<<WDCE)|(1<<WDE); // Watchdog change enable.\r
WDTCR = 0; // Turn off watchdog.\r
- \r
+ SREG = sreg_saved;\r
+\r
ADCS.Halt = FALSE; // Enable consecutive runs of ADC.\r
ADCSRA |= (1<<ADEN)|(1<<ADSC); // Enable ADC & start conversion.\r
- \r
+\r
// Wait for this cycle to complete.\r
- ADC_Wait(); \r
+ ADC_Wait();\r
}\r
\r
\r
unsigned char Error(unsigned char inp)\r
{\r
unsigned char i;\r
- \r
+\r
PWM_Stop(); // Stop charging.\r
DisableBatteries(); // Disable all loads.\r
- \r
+\r
do {\r
Doze(); // Take a nap.\r
\r
for (i = 0x01; i!=0; i<<=1) {\r
if(i & ErrorFlags) {\r
switch (i) {\r
- \r
+\r
case ERR_JUMPER_MISMATCH:\r
// Clear flag & recheck.\r
ErrorFlags &= ~i;\r
ErrorFlags &= ~i;\r
break;\r
\r
- \r
+\r
default:\r
break;\r
}\r
unsigned char JumperCheck(void)\r
{\r
DisableBatteries(); // Disconnect, or loads may be destroyed!\r
- \r
+\r
PWM_Start(); // Start PWM (controls the buck charger).\r
- \r
+\r
// Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.\r
Time_Set(TIMER_GEN,0,1,0);\r
- \r
+\r
do {\r
// If the PWM output voltage saturates the ADC, stop PWM output and\r
// report a failure.\r
// typical value are below our set maximum, everything is OK.\r
if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <\r
VIN_VBAT_DIFF_MAX ) {\r
- \r
+\r
PWM_Stop();\r
return(TRUE);\r
}\r
PWM_Stop();\r
return(FALSE);\r
}\r
- \r
+\r
// Wait for ADC conversions to complete\r
ADC_Wait();\r
} while (Time_Left(TIMER_GEN));\r
- \r
+\r
\r
// If we end up here, the measurements took too long.\r
PWM_Stop();\r
--- /dev/null
+2008-04-07 Kevin Rosenberg <kevin@rosenberg.net>\r
+ * BaseTinyFirmware/IAR: Port Martin's changes from 2008-04-03\r
+ to IAR\r
+ \r
+2008-04-03 Martin Thomas <mthomas@rhrk.uni-kl.de>\r
+ * BaseMegaFirmware/GCC: Experimental Master Code for the ATmega644\r
+ with basic "drivers" for\r
+ - keys incl. power-off with debounceing\r
+ - 74HC595 low-level "software-SPI"\r
+ - LEDs though 74HC595\r
+ - Power-off and Slave-Reset control though 74HC595\r
+ - hardware SPI for comm. with slave\r
+ - simple test-function for communication with slave\r
+ * BaseTinyFirmware/GCC/statefunc.c: \r
+ - prevent unneeded writes to eeprom if init fails\r
+ - prevent slave from entering sleep-mode standby if\r
+ "MASTER_INT" is low (so SPI communication with master is\r
+ possible even during the "8-second watchdog delay")\r
+\r
+2008-03-30 Kevin Rosenberg <kevin@rosenberg.net>\r
+ * BaseTinyFirmware/GCC Makefile's improved with more listing\r
+ output as well as added -Wl,-gc-sections option which stops\r
+ crashes using linker relaxation [thanks to Eric Weddington]\r
+\r
+2008-03-28 Kevin Rosenberg <kevin@rosenberg.net>\r
+ * BaseTinyFirmware/GCC/avr463/Makefile: Added -Wl,-relax to linker\r
+ flags. On my system this crashes avr-ld.exe, but others have\r
+ reported a large reduction in firmware size with this option. I\r
+ added this option for others to try. *\r
+ BaseTinyFirmware/GCC/avr458/Makefile: Added missing file\r
+ \r
+2008-03-14 Martin Thomas <mthomas@rhrk.uni-kl.de>\r
+ Improvements to BaseTinyFirmware:\r
+ * added "volatile" to structure object and array declarations for\r
+ objects sed in main-thread and ISRs. I'm not sure about the\r
+ current state of implicitly "guaranteed" accesses in (avr-)gcc but\r
+ it should be a "better safe than sorry" extension.\r
+ * enveloped access to timer-values in timer.c to make them\r
+ "atomic" since they are unsigned long\r
+ * "atomic" access to singned int and unsigned int members of ADCS\r
+ * it maybe better to have one place to globally enable\r
+ interrupts ("sei"). Done in "initialize" now and not several\r
+ times in the driver init-functions.\r
+ * changed some space to tab as in the original code\r
+ * added header files to the AVR-Studio project workspace\r
+ * added -lm to the linker-options in the AVR Studio gcc-plugin,\r
+ not important for the basic application but might be good if\r
+ someone uses the ode as a base for own developments\r
+\r
+2008-03-12 Kevin Rosenberg <kevin@rosenberg.net>\r
+ * Initial GCC port performed and compiles without error\r
+ * Warning: Not yet tested on BC100 hardware!\r