diff --git a/firmware/Makefile b/firmware/Makefile index f0a450c..4a13800 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -8,7 +8,7 @@ FUSES = lfuse:w:0xe2:m -U hfuse:w:0xdf:m -U efuse:w:0x01:m ######################################################################### -SRC=$(wildcard lib/*.c *.c) +SRC=$(wildcard lib/*.c *.c apps/*.c) OBJECTS= $(SRC:.c=.o) LSTFILES= $(SRC:.c=.lst) HEADERS=$(wildcard lib/*.h *.h) diff --git a/firmware/apps/blink.c b/firmware/apps/blink.c new file mode 100644 index 0000000..e43632b --- /dev/null +++ b/firmware/apps/blink.c @@ -0,0 +1,55 @@ +#include +#include +#include + +#include "../lib/apps.h" +#include "../lib/bughal.h" +#include "../lib/util.h" +#include "../lib/music.h" + +/** + * just blink mode + * - left/right button switch motor off/on + */ +static void blink(void) +{ + static timer_t mytimer; + static bool blink; + if (mode_uninitialized) { + init_leds(); + mode_uninitialized = false; + music_setNote(NOTE_PAUSE, 4); //mute + set_motor(MOTOR_OFF); + timer_set(&mytimer, 10); + blink = false; + } + + if (timer_expired(&mytimer)) { + if (!blink) { + /*lets blink*/ + led_on(LED_L | LED_R); + timer_set(&mytimer, 1); + blink = true; + } else { + /*stop blink*/ + led_off(LED_L | LED_R); + timer_set(&mytimer, 123); + blink = false; + } + + }//end if timer_expired + + if (btn_state(BTNST_SUP, BTN_LEFT)) { + button_clear(BTN_LEFT); + set_motor(MOTOR_OFF); + + } + if (btn_state(BTNST_SUP, BTN_RIGHT)) { + button_clear(BTN_RIGHT); + set_motor(MOTOR_ON); + } + +} + +REGISTER(blink) + diff --git a/firmware/apps/crazy.c b/firmware/apps/crazy.c new file mode 100644 index 0000000..c3afed4 --- /dev/null +++ b/firmware/apps/crazy.c @@ -0,0 +1,63 @@ +#include +#include +#include + +#include "../lib/apps.h" +#include "../lib/bughal.h" +#include "../lib/util.h" +#include "../lib/music.h" + +/** + * crazymoves mode + * - play random sounds and move in random fashion + */ +static void crazy(void) +{ + static timer_t mytimer; + uint8_t max = 50; + uint8_t min = 5; + uint16_t maxfreq = 5000; + uint16_t minfreq = 1000; + + if (mode_uninitialized) { + mode_uninitialized = false; + music_setNote(NOTE_PAUSE, 4); //mute + timer_set(&mytimer, 10); + init_leds(); + led_off(LED_L | LED_R); + set_motor(MOTOR_OFF); + } + + if (timer_expired(&mytimer)) { + set_motor(MOTOR_OFF); + music_setNote(NOTE_PAUSE, 0); //mute + /*set random led*/ + switch (rand() % 4) { + case 0: led_on(LED_L); break; + case 1: led_on(LED_R); break; + case 2: led_on(LED_L | LED_R); break; + default: led_off(LED_L | LED_R); break; + }; + /*decide if to switch motor on (40% chance)*/ + if (rand() % 5 > 2) + set_motor(MOTOR_ON); + + /*decide if to play sound (70% chance)*/ + if (rand() % 10 > 2) { + music_setNote((rand() % (maxfreq - minfreq)) + minfreq, + 0); + + } + + timer_set(&mytimer, (rand() % (max - min)) + min); + }//end if timer_expired + + /*deinialisation */ + if (mode_last_tick) { + set_motor(MOTOR_OFF); + music_setNote(NOTE_PAUSE, 0); //mute + } +} + +REGISTER(crazy) + diff --git a/firmware/apps/crazy_synth.c b/firmware/apps/crazy_synth.c new file mode 100644 index 0000000..b591a6a --- /dev/null +++ b/firmware/apps/crazy_synth.c @@ -0,0 +1,32 @@ +#include +#include +#include + +#include "../lib/apps.h" +#include "../lib/bughal.h" +#include "../lib/util.h" +#include "../lib/music.h" +#include "../lib/synth.h" + +/** + * do crazy synthesizer mode + * + */ +static void crazy_synth(void) +{ + /* initialisation required */ + if (mode_uninitialized) { + mode_uninitialized = false; + synth_init(); + } + + /*deinialisation required */ + if (mode_last_tick) { + synth_deinit(); + } + + return; +} + +REGISTER(crazy_synth) + diff --git a/firmware/apps/geiger.c b/firmware/apps/geiger.c new file mode 100644 index 0000000..5ae6279 --- /dev/null +++ b/firmware/apps/geiger.c @@ -0,0 +1,57 @@ +#include +#include +#include + +#include "../lib/apps.h" +#include "../lib/bughal.h" +#include "../lib/util.h" +#include "../lib/music.h" +#include "../lib/synth.h" +#include "../lib/usart.h" + +/** + * ggrbug mode + * - simulate geiger counter sounds + */ +static void geiger(void) +{ + uint8_t max = 200; + uint8_t min = 10; + + static timer_t mytimer; + static bool blink; + if (mode_uninitialized) { + init_leds(); + music_setNote(NOTE_PAUSE, 0); + mode_uninitialized = false; + timer_set(&mytimer, 10); + blink = false; + }; + if (timer_expired(&mytimer)) { + if (!blink) { + /*lets blink*/ + int i = (rand() % 3); + switch (i) { + case 0: led_on(LED_L); break; + case 1: led_on(LED_R); break; + default: led_on(LED_L | LED_R); break; + }; + if (rand() % 10 > 8) + set_motor(MOTOR_ON); + music_setNote(NOTE_C, 5); + timer_set(&mytimer, 2); + blink = true; + } else { + /*stop blink*/ + led_off(LED_L | LED_R); + set_motor(MOTOR_OFF); + music_setNote(NOTE_PAUSE, 0); + timer_set(&mytimer, (rand() % (max - min)) + min); + blink = false; + } + + }//end if timer_expired + +} + +REGISTER(geiger) diff --git a/firmware/apps/led_sound.c b/firmware/apps/led_sound.c new file mode 100644 index 0000000..0f88e54 --- /dev/null +++ b/firmware/apps/led_sound.c @@ -0,0 +1,74 @@ +#include +#include +#include + +#include "../lib/apps.h" +#include "../lib/bughal.h" +#include "../lib/util.h" +#include "../lib/music.h" +#include "../lib/synth.h" +#include "../lib/usart.h" + +static void led_sound(void) +{ + static bool discharge; + static timer_t mytimer; + uint16_t led1; + uint16_t led2; + + if (mode_uninitialized) { + mode_uninitialized = false; + set_motor(MOTOR_OFF); + ADMUX = (1 << REFS0); // use VCC reference + ADCSRA = (1 << ADPS1) | (1 << ADPS0); // prescaler F_CPU/8 + ADCSRA |= (1 << ADEN); // ADC enable - turn it on + /*do one conversion*/ + ADCSRA |= (1 << ADSC); + while (ADCSRA & (1 << ADSC)) { + /*wait for conversion to end */ + } + uint16_t __attribute__ ((unused)) dummy = ADCW; //read once + timer_set(&mytimer, 10); + discharge = true; + } + if (timer_expired(&mytimer)) { + if (discharge) { + DDRC |= (1 << PORTC0) | (1 << PORTC1) | //set LED Ports to output: + (1 << PORTC2) | (1 << PORTC3); + /*discharge*/ + PORTC = (PORTC & 0b11110000); + /*set C0 and C2 to input (disable pullups)*/ + DDRC &= ~((1 << PORTC0) | (1 << PORTC2)); //set Led Ports to input + /*pull ups off*/ + PORTC &= ~((1 << PORTC0) | (1 << PORTC2)); + discharge = false; + } else { + /*single measurement*/ + ADMUX = (ADMUX & ~(0x1F)) | 0; // select channel 0 + ADCSRA |= (1 << ADSC); // start single conversion + while (ADCSRA & (1 << ADSC)) ; // wait for conversion to end + led1 = ADCW; // read result + + ADMUX = (ADMUX & ~(0x1F)) | 2; // select channel 2 + ADCSRA |= (1 << ADSC); // start single conversion + while (ADCSRA & (1 << ADSC)) ; // wait for conversion to end + led2 = ADCW; // read result +#if 0 + USART0_putc('1'); + USART0_putc(':'); + USART0_put_uint16(led1); + USART0_crlf(); + USART0_putc('2'); + USART0_putc(':'); + USART0_put_uint16(led2); + USART0_crlf(); +#endif + music_setNote(400 + + ((0x1ff - led1) + (0x1ff - led2)) * 5, 0); + discharge = true; + } + timer_set(&mytimer, 2); //relaunch timer + } //end if timer_expired +} //end mode5 + +REGISTER(led_sound) diff --git a/firmware/apps/sound_detection.c b/firmware/apps/sound_detection.c new file mode 100644 index 0000000..00f6e78 --- /dev/null +++ b/firmware/apps/sound_detection.c @@ -0,0 +1,86 @@ +#include +#include +#include + +#include "../lib/apps.h" +#include "../lib/bughal.h" +#include "../lib/util.h" +#include "../lib/music.h" +#include "../lib/synth.h" +#include "../lib/usart.h" + +/** + * sound detection mode + * beeps,blinks and moves when sound is detected + * - beep on/off left switch (short) + * - motor on/off right switch (short) + */ +static void sound_detection(void) +{ + static timer_t mytimer; + static uint16_t maxval; // maximum of ADC values read during the las timer interval + static uint16_t lastmaxval; // maximum of values during last timer interval + uint16_t curval; // value on D5 (pin of piezo,the other is on GND) + static bool signaling; // are we currently signaling (beeping, blinking etc...) + static bool sound_on; // should sound be on when signaling + static bool motor_on; // should motor be on when signaling + + if (mode_uninitialized) { //init after mode change + maxval = 0; + lastmaxval = 0; + mode_uninitialized = false; + signaling = false; + sound_on = true; + motor_on = true; + init_mic(); + init_leds(); + timer_set(&mytimer, 10); + } + /*single ADC measurement*/ + curval = ADCW; // read result + maxval = (curval > maxval) ? curval : maxval; + + /*check for Buttons*/ + if (btn_state(BTNST_SUP, BTN_LEFT)) { + button_clear(BTN_LEFT); + sound_on = !sound_on; + } + if (btn_state(BTNST_SUP, BTN_RIGHT)) { + button_clear(BTN_RIGHT); + motor_on = !motor_on; + } + if (timer_expired(&mytimer)) { + if (signaling) { + //turn off sound + music_setNote(NOTE_PAUSE, 0); //mute + set_motor(MOTOR_OFF); + //re-init mic + init_mic(); + led_off(LED_R | LED_L); + timer_set(&mytimer, 1); + signaling = false; + lastmaxval = 10000; + } else { //sound was off wer're in measuring mode + if (maxval > lastmaxval) { + USART0_put_uint16(maxval); + USART0_crlf(); + led_on(LED_R | LED_L); + init_buzzr(); //buzzr to output + if (sound_on) + music_setNote(NOTE_C, 5); + if (motor_on) + set_motor(MOTOR_ON); + signaling = true; + timer_set(&mytimer, 5); //sound duration + } else { + timer_set(&mytimer, 1); + } + lastmaxval = maxval; + maxval = 0; + }//end if soundon + + }//end if timer_expired + +} /* end mode0 */ + +REGISTER(sound_detection) diff --git a/firmware/lib/apps.h b/firmware/lib/apps.h new file mode 100644 index 0000000..4f9be71 --- /dev/null +++ b/firmware/lib/apps.h @@ -0,0 +1,21 @@ +#ifndef APPS_H +#define APPS_H + +#include + +#define MAX_FUNS 16 +#define REGISTER(fun) static void init(void) __attribute__ ((naked, used, section (".init8"))); \ + void init(void) { \ + mode_funs[mode_num] = fun; \ + ++mode_num; \ + } \ + +typedef void (*mode_fun)(void); + +extern mode_fun mode_funs[MAX_FUNS]; +extern uint8_t mode_num; + +extern uint8_t mode_uninitialized; +extern uint8_t mode_last_tick; + +#endif /* APPS_H */ diff --git a/firmware/main.c b/firmware/main.c index 0fc0b78..91e6653 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -16,34 +16,31 @@ #include "lib/music.h" #include "lib/synth.h" -//operartion modes -#define MODE0 0 -#define MODE1 1 -#define MODE2 2 -#define MODE3 3 -#define MODE4 4 -#define MODE5 5 -#define NUM_MODES 6 +#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 42 //go to sleep +#define MODE_PWDN mode_num //go to sleep -uint8_t OpMode = MODE1; -uint8_t NextMode = MODE1; +uint8_t OpMode = 0; +uint8_t NextMode = 0; -bool mode_uninitialized = true; +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 -1) % NUM_MODES; + NextMode = (OpMode -1) % mode_num; button_clear(BTN_LEFT); } if (btn_state(BTNST_LUP, BTN_RIGHT)) { //opmode ++ - NextMode = (OpMode +1) % NUM_MODES; + NextMode = (OpMode +1) % mode_num; button_clear(BTN_RIGHT); } if ( btn_state(BTNST_LDN, BTN_RIGHT) && @@ -53,303 +50,6 @@ void modeswitch_poll(void) return; } -/** - * sound detection mode - * beeps,blinks and moves when sound is detected - * - beep on/off left switch (short) - * - motor on/off right switch (short) - */ -void do_mode0(void) -{ - static timer_t mytimer; - static uint16_t maxval; // maximum of ADC values read during the las timer interval - static uint16_t lastmaxval; // maximum of values during last timer interval - uint16_t curval; // value on D5 (pin of piezo,the other is on GND) - static bool signaling; // are we currently signaling (beeping, blinking etc...) - static bool sound_on; // should sound be on when signaling - static bool motor_on; // should motor be on when signaling - - if (mode_uninitialized) { //init after mode change - maxval = 0; - lastmaxval = 0; - mode_uninitialized = false; - signaling = false; - sound_on = true; - motor_on = true; - init_mic(); - init_leds(); - timer_set(&mytimer, 10); - } - /*single ADC measurement*/ - curval = ADCW; // read result - maxval = (curval > maxval) ? curval : maxval; - - /*check for Buttons*/ - if (btn_state(BTNST_SUP, BTN_LEFT)) { - button_clear(BTN_LEFT); - sound_on = !sound_on; - } - if (btn_state(BTNST_SUP, BTN_RIGHT)) { - button_clear(BTN_RIGHT); - motor_on = !motor_on; - } - if (timer_expired(&mytimer)) { - if (signaling) { - //turn off sound - music_setNote(NOTE_PAUSE, 0); //mute - set_motor(MOTOR_OFF); - //re-init mic - init_mic(); - led_off(LED_R | LED_L); - timer_set(&mytimer, 1); - signaling = false; - lastmaxval = 10000; - } else { //sound was off wer're in measuring mode - if (maxval > lastmaxval) { - USART0_put_uint16(maxval); - USART0_crlf(); - led_on(LED_R | LED_L); - init_buzzr(); //buzzr to output - if (sound_on) - music_setNote(NOTE_C, 5); - if (motor_on) - set_motor(MOTOR_ON); - signaling = true; - timer_set(&mytimer, 5); //sound duration - } else { - timer_set(&mytimer, 1); - } - lastmaxval = maxval; - maxval = 0; - }//end if soundon - - }//end if timer_expired - -} /* end mode0 */ - -/** - * do crazy synthesizer mode - * - */ -void do_mode1(void) -{ - /* initialisation required */ - if (mode_uninitialized) { - mode_uninitialized = false; - synth_init(); - } - - /*deinialisation required */ - if (OpMode != NextMode) { - synth_deinit(); - } - - return; -} - -/** - * crazymoves mode - * - play random sounds and move in random fashion - */ -void do_mode2(void) -{ - static timer_t mytimer; - uint8_t max = 50; - uint8_t min = 5; - uint16_t maxfreq = 5000; - uint16_t minfreq = 1000; - - if (mode_uninitialized) { - mode_uninitialized = false; - music_setNote(NOTE_PAUSE, 4); //mute - timer_set(&mytimer, 10); - init_leds(); - led_off(LED_L | LED_R); - set_motor(MOTOR_OFF); - } - - if (timer_expired(&mytimer)) { - set_motor(MOTOR_OFF); - music_setNote(NOTE_PAUSE, 0); //mute - /*set random led*/ - switch (rand() % 4) { - case 0: led_on(LED_L); break; - case 1: led_on(LED_R); break; - case 2: led_on(LED_L | LED_R); break; - default: led_off(LED_L | LED_R); break; - }; - /*decide if to switch motor on (40% chance)*/ - if (rand() % 5 > 2) - set_motor(MOTOR_ON); - - /*decide if to play sound (70% chance)*/ - if (rand() % 10 > 2) { - music_setNote((rand() % (maxfreq - minfreq)) + minfreq, - 0); - - } - - timer_set(&mytimer, (rand() % (max - min)) + min); - }//end if timer_expired - - /*deinialisation */ - if (OpMode != NextMode) { - set_motor(MOTOR_OFF); - music_setNote(NOTE_PAUSE, 0); //mute - } -} - -/** - * just blink mode - * - left/right button switch motor off/on - */ -void do_mode3(void) -{ - static timer_t mytimer; - static bool blink; - if (mode_uninitialized) { - init_leds(); - mode_uninitialized = false; - music_setNote(NOTE_PAUSE, 4); //mute - set_motor(MOTOR_OFF); - timer_set(&mytimer, 10); - blink = false; - } - - if (timer_expired(&mytimer)) { - if (!blink) { - /*lets blink*/ - led_on(LED_L | LED_R); - timer_set(&mytimer, 1); - blink = true; - } else { - /*stop blink*/ - led_off(LED_L | LED_R); - timer_set(&mytimer, 123); - blink = false; - } - - }//end if timer_expired - - if (btn_state(BTNST_SUP, BTN_LEFT)) { - button_clear(BTN_LEFT); - set_motor(MOTOR_OFF); - - } - if (btn_state(BTNST_SUP, BTN_RIGHT)) { - button_clear(BTN_RIGHT); - set_motor(MOTOR_ON); - } - -} - -/** - * ggrbug mode - * - simulate geiger counter sounds - */ -void do_mode4(void) -{ - uint8_t max = 200; - uint8_t min = 10; - - static timer_t mytimer; - static bool blink; - if (mode_uninitialized) { - init_leds(); - music_setNote(NOTE_PAUSE, 0); - mode_uninitialized = false; - timer_set(&mytimer, 10); - blink = false; - }; - if (timer_expired(&mytimer)) { - if (!blink) { - /*lets blink*/ - int i = (rand() % 3); - switch (i) { - case 0: led_on(LED_L); break; - case 1: led_on(LED_R); break; - default: led_on(LED_L | LED_R); break; - }; - if (rand() % 10 > 8) - set_motor(MOTOR_ON); - music_setNote(NOTE_C, 5); - timer_set(&mytimer, 2); - blink = true; - } else { - /*stop blink*/ - led_off(LED_L | LED_R); - set_motor(MOTOR_OFF); - music_setNote(NOTE_PAUSE, 0); - timer_set(&mytimer, (rand() % (max - min)) + min); - blink = false; - } - - }//end if timer_expired - -} - -void do_mode5(void) -{ - static bool discharge; - static timer_t mytimer; - uint16_t led1; - uint16_t led2; - - if (mode_uninitialized) { - mode_uninitialized = false; - set_motor(MOTOR_OFF); - ADMUX = (1 << REFS0); // use VCC reference - ADCSRA = (1 << ADPS1) | (1 << ADPS0); // prescaler F_CPU/8 - ADCSRA |= (1 << ADEN); // ADC enable - turn it on - /*do one conversion*/ - ADCSRA |= (1 << ADSC); - while (ADCSRA & (1 << ADSC)) { - /*wait for conversion to end */ - } - uint16_t __attribute__ ((unused)) dummy = ADCW; //read once - timer_set(&mytimer, 10); - discharge = true; - } - if (timer_expired(&mytimer)) { - if (discharge) { - DDRC |= (1 << PORTC0) | (1 << PORTC1) | //set LED Ports to output: - (1 << PORTC2) | (1 << PORTC3); - /*discharge*/ - PORTC = (PORTC & 0b11110000); - /*set C0 and C2 to input (disable pullups)*/ - DDRC &= ~((1 << PORTC0) | (1 << PORTC2)); //set Led Ports to input - /*pull ups off*/ - PORTC &= ~((1 << PORTC0) | (1 << PORTC2)); - discharge = false; - } else { - /*single measurement*/ - ADMUX = (ADMUX & ~(0x1F)) | 0; // select channel 0 - ADCSRA |= (1 << ADSC); // start single conversion - while (ADCSRA & (1 << ADSC)) ; // wait for conversion to end - led1 = ADCW; // read result - - ADMUX = (ADMUX & ~(0x1F)) | 2; // select channel 2 - ADCSRA |= (1 << ADSC); // start single conversion - while (ADCSRA & (1 << ADSC)) ; // wait for conversion to end - led2 = ADCW; // read result -#if 0 - USART0_putc('1'); - USART0_putc(':'); - USART0_put_uint16(led1); - USART0_crlf(); - USART0_putc('2'); - USART0_putc(':'); - USART0_put_uint16(led2); - USART0_crlf(); -#endif - music_setNote(400 + - ((0x1ff - led1) + (0x1ff - led2)) * 5, 0); - discharge = true; - } - timer_set(&mytimer, 2); //relaunch timer - } //end if timer_expired -} //end mode5 - void do_powerDown(void) { static timer_t mytimer; @@ -411,7 +111,7 @@ void do_powerDown(void) sei(); sleep_cpu(); sleep_disable(); - NextMode = MODE2; + NextMode = 0; break; default: break; @@ -440,16 +140,18 @@ void __attribute__ ((noreturn)) main(void) button_poll(); modeswitch_poll(); - switch (OpMode) { - case MODE1 : do_mode1(); break ; - case MODE2 : do_mode2(); break ; - case MODE3 : do_mode3(); break ; - case MODE4 : do_mode4(); break ; - case MODE5 : do_mode5(); break ; - case MODE_PWDN : do_powerDown(); break ; - default : do_mode0(); break ; - } if (OpMode != NextMode){ + mode_last_tick = true; + } + + if(OpMode < mode_num) { + mode_funs[OpMode](); + } else { + do_powerDown(); + } + + if (OpMode != NextMode){ + mode_last_tick = false; mode_uninitialized = true; OpMode = NextMode; }