4008-04-07 Release
authorKevin Rosenberg <kevin@rosenberg.net>
Mon, 7 Apr 2008 17:02:56 +0000 (11:02 -0600)
committerKevin Rosenberg <kevin@rosenberg.net>
Mon, 7 Apr 2008 17:02:56 +0000 (11:02 -0600)
2008-04-07 Kevin Rosenberg <kevin@rosenberg.net>
* BaseTinyFirmware/IAR: Port Martin's changes from 2008-04-03
to IAR

2008-04-03 Martin Thomas <mthomas@rhrk.uni-kl.de>
* BaseMegaFirmware/GCC: Experimental Master Code for the ATmega644
with basic "drivers" for
- keys incl. power-off with debounceing
- 74HC595 low-level "software-SPI"
- LEDs though 74HC595
- Power-off and Slave-Reset control though 74HC595
- hardware SPI for comm. with slave
- simple test-function for communication with slave
* BaseTinyFirmware/GCC/statefunc.c:
- prevent unneeded writes to eeprom if init fails
- prevent slave from entering sleep-mode standby if
"MASTER_INT" is low (so SPI communication with master is
possible even during the "8-second watchdog delay")

25 files changed:
BaseMegaFirmware/GCC/bc100_master.aps [new file with mode: 0644]
BaseMegaFirmware/GCC/bc100_master.aws [new file with mode: 0644]
BaseMegaFirmware/GCC/bc100_slave.c [new file with mode: 0644]
BaseMegaFirmware/GCC/bc100_slave.h [new file with mode: 0644]
BaseMegaFirmware/GCC/default/Makefile [new file with mode: 0644]
BaseMegaFirmware/GCC/key_io.c [new file with mode: 0644]
BaseMegaFirmware/GCC/key_io.h [new file with mode: 0644]
BaseMegaFirmware/GCC/main.c [new file with mode: 0644]
BaseMegaFirmware/GCC/mystdio.c [new file with mode: 0644]
BaseMegaFirmware/GCC/mystdio.h [new file with mode: 0644]
BaseMegaFirmware/GCC/port_ext.c [new file with mode: 0644]
BaseMegaFirmware/GCC/port_ext.h [new file with mode: 0644]
BaseMegaFirmware/GCC/spi.c [new file with mode: 0644]
BaseMegaFirmware/GCC/spi.h [new file with mode: 0644]
BaseMegaFirmware/GCC/timebase.c [new file with mode: 0644]
BaseMegaFirmware/GCC/timebase.h [new file with mode: 0644]
BaseMegaFirmware/GCC/uart.c [new file with mode: 0644]
BaseMegaFirmware/GCC/uart.h [new file with mode: 0644]
BaseTinyFirmware/GCC/ChangeLog [deleted file]
BaseTinyFirmware/GCC/PWM.c
BaseTinyFirmware/GCC/avr458/Makefile
BaseTinyFirmware/GCC/statefunc.c
BaseTinyFirmware/GCC/structs.h
BaseTinyFirmware/IAR/statefunc.c
ChangeLog [new file with mode: 0644]

