From cbecd7ef38b1599aa095a843ba18aee867fa0bda Mon Sep 17 00:00:00 2001 From: Thammi Date: Mon, 26 Aug 2013 20:39:15 +0200 Subject: [PATCH] Add interrupts, music and much more stuff --- firmware/apps/blinker.c | 21 +++---- firmware/apps/music.c | 46 ++++++++++++++ firmware/apps/test.c | 15 +++++ firmware/include/pentabug/hal.h | 14 +++++ firmware/include/pentabug/lifecycle.h | 15 +++-- firmware/include/pentabug/music.h | 23 +++++++ firmware/include/pentabug/timer.h | 20 ++++++ firmware/lib/hal.c | 87 +++++++++++++++++++++++++++ firmware/lib/lifecycle.c | 3 +- firmware/lib/music.c | 21 +++++++ firmware/lib/timer.c | 32 ++++++++++ firmware/main.c | 33 +++------- 12 files changed, 287 insertions(+), 43 deletions(-) create mode 100644 firmware/apps/music.c create mode 100644 firmware/apps/test.c create mode 100644 firmware/include/pentabug/hal.h create mode 100644 firmware/include/pentabug/music.h create mode 100644 firmware/include/pentabug/timer.h create mode 100644 firmware/lib/hal.c create mode 100644 firmware/lib/music.c create mode 100644 firmware/lib/timer.c diff --git a/firmware/apps/blinker.c b/firmware/apps/blinker.c index bc00ab8..0580f90 100644 --- a/firmware/apps/blinker.c +++ b/firmware/apps/blinker.c @@ -8,24 +8,17 @@ #include static void init(void) { - PIND |= 1 << 4; - DDRD |= 1 << 4; - - _delay_ms(2000); + _delay_ms(1000); } static void blinker(void) { - size_t i; + PORTD |= 1 << 4; + _delay_ms(800); + test_stop_app(); - for(i = 0; i < 5; ++i) { - PORTD |= 1 << 4; - _delay_ms(800); - - PORTD &= ~(1 << 4); - _delay_ms(200); - } - - stop_app(); + PORTD &= ~(1 << 4); + _delay_ms(200); + test_stop_app(); } REGISTER(blinker, init, NULL); diff --git a/firmware/apps/music.c b/firmware/apps/music.c new file mode 100644 index 0000000..1ae9b9a --- /dev/null +++ b/firmware/apps/music.c @@ -0,0 +1,46 @@ +#include + +#include +#define __DELAY_BACKWARD_COMPATIBLE__ +#include + +#include +#include +#include + +#define NOTE_SHORT 0xfffe + +static uint16_t notes[] = { + NOTE_C, NOTE_D, NOTE_E, NOTE_F, NOTE_G, NOTE_G, NOTE_SHORT, + NOTE_A, NOTE_A, NOTE_A, NOTE_A, NOTE_G, NOTE_SHORT, + NOTE_A, NOTE_A, NOTE_A, NOTE_A, NOTE_G, NOTE_SHORT, + NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_E, NOTE_E, NOTE_SHORT, + NOTE_D, NOTE_D, NOTE_D, NOTE_D, NOTE_C, NOTE_SHORT, + NOTE_PAUSE, NOTE_PAUSE, NOTE_PAUSE, +}; + +static void init(void) { + PORTC ^= 1 << 2; +} + +static void run(void) { + size_t i; + for(i = 0; i < sizeof(notes) / sizeof(*notes); ++i) { + if(notes[i] != NOTE_SHORT) { + set_note(notes[i], 4); + _delay_ms(200); + test_stop_app(); + + stop_note(); + _delay_ms(10); + test_stop_app(); + } else { + _delay_ms(100); + } + + PORTD ^= 1 << 4; + PORTC ^= 1 << 2; + } +} + +REGISTER(run, init, NULL); diff --git a/firmware/apps/test.c b/firmware/apps/test.c new file mode 100644 index 0000000..2da1f78 --- /dev/null +++ b/firmware/apps/test.c @@ -0,0 +1,15 @@ +#include + +#include +#define __DELAY_BACKWARD_COMPATIBLE__ +#include + +#include +#include + +static void tester(void) { + PORTD ^= 1 << 4; + _delay_ms(100); +} + +REG(tester); diff --git a/firmware/include/pentabug/hal.h b/firmware/include/pentabug/hal.h new file mode 100644 index 0000000..4a083b0 --- /dev/null +++ b/firmware/include/pentabug/hal.h @@ -0,0 +1,14 @@ +#ifndef HAL_H +#define HAL_H + +#include + +#define BUTTON_L 0 +#define BUTTON_R 1 + +void init_hw(void); +void reset_hw(void); + +int8_t button_state(void); + +#endif /* HAL_H */ diff --git a/firmware/include/pentabug/lifecycle.h b/firmware/include/pentabug/lifecycle.h index 706a751..cafa1f2 100644 --- a/firmware/include/pentabug/lifecycle.h +++ b/firmware/include/pentabug/lifecycle.h @@ -5,7 +5,8 @@ #include extern jmp_buf app_jmp_buf; -extern volatile uint8_t should_stop; +extern volatile uint8_t app_should_stop; +extern volatile int8_t app_direction; // this code does not work ... i have no idea why // putting the exact same statements at the calling line works ... @@ -20,19 +21,25 @@ static int enter_app(void) { // 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; + app_should_stop = 1; } // stop app if previously requested inline static void test_stop_app(void) { - if(should_stop) { + if(app_should_stop) { + app_should_stop = 0; stop_app(); } } +// request the next app to run, set direction +inline static void next_app(int8_t new_direction) { + app_direction = new_direction; + request_stop_app(); +} + #endif /* LIFECYCLE_H */ diff --git a/firmware/include/pentabug/music.h b/firmware/include/pentabug/music.h new file mode 100644 index 0000000..b8bd20c --- /dev/null +++ b/firmware/include/pentabug/music.h @@ -0,0 +1,23 @@ +#ifndef MUSIC_H +#define MUSIC_H + +#include + +#define NOTE_PAUSE 0xffff //Pause +#define NOTE_C 30577 // note C +#define NOTE_Db 28862 // note C# / Db +#define NOTE_D 27242 // note D +#define NOTE_Eb 25713 // note D# / Eb +#define NOTE_E 24270 // note E +#define NOTE_F 22908 // note F +#define NOTE_Gb 21622 // note F# / Gb +#define NOTE_G 20408 // note G +#define NOTE_Ab 19263 // note G# / Ab +#define NOTE_A 18182 // note A +#define NOTE_Bb 17161 // note A# / Bb +#define NOTE_B 16198 // note B + +void set_note(uint16_t note, uint8_t octave); +void stop_note(void); + +#endif /* MUSIC_H */ diff --git a/firmware/include/pentabug/timer.h b/firmware/include/pentabug/timer.h new file mode 100644 index 0000000..697ac0e --- /dev/null +++ b/firmware/include/pentabug/timer.h @@ -0,0 +1,20 @@ +#ifndef TIMER_H +#define TIMER_H + +#include + +// this library addresses the 16 bit timer + +#define PRESCALE_1 (1 << CS10) +#define PRESCALE_8 (1 << CS11) +#define PRESCALE_64 (1 << CS11 | 1 << CS10) +#define PRESCALE_256 (1 << CS12) +#define PRESCALE_1024 (1 << CS12 | 1 << CS10) + +typedef void (*timer_fun)(void); + +void start_timer(uint8_t scaler, uint16_t compare, timer_fun fun); + +void stop_timer(void); + +#endif /* TIMER_H */ diff --git a/firmware/lib/hal.c b/firmware/lib/hal.c new file mode 100644 index 0000000..3c8908d --- /dev/null +++ b/firmware/lib/hal.c @@ -0,0 +1,87 @@ +#include + +#include +#include +#define __DELAY_BACKWARD_COMPATIBLE__ +#include + +#include + +#include + +static uint8_t ir_active = 1; +static int int_skip = 0; + +static int button_count[2]; + +// major interrupt for button handling, every 5ms +inline static void major_interrupt(void) { + uint8_t i = 0; + + for(i = 0; i < 2; ++i) { + if(PINB & (1 << i)) { + button_count[i] = 0; + } else { + ++button_count[i]; + } + + if(button_count[i] == 400) { + next_app(i ? 1 : -1); + PORTC ^= 1 << 2; + } + } +} + +ISR(TIMER0_COMPA_vect) { + if(ir_active) { + PORTD ^= 1 << 2; + } + + ++int_skip; + + if(int_skip >= 38 * 5) { + int_skip = 0; + major_interrupt(); + } +} + +void init_hw(void) { + // we need to get real fast (8MHz) to handle 38kHz IR frequency ... + + CLKPR = 0b10000000; + CLKPR = 0b00000000; + + // initialize timer + + TIMSK0 |= (1 << OCIE0A); + + // calculated and works, but frequency is a little bit off? + OCR0A = 105; + + TCCR0A = (1 << WGM01); + TCCR0B = (1 << CS00); + + sei(); +} + +void reset_hw(void) { + stop_timer(); + + // 0: S1 + // 1: S2 + // 7: BUZZR + PORTB = (1 << 0) | (1 << 1) | (1 << 7); + DDRB = (1 << 7); + + // 0: BUZGND + // 2: LED2 + // 3: LED2 (+) + PORTC = (1 << 2) | (1 << 3); + DDRC = (1 << 0) | (1 << 2) | (1 << 3); + + // 2: IR + // 4: LED + PORTD = (1 << 4); + DDRD = (1 << 2) | (1 << 4); +} + diff --git a/firmware/lib/lifecycle.c b/firmware/lib/lifecycle.c index 57531db..eab1e9d 100644 --- a/firmware/lib/lifecycle.c +++ b/firmware/lib/lifecycle.c @@ -1,4 +1,5 @@ #include jmp_buf app_jmp_buf; -volatile uint8_t should_stop; +volatile uint8_t app_should_stop = 0; +volatile int8_t app_direction = 1; diff --git a/firmware/lib/music.c b/firmware/lib/music.c new file mode 100644 index 0000000..c3cd969 --- /dev/null +++ b/firmware/lib/music.c @@ -0,0 +1,21 @@ +#include + +#include + +#include + +static void tune(void) { + PORTB ^= 1 << 7; +} + +void set_note(uint16_t note, uint8_t octave) { + if(note != NOTE_PAUSE) { + start_timer(PRESCALE_8, note >> octave, tune); + } else { + stop_timer(); + } +} + +void stop_note(void) { + stop_timer(); +} diff --git a/firmware/lib/timer.c b/firmware/lib/timer.c new file mode 100644 index 0000000..39cbbb6 --- /dev/null +++ b/firmware/lib/timer.c @@ -0,0 +1,32 @@ +#include + +#include + +#include +#include + +static timer_fun current_fun = NULL; + +void start_timer(uint8_t scaler, uint16_t compare, timer_fun fun) { + current_fun = fun; + + TCCR1A = 0; + TCCR1B = (1 << WGM12) | scaler; + TIMSK1 = 1 << OCIE1A; + OCR1A = compare; +} + +void stop_timer(void) { + current_fun = NULL; + + TIMSK1 = 0; + TCCR1A = 0; + TCCR1B = 0; +} + +ISR(TIMER1_COMPA_vect, ISR_NOBLOCK) { + if(current_fun) { + current_fun(); + } +} + diff --git a/firmware/main.c b/firmware/main.c index 73a0977..9ecd98a 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -2,28 +2,16 @@ #include #include -#include - +#include #include #include -static inline void reset_hw(void) { - DDRB = 0; - DDRC = 0; - DDRD = 0; - - PORTB = 0; - PORTC = 0; - PORTD = 0; - - PINB = 0; - PINC = 0; - PIND = 0; -} - static inline void run_app(struct app_t* app) { - should_stop = 0; + app_should_stop = 0; + if(setjmp(app_jmp_buf) == 0) { + // initial call + if(app->init) { app->init(); } @@ -34,7 +22,8 @@ static inline void run_app(struct app_t* app) { } } - // this is the exit + // returned after longjmp() + if(app->cleanup) { app->cleanup(); } @@ -44,12 +33,8 @@ static inline void run_app(struct app_t* 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; + init_hw(); // cycle through apps @@ -58,7 +43,7 @@ int main(void) { run_app(&apps[app_index]); - if(direction > 0) { + if(app_direction > 0) { app_index++; if(apps[app_index].run == NULL) {