diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bbb2094 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.d +*.o +*.bin +*.hex diff --git a/PINOUT b/PINOUT index 505ad66..a416e1d 100644 --- a/PINOUT +++ b/PINOUT @@ -1,6 +1,6 @@ 1 - VCC 2 - PB0 - Fet 1 -3 - PB3 - Fet 2 +3 - PB1 - Fet 2 4 - RESET 5 - PB2 - Led 1 6 - PA7 - Led 2 diff --git a/firmware/Makefile b/firmware/Makefile new file mode 100644 index 0000000..672d8bb --- /dev/null +++ b/firmware/Makefile @@ -0,0 +1,76 @@ +CFLAGS += -Wall -Os -I. -mmcu=attiny24 -std=c99 +DEFINES += -DF_CPU=1e6 + +OBJECTS = cup.o + +# further optimization: +# this removes dead code and does global linker optimization +#CFLAGS += -ffunction-sections -Wl,--gc-sections -Wl,--relax +#CFLAGS += --param inline-call-cost=2 + +COMPILE = avr-gcc $(CFLAGS) $(DEFINES) + +# symbolic targets: +all: firmware.hex + +.c.o: + $(COMPILE) -c $< -o $@ + +.S.o: + $(COMPILE) -x assembler-with-cpp -c $< -o $@ +# "-x assembler-with-cpp" should not be necessary since this is the default +# file type for the .S (with capital S) extension. However, upper case +# characters are not always preserved on Windows. To ensure WinAVR +# compatibility define the file type manually. + +.c.s: + $(COMPILE) -S $< -o $@ + +flash: all + avrdude -c usbasp -p t24 -U flash:w:firmware.hex + +fuses: + avrdude -c usbasp -p t24 -U lfuse:w:0x61:m # -U hfuse:w:0xf7:m # internal 8Mhz oscillator + + +## what are the source dependencies +%.d: %.c + @set -e; rm -f $@; \ + $(COMPILE) -MM $< | sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' > $@; +# line 1: exits if anything goes wrong +# line 2a: gcc -MM outputs dependencies +# line 2b: insert the %.d into dependency list + +#main.c: version.h + + +version.h: .svn/entries + export LANG=POSIX; (svn info 2>/dev/null || echo "Revision: unknown") | awk '/^Revision:/ {print "#define SVNVERSION \"" $$2 "\""};' >version.h + + +clean: + rm -f *.o *.hex *.obj *.i *.s *.d */*.i */*.s */*.o */*.d version.h + +# file targets: +firmware.bin: $(OBJECTS) + $(COMPILE) -o firmware.bin $(OBJECTS) + +firmware.hex: firmware.bin + rm -f firmware.hex firmware.eep.hex + avr-objcopy -j .text -j .data -O ihex firmware.bin firmware.hex + avr-size firmware.bin +# ./checksize firmware.bin 8192 960 +# do the checksize script as our last action to allow successful compilation +# on Windows with WinAVR where the Unix commands will fail. + +disasm: firmware.bin + avr-objdump -d firmware.bin >disasm + +functionsize: disasm + python avrbuild/functionsize.py + +countregs: disasm + python avrbuild/countregs.py + +# for depends: +-include $(OBJECTS:.o=.d) diff --git a/firmware/cup.c b/firmware/cup.c index a7ed9ef..de043dc 100644 --- a/firmware/cup.c +++ b/firmware/cup.c @@ -10,6 +10,8 @@ #define FET0_PIN 0 #define FET1_PIN 1 +#define TIMEOUT 255 + uint8_t led_color = 0; uint8_t setting_timeout = 0; @@ -23,28 +25,58 @@ uint8_t heat_pwm = 0; uint8_t heat_on[2] = {0, 0}; uint8_t heat_off[2] = {0, 0}; -ISR(timer1 overflow) +uint8_t input_state = 0; +uint8_t dev_state = 0; + +/* gray code to change lookup table, index is old state .. new state */ +int8_t state_change[16] = {0, 1, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, -1, 1, 0}; + +ISR(TIM1_OVF_vect) { + /* timeout for displaying target temperature */ if(setting_timeout) {setting_timeout--;} - heat_pwm_cnt++; - if(heat_pwm == heat_on[0]) {PORTB |= (1 << FET0);} - if(heat_pwm == heat_off[0]) {PORTB &= ~(1 << FET0);} - if(heat_pwm == heat_on[1]) {PORTB |= (1 << FET1);} - if(heat_pwm == heat_off[1]) {PORTB &= ~(1 << FET1);} + /* incremtening softpwm, toggling output if needed */ + heat_pwm++; + if(heat_pwm == heat_on[0]) {PORTB |= (1 << FET0_PIN);} + if(heat_pwm == heat_off[0]) {PORTB &= ~(1 << FET0_PIN);} + if(heat_pwm == heat_on[1]) {PORTB |= (1 << FET1_PIN);} + if(heat_pwm == heat_off[1]) {PORTB &= ~(1 << FET1_PIN);} +} + +ISR(PCINT0_vect) +{ + uint8_t new_state = (PORTA & ((1 << IMPULS1_PIN) | (1 << IMPULS0_PIN) | (1 << TAST_PIN))) >> 1; + uint8_t diff = new_state ^ input_state; + if(!diff) {return;} + + if(diff & (1 << TAST_PIN) && new_state & (1 << TAST_PIN)) + { + dev_state = !dev_state; + } + + int8_t change = state_change[((input_state & 3) << 2) | (new_state & 3)]; + if(change) + { + target += change; + setting_timeout = TIMEOUT; + } + + input_state = new_state; } void io_init(void) { PORTA = (1 << TAST_PIN) | (1 << IMPULS1_PIN) | (1 << IMPULS0_PIN);/* enable pullups on inputs */ PORTB = 0; - DDRA = (1 << OC0B);/* led outputs ... */ - DDRB = (1 << OC0A) | (1 << FET0_PIN) | (1 << FET1_PIN);/* ... and FET output */ + DDRA = (1 << PA7);/* led outputs ... */ + DDRB = (1 << PB2) | (1 << FET0_PIN) | (1 << FET1_PIN);/* ... and FET output */ + input_state = PORTA & ((1 << IMPULS1_PIN) | (1 << IMPULS0_PIN) | (1 << TAST_PIN)); } void led_init(void) { - TCCR0A = (1 << COM0A1) | (1 << COM0B1) | (1 << COM0B0) | (1 << WGM1) | (1 << WGM0);/* pwm enable: fast, A not inverted, B inverted */ + TCCR0A = (1 << COM0A1) | (1 << COM0B1) | (1 << COM0B0) | (1 << WGM01) | (1 << WGM00);/* pwm enable: fast, A not inverted, B inverted */ TCCR0B = (1 << CS02) | (1 << CS00);/* prescaler / 1024 */ OCR0A = OCR0B = led_color; } @@ -65,7 +97,7 @@ void adc_init(void) void heat_init(void) { - TCCRB1 = (1 << CS12) | (1 << CS10);/* prescaler / 1024 */ + TCCR1B = (1 << CS12) | (1 << CS10);/* prescaler / 1024 */ TIMSK1 = (1 << TOIE1);/* interupt on overflow */ /* insert loading of heat setting here */ } @@ -92,8 +124,8 @@ int main(void) { /* new adc result */ ADCSRA |= (1 << ADIF); - adc_sum[adc_pos++] += ADC; - if(!adc_pos) + adc_sum += ADC; + if(!++adc_pos) { temp = adc_sum; }