diff --git a/BaseMegaFirmware/GCC/bc100_master.aps b/BaseMegaFirmware/GCC/bc100_master.aps
new file mode 100644 (file)
index 0000000..da05a21
--- /dev/null
@@ -0,0 +1 @@
+<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
diff --git a/BaseMegaFirmware/GCC/bc100_master.aws b/BaseMegaFirmware/GCC/bc100_master.aws
new file mode 100644 (file)
index 0000000..93a72f1
--- /dev/null
@@ -0,0 +1 @@
+<AVRWorkspace><IOSettings><CurrentRegisters/></IOSettings><part name="ATMEGA644"/><Files/></AVRWorkspace>\r
diff --git a/BaseMegaFirmware/GCC/bc100_slave.c b/BaseMegaFirmware/GCC/bc100_slave.c
new file mode 100644 (file)
index 0000000..a03a334
--- /dev/null
@@ -0,0 +1,105 @@
+// 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
diff --git a/BaseMegaFirmware/GCC/bc100_slave.h b/BaseMegaFirmware/GCC/bc100_slave.h
new file mode 100644 (file)
index 0000000..63450b7
--- /dev/null
@@ -0,0 +1,23 @@
+// 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
diff --git a/BaseMegaFirmware/GCC/default/Makefile b/BaseMegaFirmware/GCC/default/Makefile
new file mode 100644 (file)
index 0000000..f1333e5
--- /dev/null
@@ -0,0 +1,96 @@
+###############################################################################\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
diff --git a/BaseMegaFirmware/GCC/key_io.c b/BaseMegaFirmware/GCC/key_io.c
new file mode 100644 (file)
index 0000000..3c8eaa7
--- /dev/null
@@ -0,0 +1,76 @@
+// 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
diff --git a/BaseMegaFirmware/GCC/key_io.h b/BaseMegaFirmware/GCC/key_io.h
new file mode 100644 (file)
index 0000000..8c0891f
--- /dev/null
@@ -0,0 +1,101 @@
+/* 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
diff --git a/BaseMegaFirmware/GCC/main.c b/BaseMegaFirmware/GCC/main.c
new file mode 100644 (file)
index 0000000..f467b4b
--- /dev/null
@@ -0,0 +1,250 @@
+/* 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
diff --git a/BaseMegaFirmware/GCC/mystdio.c b/BaseMegaFirmware/GCC/mystdio.c
new file mode 100644 (file)
index 0000000..9fe8a24
--- /dev/null
@@ -0,0 +1,22 @@
+// 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
diff --git a/BaseMegaFirmware/GCC/mystdio.h b/BaseMegaFirmware/GCC/mystdio.h
new file mode 100644 (file)
index 0000000..7c3eaa0
--- /dev/null
@@ -0,0 +1,13 @@
+#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
diff --git a/BaseMegaFirmware/GCC/port_ext.c b/BaseMegaFirmware/GCC/port_ext.c
new file mode 100644 (file)
index 0000000..40ff4ab
--- /dev/null
@@ -0,0 +1,126 @@
+// 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
diff --git a/BaseMegaFirmware/GCC/port_ext.h b/BaseMegaFirmware/GCC/port_ext.h
new file mode 100644 (file)
index 0000000..aa25da9
--- /dev/null
@@ -0,0 +1,32 @@
+// 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
diff --git a/BaseMegaFirmware/GCC/spi.c b/BaseMegaFirmware/GCC/spi.c
new file mode 100644 (file)
index 0000000..a69e4e7
--- /dev/null
@@ -0,0 +1,43 @@
+// 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
diff --git a/BaseMegaFirmware/GCC/spi.h b/BaseMegaFirmware/GCC/spi.h
new file mode 100644 (file)
index 0000000..fbe77f0
--- /dev/null
@@ -0,0 +1,25 @@
+// 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
diff --git a/BaseMegaFirmware/GCC/timebase.c b/BaseMegaFirmware/GCC/timebase.c
new file mode 100644 (file)
index 0000000..92bf015
--- /dev/null
@@ -0,0 +1,87 @@
+// 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
diff --git a/BaseMegaFirmware/GCC/timebase.h b/BaseMegaFirmware/GCC/timebase.h
new file mode 100644 (file)
index 0000000..b5325eb
--- /dev/null
@@ -0,0 +1,11 @@
+#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
diff --git a/BaseMegaFirmware/GCC/uart.c b/BaseMegaFirmware/GCC/uart.c
new file mode 100644 (file)
index 0000000..48d2c9a
--- /dev/null
@@ -0,0 +1,585 @@
+/*************************************************************************\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
diff --git a/BaseMegaFirmware/GCC/uart.h b/BaseMegaFirmware/GCC/uart.h
new file mode 100644 (file)
index 0000000..ca9c460
--- /dev/null
@@ -0,0 +1,178 @@
+#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
diff --git a/BaseTinyFirmware/GCC/ChangeLog b/BaseTinyFirmware/GCC/ChangeLog
deleted file mode 100644 (file)
index 9c5d2d5..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-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
index 9d205fc2703410e731abe05f92d8ef3d4186d3db..a84a357ab35baa538e515335c4eb7b6f41737a71 100644 (file)
  *      AVR463: Charging NiMH Batteries with BC100\r
  *\r
  * \par Documentation\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
  *      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
  * $Name$\r
  * $Revision: 2299 $\r
  * $RCSfile$\r
@@ -67,52 +67,52 @@ void PWM_Start(void)
 {\r
        // Clear OC1B on compare match, enable PWM on comparator OCR1B.\r
        TCCR1A = (1<<COM1B1)|(0<<COM1B0)|(1<<PWM1B);\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
        // Non-inverted PWM, T/C stopped.\r
        TCCR1B = 0;\r
-       \r
+\r
        // Copy shadow bits, disconnect OC1D.\r
        TCCR1C = (TCCR1A & 0xF0);\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
        // 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
        // Does not matter -- PWM6 mode not used.\r
        TCCR1E = 0;\r
-       \r
+\r
        // Does not matter -- OC1A is disabled.\r
        OCR1A = 0;\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
        // 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
        // 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
        // Does not matter -- OC1D is disabled.\r
        OCR1D = 0;\r
-       \r
+\r
        // No dead time values.\r
        DT1 = 0;\r
        // No dead time values.\r
        DT1 = 0;\r
-       \r
+\r
        // Set PWM port pin to output.\r
        DDRB |= (1<<PB3);\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
        // 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
        // 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
        }while(Time_Left(TIMER_GEN));\r
-       \r
+\r
        // Now wait for PLL to lock.\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
        }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
        // CLK PCK = 64MHz / 1 = 64MHz.\r
        TCCR1B |= (0<<CS13)|(0<<CS12)|(0<<CS11)|(1<<CS10);\r
 }\r
@@ -139,9 +139,9 @@ unsigned char PWM_IncrementDutyCycle(void){
  * \retval TRUE Success, duty cycle could be decremented.\r
  * \retval FALSE Failure, duty cycle already at zero.\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
                OCR1B -= 1;\r
                return(TRUE);\r
        } else {\r
index 412aa8da755bf32357bd8545f0052868c8a1e265..c2d1462e600dd9cc3cb6bdc05cac0465160bf532 100644 (file)
@@ -13,7 +13,7 @@ COMMON = -mmcu=$(MCU)
 \r
 ## Compile options common for all C compilation units.\r
 CFLAGS = $(COMMON)\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
 CFLAGS += -Wall -Wstrict-prototypes -Wundef -Wa,-adhlns=./$(*F).lst\r
 CFLAGS += -MMD -MP -MF dep/$(@F).d  \r
 CFLAGS += -DLIION\r
@@ -25,7 +25,7 @@ ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
 \r
 ## Linker flags\r
 LDFLAGS = $(COMMON)\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
 \r
 ## Intel Hex file production flags\r
 HEX_FLASH_FLAGS = -R .eeprom\r
index ef1464dcab714766f0addf4d6fb0261e04cec53b..9fc0ae5ae08669aecee4f6b6dfa13b1d2c4117c3 100644 (file)
  *      AVR463: Charging NiMH Batteries with BC100\r
  *\r
  * \par Documentation\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
  *      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
  * $Name$\r
  * $Revision: 2299 $\r
  * $RCSfile$\r
@@ -65,6 +65,9 @@ unsigned char ErrorFlags;  //!< \brief Holds error flags.
 //! \note See menu.h for definitions of states.\r
 unsigned char ErrorState;\r
 \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
 //******************************************************************************\r
 // Functions\r
@@ -93,17 +96,20 @@ unsigned char Initialize(unsigned char inp)
 \r
        // Disable interrupts while setting prescaler.\r
        cli();\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
        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
        // Init 1-Wire(R) interface.\r
        OWI_Init(OWIBUS);\r
-       \r
+\r
        // Clear on-chip EEPROM.\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
                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
 \r
@@ -124,10 +130,10 @@ unsigned char Initialize(unsigned char inp)
        }\r
 \r
        DisableBatteries();\r
        }\r
 \r
        DisableBatteries();\r
-       \r
+\r
        BattActive = 0;               // We have to start somewhere..\r
        ErrorFlags = 0;\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
        // Init complete! Go to ST_BATCON next.\r
        return(ST_BATCON);\r
 }\r
@@ -153,16 +159,16 @@ unsigned char Initialize(unsigned char inp)
 unsigned char BatteryControl(unsigned char inp)\r
 {\r
        unsigned char i;\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
        // 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
        // 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_ERROR);\r
        }\r
 \r
@@ -229,43 +235,72 @@ unsigned char Sleep(unsigned char inp)
                                return(ST_BATCON);\r
                        }\r
                }\r
                                return(ST_BATCON);\r
                        }\r
                }\r
-               \r
+\r
                DisableBatteries();  // Disable both batteries before Doze()!\r
        } while (TRUE);\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
 \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
  */\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
        // 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
        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
        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
        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
        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
        // Wait for this cycle to complete.\r
