#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/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 /*specialmodes, not in normal mode loop*/ #define MODE_PWDN 42 //go to sleep uint8_t OpMode = MODE1; uint8_t NextMode = MODE1; bool mode_uninitialized = true; /*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; button_clear(BTN_LEFT); } if (btn_state(BTNST_LUP, BTN_RIGHT)) { //opmode ++ NextMode = (OpMode +1) % NUM_MODES; button_clear(BTN_RIGHT); } if ( btn_state(BTNST_LDN, BTN_RIGHT) && btn_state(BTNST_LDN, BTN_LEFT) ) { NextMode = MODE_PWDN; } 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; static uint8_t pwdn_state; static bool ledRon; if (mode_uninitialized) { mode_uninitialized = false; pwdn_state = 0; timer_set(&mytimer, 5); 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 set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sei(); sleep_cpu(); sleep_disable(); NextMode = MODE2; break; default: break; } //end switch } //end timer expired } // end do_powerDown void __attribute__ ((noreturn)) main(void) { /* hardware initialisation: */ init_leds(); init_buzzr(); init_switch(); USART0_Init(); init_motor(); /* software initialisation */ timer_init(); music_init(); /* here the show begins: */ sei(); for ever { //main polling loop; 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_uninitialized = true; OpMode = NextMode; } } }