diff --git a/firmware/Makefile b/firmware/Makefile index b5c013b..b052ecf 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -11,16 +11,16 @@ FUSES = lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0x01:m SRC=$(wildcard lib/*.c apps/*.c *.c) OBJECTS= $(SRC:.c=.o) LSTFILES= $(SRC:.c=.lst) -HEADERS=$(wildcard lib/*.h *.h) +HEADERS=$(wildcard */*/*.h */*.h *.h) # Compiler Options -GCFLAGS = -ffreestanding -std=gnu99 -mmcu=$(MCU) $(OPTIMIZATION) -Wl,-gc-sections -nostdlib -I. +GCFLAGS = -ffreestanding -std=gnu99 -mmcu=$(MCU) $(OPTIMIZATION) -Wl,-gc-sections -nostdlib -I. -Iinclude # Warnings GCFLAGS += -Wstrict-prototypes -Wundef -Wall -Wextra -Wunreachable-code # Optimizazions GCFLAGS += -fsingle-precision-constant -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -fno-builtin -ffunction-sections -fno-common -fdata-sections # Debug stuff -GCFLAGS += -Wa,-adhlns=$(<:.c=.lst),-gstabs -g +GCFLAGS += -Wa,-adhlns=$(<:.c=.lst),-gstabs -g GCFLAGS += -DF_CPU=$(F_CPU) -DQUARZ=$(QUARZ) diff --git a/firmware/apps/blinker.c b/firmware/apps/blinker.c new file mode 100644 index 0000000..bc00ab8 --- /dev/null +++ b/firmware/apps/blinker.c @@ -0,0 +1,31 @@ +#include + +#include +#define __DELAY_BACKWARD_COMPATIBLE__ +#include + +#include +#include + +static void init(void) { + PIND |= 1 << 4; + DDRD |= 1 << 4; + + _delay_ms(2000); +} + +static void blinker(void) { + size_t i; + + for(i = 0; i < 5; ++i) { + PORTD |= 1 << 4; + _delay_ms(800); + + PORTD &= ~(1 << 4); + _delay_ms(200); + } + + stop_app(); +} + +REGISTER(blinker, init, NULL); diff --git a/firmware/include/pentabug/app.h b/firmware/include/pentabug/app.h new file mode 100644 index 0000000..f1e0564 --- /dev/null +++ b/firmware/include/pentabug/app.h @@ -0,0 +1,24 @@ +#ifndef APP_H +#define APP_H + +#define MAX_APPS 8 + +#define REG(run) REGISTER(run, NULL, NULL); +#define REGISTER(_run, _init, _cleanup) static void __init(void) __attribute__ ((naked, used, section (".init8"))); \ + void __init(void) { \ + uint8_t i = 0; \ + while(apps[i].run) ++i; \ + apps[i].run = _run; \ + apps[i].init = _init; \ + apps[i].cleanup = _cleanup; \ + } + +struct app_t { + void (*run)(void); + void (*init)(void); + void (*cleanup)(void); +}; + +extern struct app_t apps[MAX_APPS]; + +#endif /* APP_H */ diff --git a/firmware/include/pentabug/lifecycle.h b/firmware/include/pentabug/lifecycle.h new file mode 100644 index 0000000..597c13f --- /dev/null +++ b/firmware/include/pentabug/lifecycle.h @@ -0,0 +1,34 @@ +#ifndef LIFECYCLE_H +#define LIFECYCLE_H + +#include +#include + +extern jmp_buf app_jmp_buf; +extern uint8_t should_stop; + +// initialize lifecycle, stopped if return != 0 +inline static int enter_app(void) { + should_stop = 0; + return setjmp(app_jmp_buf); +} + +// stop the running app +inline static void stop_app(void) { + longjmp(app_jmp_buf, 1); + for(;;); +} + +// request to stop the app later +inline static void request_stop_app(void) { + should_stop = 1; +} + +// stop app if previously requested +inline static void test_stop_app(void) { + if(should_stop) { + stop_app(); + } +} + +#endif /* LIFECYCLE_H */ diff --git a/firmware/lib/app.c b/firmware/lib/app.c new file mode 100644 index 0000000..36f619c --- /dev/null +++ b/firmware/lib/app.c @@ -0,0 +1,3 @@ +#include + +struct app_t apps[MAX_APPS]; diff --git a/firmware/lib/lifecycle.c b/firmware/lib/lifecycle.c new file mode 100644 index 0000000..3f5491d --- /dev/null +++ b/firmware/lib/lifecycle.c @@ -0,0 +1,4 @@ +#include + +jmp_buf app_jmp_buf; +uint8_t should_stop; diff --git a/firmware/main.c b/firmware/main.c index 80fe084..ac62e32 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -1,172 +1,78 @@ -#include -#include -#include -#include -#define __DELAY_BACKWARD_COMPATIBLE__ -#include +#include +#include #include -#include "main.h" +#include -#define ever (;;) /* awesomnes++ */ +#include +#include -#include "lib/usart.h" -#include "lib/bughal.h" -#include "lib/util.h" -#include "lib/music.h" +static inline void reset_hw(void) { + DDRB = 0; + DDRC = 0; + DDRD = 0; -#include "lib/apps.h" + PORTB = 0; + PORTC = 0; + PORTD = 0; -mode_fun mode_funs[MAX_FUNS] = { NULL }; -uint8_t mode_num = 0; - -/*specialmodes, not in normal mode loop*/ -#define MODE_PWDN mode_num //go to sleep - -uint8_t OpMode = 0; -uint8_t NextMode = 0; - -uint8_t mode_uninitialized = true; -uint8_t mode_last_tick = false; - -/*check if mode should be changed (one of the buttons long pressed)*/ -void modeswitch_poll(void) -{ - if (btn_state(BTNST_LUP, BTN_LEFT)) { - //opmode -- - NextMode = OpMode <= 0 ? mode_num - 1 : OpMode - 1; - button_clear(BTN_LEFT); - } - if (btn_state(BTNST_LUP, BTN_RIGHT)) { - //opmode ++ - NextMode = (OpMode +1) % mode_num; - button_clear(BTN_RIGHT); - } - if ( btn_state(BTNST_LDN, BTN_RIGHT) && - btn_state(BTNST_LDN, BTN_LEFT) ) { - NextMode = MODE_PWDN; - } - return; + PINB = 0; + PINC = 0; + PIND = 0; } -void do_powerDown(void) -{ - static timer_t mytimer; - static uint8_t pwdn_state; - static bool ledRon; - uint8_t oldreg; - if (mode_uninitialized) { - mode_uninitialized = false; - pwdn_state = 0; - timer_set(&mytimer, 5); - set_motor(MOTOR_OFF); - ledRon = true; - }; - if (timer_expired(&mytimer)) { - switch (pwdn_state) { - case 0: - if (ledRon) { - led_on(LED_L); - led_off(LED_R); - } else { - led_off(LED_L); - led_on(LED_R); - }; - ledRon = !ledRon; - timer_set(&mytimer, 6); - if ((btn_state(BTNST_SUP, BTN_RIGHT) - || btn_state(BTNST_LUP, BTN_RIGHT)) - && (btn_state(BTNST_SUP, BTN_LEFT) - || btn_state(BTNST_LUP, BTN_LEFT))) { - //both buttons released - led_off(LED_L | LED_R); - pwdn_state = 1; - timer_set(&mytimer, 10); +static inline void run_app(struct app_t* app) { + if(enter_app()) { + // this is the exit + if(app->cleanup) { + app->cleanup(); + } + + return; + } + + if(app->init) { + app->init(); + } + + for(;;) { + app->run(); + test_stop_app(); + } +} + +int main(void) { + uint8_t app_index = 0; + int8_t direction = 1; + + // we need to get real fast (8MHz) to handle 38kHz IR frequency ... + + CLKPR = 0b10000000; + CLKPR = 0b00000000; + + // cycle through apps + + for(;;) { + reset_hw(); + + run_app(&apps[app_index]); + + for(;;); + + if(direction > 0) { + app_index++; + + if(apps[app_index].run == NULL) { + app_index = 0; } - break; - case 1: - music_setNote(NOTE_A, 4); - timer_set(&mytimer, 10); - pwdn_state++; - break; - case 2: - music_setNote(NOTE_F, 4); - timer_set(&mytimer, 5); - pwdn_state++; - break; - case 3: - music_setNote(NOTE_D, 3); - timer_set(&mytimer, 15); - pwdn_state++; - break; - case 4: - music_setNote(NOTE_PAUSE, 4); - timer_set(&mytimer, 1); - pwdn_state++; - break; - case 5: //now we can really power down - // lets switch everything off - oldreg = PCMSK2; - PCIFR = 0; - PCICR |= (1< $(PROJECT).hex" + @$(OBJCOPY) -O ihex -R .eeprom $(PROJECT).elf $(PROJECT).hex + +$(PROJECT).elf: $(OBJECTS) Makefile + @echo " \033[1;34mLink \033[0m (\033[1;33m $(OBJECTS)\033[0m) -> $(PROJECT).elf" + @$(GCC) $(OBJECTS) $(LDFLAGS) -o $(PROJECT).elf + +clean: + $(REMOVE) $(OBJECTS) + $(REMOVE) $(LSTFILES) + $(REMOVE) $(PROJECT).hex + $(REMOVE) $(PROJECT).elf + +######################################################################### + +%.o: %.c Makefile $(HEADERS) + @echo " \033[1;34mCompile\033[0m $<" + @$(GCC) $(GCFLAGS) -o $@ -c $< + + +######################################################################### + +fuse: + $(AVRDUDE) -p m88 -F -c usbtiny -v -v -U $(FUSES) + +flash: $(PROJECT).hex Makefile + $(AVRDUDE) -p m88 -F -c usbtiny -B 1 -U flash:w:$(PROJECT).hex + +fljohn: $(PROJECT).hex Makefile + $(AVRDUDE) -p m88 -F -P /dev/serial/by-id/usb-FTDI_USB__-__Serial-if00-port0 -c stk500v2 -v -v -U flash:w:$(PROJECT).hex + +flsmart: $(PROJECT).hex Makefile + $(AVRDUDE) -p m88 -F -P /dev/ttyUSB0 -c stk500v2 -v -v -U flash:w:$(PROJECT).hex + + +.PHONY : clean all fuse flash fljohn + diff --git a/old_firmware/README.md b/old_firmware/README.md new file mode 100644 index 0000000..b1298a8 --- /dev/null +++ b/old_firmware/README.md @@ -0,0 +1,24 @@ +## Firmware + +This firmware is to be flashed to the atmega88 of the pentabug. +The Makefile supports 2 different ways of flashing the firmware image: + +### the serial bootloader way + +With the + + make serflash + +target of the Makefile You can flash the microcontroler via the serial bootloader that is part of the initial firmware. + + +### the isp way + +With the + + make flash + +target of the Makefile you can flash the microcontroler via an isp programmer. +Adjust the avrdude settings to Your programmers needs beforehand. + + diff --git a/firmware/apps/blink.c b/old_firmware/apps/blink.c similarity index 100% rename from firmware/apps/blink.c rename to old_firmware/apps/blink.c diff --git a/firmware/apps/cockroach.c b/old_firmware/apps/cockroach.c similarity index 100% rename from firmware/apps/cockroach.c rename to old_firmware/apps/cockroach.c diff --git a/firmware/apps/crazy_synth.c b/old_firmware/apps/crazy_synth.c similarity index 100% rename from firmware/apps/crazy_synth.c rename to old_firmware/apps/crazy_synth.c diff --git a/firmware/apps/led_sound.c b/old_firmware/apps/led_sound.c similarity index 100% rename from firmware/apps/led_sound.c rename to old_firmware/apps/led_sound.c diff --git a/firmware/apps/mariofx.c b/old_firmware/apps/mariofx.c similarity index 100% rename from firmware/apps/mariofx.c rename to old_firmware/apps/mariofx.c diff --git a/firmware/apps/sound_detection.c b/old_firmware/apps/sound_detection.c similarity index 100% rename from firmware/apps/sound_detection.c rename to old_firmware/apps/sound_detection.c diff --git a/firmware/bootloader/chipdef.h b/old_firmware/bootloader/chipdef.h similarity index 100% rename from firmware/bootloader/chipdef.h rename to old_firmware/bootloader/chipdef.h diff --git a/firmware/bootloader/main.c b/old_firmware/bootloader/main.c similarity index 100% rename from firmware/bootloader/main.c rename to old_firmware/bootloader/main.c diff --git a/firmware/bootloader/makefile b/old_firmware/bootloader/makefile similarity index 100% rename from firmware/bootloader/makefile rename to old_firmware/bootloader/makefile diff --git a/firmware/bootloader/mega88.h b/old_firmware/bootloader/mega88.h similarity index 100% rename from firmware/bootloader/mega88.h rename to old_firmware/bootloader/mega88.h diff --git a/firmware/disabled_apps/crazy.c b/old_firmware/disabled_apps/crazy.c similarity index 100% rename from firmware/disabled_apps/crazy.c rename to old_firmware/disabled_apps/crazy.c diff --git a/firmware/lib/apps.h b/old_firmware/lib/apps.h similarity index 100% rename from firmware/lib/apps.h rename to old_firmware/lib/apps.h diff --git a/firmware/lib/bughal.c b/old_firmware/lib/bughal.c similarity index 100% rename from firmware/lib/bughal.c rename to old_firmware/lib/bughal.c diff --git a/firmware/lib/bughal.h b/old_firmware/lib/bughal.h similarity index 100% rename from firmware/lib/bughal.h rename to old_firmware/lib/bughal.h diff --git a/firmware/lib/freq_table.c b/old_firmware/lib/freq_table.c similarity index 100% rename from firmware/lib/freq_table.c rename to old_firmware/lib/freq_table.c diff --git a/firmware/lib/freq_table.h b/old_firmware/lib/freq_table.h similarity index 100% rename from firmware/lib/freq_table.h rename to old_firmware/lib/freq_table.h diff --git a/firmware/lib/music.c b/old_firmware/lib/music.c similarity index 100% rename from firmware/lib/music.c rename to old_firmware/lib/music.c diff --git a/firmware/lib/music.h b/old_firmware/lib/music.h similarity index 100% rename from firmware/lib/music.h rename to old_firmware/lib/music.h diff --git a/firmware/lib/timer.c b/old_firmware/lib/timer.c similarity index 100% rename from firmware/lib/timer.c rename to old_firmware/lib/timer.c diff --git a/firmware/lib/timer.h b/old_firmware/lib/timer.h similarity index 100% rename from firmware/lib/timer.h rename to old_firmware/lib/timer.h diff --git a/firmware/lib/usart.c b/old_firmware/lib/usart.c similarity index 100% rename from firmware/lib/usart.c rename to old_firmware/lib/usart.c diff --git a/firmware/lib/usart.h b/old_firmware/lib/usart.h similarity index 100% rename from firmware/lib/usart.h rename to old_firmware/lib/usart.h diff --git a/firmware/lib/util.c b/old_firmware/lib/util.c similarity index 100% rename from firmware/lib/util.c rename to old_firmware/lib/util.c diff --git a/firmware/lib/util.h b/old_firmware/lib/util.h similarity index 100% rename from firmware/lib/util.h rename to old_firmware/lib/util.h diff --git a/old_firmware/main.c b/old_firmware/main.c new file mode 100644 index 0000000..80fe084 --- /dev/null +++ b/old_firmware/main.c @@ -0,0 +1,172 @@ +#include +#include +#include +#include +#define __DELAY_BACKWARD_COMPATIBLE__ +#include +#include + +#include "main.h" + +#define ever (;;) /* awesomnes++ */ + +#include "lib/usart.h" +#include "lib/bughal.h" +#include "lib/util.h" +#include "lib/music.h" + +#include "lib/apps.h" + +mode_fun mode_funs[MAX_FUNS] = { NULL }; +uint8_t mode_num = 0; + +/*specialmodes, not in normal mode loop*/ +#define MODE_PWDN mode_num //go to sleep + +uint8_t OpMode = 0; +uint8_t NextMode = 0; + +uint8_t mode_uninitialized = true; +uint8_t mode_last_tick = false; + +/*check if mode should be changed (one of the buttons long pressed)*/ +void modeswitch_poll(void) +{ + if (btn_state(BTNST_LUP, BTN_LEFT)) { + //opmode -- + NextMode = OpMode <= 0 ? mode_num - 1 : OpMode - 1; + button_clear(BTN_LEFT); + } + if (btn_state(BTNST_LUP, BTN_RIGHT)) { + //opmode ++ + NextMode = (OpMode +1) % mode_num; + button_clear(BTN_RIGHT); + } + if ( btn_state(BTNST_LDN, BTN_RIGHT) && + btn_state(BTNST_LDN, BTN_LEFT) ) { + NextMode = MODE_PWDN; + } + return; +} + +void do_powerDown(void) +{ + static timer_t mytimer; + static uint8_t pwdn_state; + static bool ledRon; + uint8_t oldreg; + if (mode_uninitialized) { + mode_uninitialized = false; + pwdn_state = 0; + timer_set(&mytimer, 5); + set_motor(MOTOR_OFF); + ledRon = true; + }; + if (timer_expired(&mytimer)) { + switch (pwdn_state) { + case 0: + if (ledRon) { + led_on(LED_L); + led_off(LED_R); + } else { + led_off(LED_L); + led_on(LED_R); + }; + ledRon = !ledRon; + timer_set(&mytimer, 6); + if ((btn_state(BTNST_SUP, BTN_RIGHT) + || btn_state(BTNST_LUP, BTN_RIGHT)) + && (btn_state(BTNST_SUP, BTN_LEFT) + || btn_state(BTNST_LUP, BTN_LEFT))) { + //both buttons released + led_off(LED_L | LED_R); + pwdn_state = 1; + timer_set(&mytimer, 10); + } + break; + case 1: + music_setNote(NOTE_A, 4); + timer_set(&mytimer, 10); + pwdn_state++; + break; + case 2: + music_setNote(NOTE_F, 4); + timer_set(&mytimer, 5); + pwdn_state++; + break; + case 3: + music_setNote(NOTE_D, 3); + timer_set(&mytimer, 15); + pwdn_state++; + break; + case 4: + music_setNote(NOTE_PAUSE, 4); + timer_set(&mytimer, 1); + pwdn_state++; + break; + case 5: //now we can really power down + // lets switch everything off + oldreg = PCMSK2; + PCIFR = 0; + PCICR |= (1<