-       ADC_Wait();                             \r
+       ADC_Wait();\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -294,10 +329,10 @@ void Doze(void)
 unsigned char Error(unsigned char inp)\r
        {\r
        unsigned char i;\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
        PWM_Stop();           // Stop charging.\r
        DisableBatteries();   // Disable all loads.\r
-       \r
+\r
        do {\r
                Doze();           // Take a nap.\r
 \r
        do {\r
                Doze();           // Take a nap.\r
 \r
@@ -306,7 +341,7 @@ unsigned char Error(unsigned char inp)
                for (i = 0x01; i!=0; i<<=1) {\r
                        if(i & ErrorFlags) {\r
                                switch (i) {\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
                                case  ERR_JUMPER_MISMATCH:\r
                                        // Clear flag & recheck.\r
                                        ErrorFlags &= ~i;\r
@@ -341,7 +376,7 @@ unsigned char Error(unsigned char inp)
                                        ErrorFlags &= ~i;\r
                                break;\r
 \r
                                        ErrorFlags &= ~i;\r
                                break;\r
 \r
-                                       \r
+\r
                                default:\r
                                break;\r
                                }\r
                                default:\r
                                break;\r
                                }\r
@@ -386,12 +421,12 @@ unsigned char JumperCheck(void)
        signed int adcs_IBAT_tmp;\r
 \r
         DisableBatteries();       // Disconnect, or loads may be destroyed!\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
         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
         // 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
        do {\r
                // If the PWM output voltage saturates the ADC, stop PWM output and\r
                // report a failure.\r
@@ -412,7 +447,7 @@ unsigned char JumperCheck(void)
                // 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
                // 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(TRUE);\r
                }\r
@@ -429,11 +464,11 @@ unsigned char JumperCheck(void)
                        PWM_Stop();\r
                        return(FALSE);\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
                // 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
 \r
        // If we end up here, the measurements took too long.\r
        PWM_Stop();\r
index a78b9c1d10d07b1328d67d6167c87dbb54764029..742c17e94e9e97a98cc314a3ee197f4a687a67e1 100644 (file)
@@ -45,7 +45,7 @@ struct Batteries_struct
        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 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
        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
index e34994f7d704e268184cd4910af2e0d2dbd9fc16..9dbdde18c4cf8c6bcc5a93b03471ea840d4f048d 100644 (file)
  *      AVR463: Charging NiMH Batteries with BC100\r
  *\r
  * \par Documentation\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
  *      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
  * $Name$\r
  * $Revision: 2299 $\r
  * $RCSfile$\r
@@ -60,6 +60,9 @@ unsigned char ErrorFlags;  //!< \brief Holds error flags.
 //! \note See menu.h for definitions of states.\r
 unsigned char ErrorState;\r
 \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
 //******************************************************************************\r
 // Functions\r
@@ -88,17 +91,20 @@ unsigned char Initialize(unsigned char inp)
 \r
        // Disable interrupts while setting prescaler.\r
        __disable_interrupt();\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
        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
        // Init 1-Wire(R) interface.\r
        OWI_Init(OWIBUS);\r
-       \r
+\r
        // Clear on-chip EEPROM.\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
                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
                }\r
        }\r
 \r
@@ -114,12 +120,12 @@ unsigned char Initialize(unsigned char inp)
                ADC_Wait();\r
                BatteryStatusRefresh();\r
        }\r
                ADC_Wait();\r
                BatteryStatusRefresh();\r
        }\r
