pentabug/firmware/main.c

451 lines
9.9 KiB
C
Raw Normal View History

2012-07-17 01:05:27 +02:00
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
2012-10-01 21:39:25 +02:00
#define __DELAY_BACKWARD_COMPATIBLE__
2012-07-17 01:05:27 +02:00
#include <util/delay.h>
#include <stdlib.h>
#include "main.h"
2012-10-10 04:15:06 +02:00
#define ever (;;) /* awesomnes++ */
2012-09-02 21:53:11 +02:00
#include "lib/usart.h"
2012-09-02 23:49:57 +02:00
#include "lib/bughal.h"
2012-10-01 21:39:25 +02:00
#include "lib/util.h"
#include "lib/music.h"
2012-10-10 04:15:06 +02:00
#include "lib/synth.h"
2012-07-26 01:34:49 +02:00
//operartion modes
#define MODE0 0
#define MODE1 1
#define MODE2 2
#define MODE3 3
2012-10-05 21:12:26 +02:00
#define MODE4 4
2012-10-10 04:15:06 +02:00
#define MODE5 5
#define NUM_MODES 6
//special modes, not in normal mode loop
#define MODE_PWDN 42 //go to sleep
2012-10-10 05:12:38 +02:00
uint8_t OpMode = MODE1;
uint8_t NextMode = MODE1;
2012-10-10 04:15:06 +02:00
bool mode_uninitialized = true;
2012-10-07 00:52:53 +02:00
// check if mode should be changed (one of the buttons long pressed)
2012-10-10 04:15:06 +02:00
void modeswitch_poll(void)
{
2012-10-07 00:52:53 +02:00
if (btn_state(BTNST_LUP, BTN_LEFT)) {
//opmode -
2012-10-10 04:15:06 +02:00
NextMode = (0 == OpMode) ? (NUM_MODES - 1) : (OpMode - 1);
//mode_uninitialized = true;
2012-10-07 00:52:53 +02:00
button_clear(BTN_LEFT);
};
if (btn_state(BTNST_LUP, BTN_RIGHT)) {
//opmode +
//mode_uninitialized = true;
2012-10-10 04:15:06 +02:00
NextMode = ((NUM_MODES - 1) == OpMode) ? 0 : (OpMode + 1);
2012-10-07 00:52:53 +02:00
button_clear(BTN_RIGHT);
};
if (btn_state(BTNST_LDN,BTN_RIGHT) && btn_state(BTNST_LDN,BTN_LEFT)){
NextMode = MODE_PWDN;
};
2012-10-07 00:52:53 +02:00
return;
}
2012-10-10 04:15:06 +02:00
/**
* sound detection mode
* beeps,blinks and moves when sound is detected
2012-10-07 17:16:24 +02:00
* - beep on/off left switch (short)
* - motor on/off right switch (short)
*/
2012-10-10 04:15:06 +02:00
void do_mode0(void)
{
2012-10-07 00:52:53 +02:00
static timer_t mytimer;
2012-10-10 05:12:38 +02:00
static uint16_t maxval; //maximum of ADC values read during the las timer interval
2012-10-10 04:15:06 +02:00
static uint16_t lastmaxval; //maximum of values during last timer interval
2012-10-10 05:12:38 +02:00
uint16_t curval; //current value on D5 (one pin of the 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
2012-10-10 04:15:06 +02:00
if (mode_uninitialized) { //init after mode change
2012-10-07 00:52:53 +02:00
maxval = 0;
lastmaxval = 000;
2012-10-10 04:15:06 +02:00
mode_uninitialized = false;
2012-10-07 00:52:53 +02:00
signaling = false;
sound_on = true;
motor_on = true;
init_mic();
init_leds();
timer_set(&mytimer, 10);
2012-10-10 04:15:06 +02:00
}
// single ADC measurement
2012-10-10 04:15:06 +02:00
curval = ADCW; // read result
2012-10-07 00:52:53 +02:00
maxval = (curval > maxval) ? curval : maxval;
2012-10-07 00:52:53 +02:00
//check for Buttons
if (btn_state(BTNST_SUP, BTN_LEFT)) {
button_clear(BTN_LEFT);
sound_on = !sound_on;
2012-10-10 05:12:38 +02:00
}
2012-10-07 00:52:53 +02:00
if (btn_state(BTNST_SUP, BTN_RIGHT)) {
button_clear(BTN_RIGHT);
motor_on = !motor_on;
2012-10-10 05:12:38 +02:00
}
2012-10-07 00:52:53 +02:00
if (timer_expired(&mytimer)) {
if (signaling) {
//turn off sound
2012-10-10 04:15:06 +02:00
music_setNote(NOTE_PAUSE, 0); //mute
2012-10-07 00:52:53 +02:00
set_motor(MOTOR_OFF);
//re-init mic
init_mic();
led_off(LED_R | LED_L);
timer_set(&mytimer, 1);
signaling = false;
lastmaxval = 10000;
2012-10-10 04:15:06 +02:00
} else { //sound was off wer're in measuring mode
2012-10-07 00:52:53 +02:00
if (maxval > lastmaxval) {
USART0_put_uint16(maxval);
USART0_crlf();
led_on(LED_R | LED_L);
2012-10-10 04:15:06 +02:00
init_buzzr(); //buzzr to output
2012-10-07 00:52:53 +02:00
if (sound_on)
music_setNote(NOTE_C, 5);
if (motor_on)
set_motor(MOTOR_ON);
signaling = true;
2012-10-10 04:15:06 +02:00
timer_set(&mytimer, 5); //sound duration
2012-10-07 00:52:53 +02:00
} else {
timer_set(&mytimer, 1);
2012-10-10 04:15:06 +02:00
}
2012-10-07 00:52:53 +02:00
lastmaxval = maxval;
2012-10-10 05:12:38 +02:00
maxval = 0;
}//end if soundon
2012-10-07 00:52:53 +02:00
2012-10-10 05:12:38 +02:00
}//end if timer_expired
2012-10-05 21:12:26 +02:00
2012-10-10 04:15:06 +02:00
} /* end mode0 */
2012-10-07 00:52:53 +02:00
2012-10-10 04:15:06 +02:00
/**
2012-10-10 05:12:38 +02:00
* do crazy synthesizer mode
2012-10-10 04:15:06 +02:00
*
2012-10-07 17:16:24 +02:00
*/
2012-10-10 04:15:06 +02:00
void do_mode1(void)
{
if (mode_uninitialized) {
mode_uninitialized = false;
synth_init();
2012-10-10 05:12:38 +02:00
}
2012-10-07 17:16:24 +02:00
2012-10-10 04:15:06 +02:00
/*deinialisation required*/
if(OpMode != NextMode){
synth_deinit();
}
2012-10-10 05:12:38 +02:00
2012-10-10 04:15:06 +02:00
return;
2012-10-07 00:52:53 +02:00
}
2012-10-10 04:15:06 +02:00
/**
* crazymoves mode
2012-10-07 17:16:24 +02:00
* - play random sounds and move in random fashion
*/
2012-10-10 04:15:06 +02:00
void do_mode2(void)
{
2012-10-07 00:52:53 +02:00
static timer_t mytimer;
uint8_t max = 50;
uint8_t min = 5;
uint16_t maxfreq = 5000;
uint16_t minfreq = 1000;
2012-10-07 00:52:53 +02:00
2012-10-10 04:15:06 +02:00
if (mode_uninitialized) {
mode_uninitialized = false;
music_setNote(NOTE_PAUSE, 4); //mute
2012-10-07 00:52:53 +02:00
timer_set(&mytimer, 10);
init_leds();
2012-10-07 00:52:53 +02:00
led_off(LED_L | LED_R);
set_motor(MOTOR_OFF);
}
if (timer_expired(&mytimer)) {
set_motor(MOTOR_OFF);
2012-10-10 04:15:06 +02:00
music_setNote(NOTE_PAUSE, 0); //mute
2012-10-07 00:52:53 +02:00
// 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) {
2012-10-10 04:15:06 +02:00
music_setNote((rand() % (maxfreq - minfreq)) + minfreq,
0);
2012-10-07 00:52:53 +02:00
}
timer_set(&mytimer, (rand() % (max - min)) + min);
2012-10-10 04:15:06 +02:00
}//end if timer_expired
/*deinialisation */
if(OpMode != NextMode){
set_motor(MOTOR_OFF);
music_setNote(NOTE_PAUSE, 0); //mute
}
2012-10-07 00:52:53 +02:00
}
2012-10-07 17:16:24 +02:00
2012-10-10 04:15:06 +02:00
/**
* just blink mode
* - left/right button switch motor off/on
*/
void do_mode3(void)
{
2012-10-07 00:52:53 +02:00
static timer_t mytimer;
static bool blink;
2012-10-10 04:15:06 +02:00
if (mode_uninitialized) {
init_leds();
2012-10-10 04:15:06 +02:00
mode_uninitialized = false;
music_setNote(NOTE_PAUSE, 4); //mute
2012-10-07 00:52:53 +02:00
set_motor(MOTOR_OFF);
timer_set(&mytimer, 10);
blink = false;
2012-10-10 04:15:06 +02:00
}
2012-10-05 21:12:26 +02:00
2012-10-07 00:52:53 +02:00
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;
}
2012-10-10 04:15:06 +02:00
} //end if timer_expired
2012-10-07 00:52:53 +02:00
if (btn_state(BTNST_SUP, BTN_LEFT)) {
button_clear(BTN_LEFT);
set_motor(MOTOR_OFF);
2012-10-05 21:12:26 +02:00
2012-10-10 04:15:06 +02:00
}
2012-10-07 00:52:53 +02:00
if (btn_state(BTNST_SUP, BTN_RIGHT)) {
button_clear(BTN_RIGHT);
set_motor(MOTOR_ON);
2012-10-10 04:15:06 +02:00
}
2012-10-05 21:12:26 +02:00
2012-10-07 00:52:53 +02:00
}
2012-10-07 17:16:24 +02:00
2012-10-10 04:15:06 +02:00
/**
* ggrbug mode
2012-10-07 17:16:24 +02:00
* - simulate geiger counter sounds
*/
2012-10-10 04:15:06 +02:00
void do_mode4(void)
{
2012-10-07 00:52:53 +02:00
uint8_t max = 200;
uint8_t min = 10;
static timer_t mytimer;
static bool blink;
2012-10-10 04:15:06 +02:00
if (mode_uninitialized) {
init_leds();
2012-10-07 00:52:53 +02:00
music_setNote(NOTE_PAUSE, 0);
2012-10-10 04:15:06 +02:00
mode_uninitialized = false;
2012-10-07 00:52:53 +02:00
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;
}
2012-10-05 21:12:26 +02:00
2012-10-10 04:15:06 +02:00
} //end if timer_expired
2012-10-07 00:52:53 +02:00
}
2012-10-10 04:15:06 +02:00
void do_mode5(void)
{
static bool discharge;
static timer_t mytimer;
2012-10-10 04:15:06 +02:00
uint16_t led1;
uint16_t led2;
2012-10-10 04:15:06 +02:00
if (mode_uninitialized) {
mode_uninitialized = false;
set_motor(MOTOR_OFF);
2012-10-10 04:15:06 +02:00
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
2012-10-10 04:15:06 +02:00
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;
2012-10-10 04:15:06 +02:00
}
if (timer_expired(&mytimer)) {
2012-10-10 04:15:06 +02:00
if (discharge) {
2012-10-10 05:12:38 +02:00
DDRC |= (1 << PORTC0) | (1 << PORTC1) | //set LED Ports to output:
2012-10-10 04:15:06 +02:00
(1 << PORTC2) | (1 << PORTC3) ;
// discharge
PORTC = (PORTC & 0b11110000);
//set C0 and C2 to input (disable pullups)
2012-10-10 05:12:38 +02:00
DDRC &= ~((1 << PORTC0) | (1 << PORTC2)); //set Led Ports to input
//pull ups off
2012-10-10 04:15:06 +02:00
PORTC &= ~((1 << PORTC0) | (1 << PORTC2));
discharge = false;
2012-10-10 04:15:06 +02:00
} 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
2012-10-10 05:12:38 +02:00
2012-10-10 04:15:06 +02:00
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
//TODO: find out how to do this
//meanwhile: switch back to normal operation (silent mode 2)
NextMode=MODE2;
break;
default: break;
} //end switch
} //end timer expired
} // end do_powerDown
2012-10-10 05:12:38 +02:00
void __attribute__ ((noreturn)) main(void)
2012-10-10 04:15:06 +02:00
{
/* hardware initialisation: */
2012-09-02 23:49:57 +02:00
init_leds();
2012-09-06 23:09:20 +02:00
init_buzzr();
2012-10-01 21:39:25 +02:00
init_switch();
USART0_Init();
init_motor();
/* software initialisation */
timer_init();
music_init();
2012-10-01 21:39:25 +02:00
2012-10-10 05:12:38 +02:00
2012-10-10 04:15:06 +02:00
/* here the show begins: */
sei();
2012-10-07 00:52:53 +02:00
2012-10-10 04:15:06 +02:00
for ever {
2012-10-07 00:52:53 +02:00
//main polling loop;
button_poll();
if (OpMode != MODE_PWDN) modeswitch_poll(); //there is no way out of PWND
2012-10-07 00:52:53 +02:00
switch (OpMode) {
2012-10-10 05:12:38 +02:00
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 ;
2012-10-10 05:12:38 +02:00
default: do_mode0() ; break ;
2012-10-10 04:15:06 +02:00
}
if (OpMode!=NextMode) mode_uninitialized = true;
2012-10-10 04:15:06 +02:00
OpMode = NextMode;
}
2012-07-18 15:55:20 +02:00
}
2012-10-10 04:15:06 +02:00