-    \r
+\r
        DisableBatteries();\r
        DisableBatteries();\r
-       \r
+\r
        BattActive = 0;               // We have to start somewhere..\r
        ErrorFlags = 0;\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
        // Init complete! Go to ST_BATCON next.\r
        return(ST_BATCON);\r
 }\r
@@ -145,23 +151,23 @@ unsigned char Initialize(unsigned char inp)
 unsigned char BatteryControl(unsigned char inp)\r
 {\r
        unsigned char i;\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
        // 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
        // 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
                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
                        EnableBattery(i);\r
                        ADC_Wait();\r
 \r
@@ -169,7 +175,7 @@ unsigned char BatteryControl(unsigned char inp)
                                if (!BattData.Charged) {\r
                                        BatteryDataRefresh();\r
 \r
                                if (!BattData.Charged) {\r
                                        BatteryDataRefresh();\r
 \r
-                                       return(ST_PREQUAL);       \r
+                                       return(ST_PREQUAL);\r
                                }\r
                        }\r
                }\r
                                }\r
                        }\r
                }\r
@@ -221,43 +227,73 @@ unsigned char Sleep(unsigned char inp)
                                return(ST_BATCON);\r
                        }\r
                }\r
                                return(ST_BATCON);\r
                        }\r
                }\r
-               \r
+\r
                DisableBatteries();  // Disable both batteries before Doze()!\r
        } while (TRUE);\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
 \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
  */\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
        // 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
        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
        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
        __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
        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
        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
        // Wait for this cycle to complete.\r
-       ADC_Wait();                             \r
+       ADC_Wait();\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -286,10 +322,10 @@ void Doze(void)
 unsigned char Error(unsigned char inp)\r
        {\r
        unsigned char i;\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
        PWM_Stop();           // Stop charging.\r
        DisableBatteries();   // Disable all loads.\r
-       \r
+\r
        do {\r
                Doze();           // Take a nap.\r
 \r
        do {\r
                Doze();           // Take a nap.\r
 \r
@@ -298,7 +334,7 @@ unsigned char Error(unsigned char inp)
                for (i = 0x01; i!=0; i<<=1) {\r
                        if(i & ErrorFlags) {\r
                                switch (i) {\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
                                case  ERR_JUMPER_MISMATCH:\r
                                        // Clear flag & recheck.\r
                                        ErrorFlags &= ~i;\r
@@ -333,7 +369,7 @@ unsigned char Error(unsigned char inp)
                                        ErrorFlags &= ~i;\r
                                break;\r
 \r
                                        ErrorFlags &= ~i;\r
                                break;\r
 \r
-                                       \r
+\r
                                default:\r
                                break;\r
                                }\r
                                default:\r
                                break;\r
                                }\r
@@ -374,12 +410,12 @@ void SetErrorFlag(unsigned char Flag)
 unsigned char JumperCheck(void)\r
 {\r
         DisableBatteries();       // Disconnect, or loads may be destroyed!\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
         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
         // 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
        do {\r
                // If the PWM output voltage saturates the ADC, stop PWM output and\r
                // report a failure.\r
@@ -392,7 +428,7 @@ unsigned char JumperCheck(void)
                // 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
                // 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(TRUE);\r
                }\r
@@ -409,11 +445,11 @@ unsigned char JumperCheck(void)
                        PWM_Stop();\r
                        return(FALSE);\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
       // 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
 \r
        // If we end up here, the measurements took too long.\r
        PWM_Stop();\r
diff --git a/ChangeLog b/ChangeLog
new file mode 100644 (file)
index 0000000..da54f36
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,52 @@
+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