From 79160371996d89075b7660db5a08634b97b4bb12 Mon Sep 17 00:00:00 2001 From: Thammi Date: Tue, 27 Aug 2013 00:22:38 +0200 Subject: [PATCH] Add melody support and hal stubs --- firmware/README.md | 23 ++++++++++++++++++--- firmware/apps/music.c | 32 +++++++++++++----------------- firmware/include/pentabug/hal.h | 28 +++++++++++++++++++++++--- firmware/include/pentabug/helper.h | 6 ++++++ firmware/include/pentabug/music.h | 11 +++++++++- firmware/include/pentabug/timer.h | 5 ++++- firmware/lib/music.c | 29 +++++++++++++++++++++++++-- firmware/main.c | 11 ++++++++++ 8 files changed, 117 insertions(+), 28 deletions(-) create mode 100644 firmware/include/pentabug/helper.h diff --git a/firmware/README.md b/firmware/README.md index b1298a8..e76cdf7 100644 --- a/firmware/README.md +++ b/firmware/README.md @@ -1,4 +1,8 @@ -## Firmware +# Firmware + +## Flashing + +## General This firmware is to be flashed to the atmega88 of the pentabug. The Makefile supports 2 different ways of flashing the firmware image: @@ -9,8 +13,8 @@ With the make serflash -target of the Makefile You can flash the microcontroler via the serial bootloader that is part of the initial firmware. - +target of the Makefile You can flash the microcontroler via the serial +bootloader that is part of the initial firmware. ### the isp way @@ -21,4 +25,17 @@ With the target of the Makefile you can flash the microcontroler via an isp programmer. Adjust the avrdude settings to Your programmers needs beforehand. +## App API + +The new firmware aims to be as simple as possible to the application developer. +The applications are defined by a function which is called repeatedly in an +Arduino like main loop. Most hardware components are (read: should be in the +near future) accessible through an easy API. + +There can be multiple different applications in one firmware. The next +application can be started by pressing one of the two buttons for at least 2 +seconds. The application has to be cooperative as other applications can only +be started if the `test_app_stop()` function is called in your application +regularly. You most propably won't have to worry about this as most functions +in the hardware abstraction layer are already doing this for you. diff --git a/firmware/apps/music.c b/firmware/apps/music.c index 1ae9b9a..be04066 100644 --- a/firmware/apps/music.c +++ b/firmware/apps/music.c @@ -8,39 +8,35 @@ #include #include -#define NOTE_SHORT 0xfffe +#define NOTE_BREAK 0xfffe +#define NOTE_SHORT 0xfffd 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_C, NOTE_D, NOTE_E, NOTE_F, NOTE_SHORT, NOTE_G, NOTE_G, NOTE_BREAK, + NOTE_A, NOTE_A, NOTE_A, NOTE_A, NOTE_SHORT, NOTE_G, NOTE_BREAK, + NOTE_A, NOTE_A, NOTE_A, NOTE_A, NOTE_SHORT, NOTE_G, NOTE_BREAK, + NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_SHORT, NOTE_E, NOTE_E, NOTE_BREAK, + NOTE_D, NOTE_D, NOTE_D, NOTE_D, NOTE_SHORT, NOTE_C, NOTE_BREAK, 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) { + if(notes[i] == NOTE_BREAK) { + _delay_ms(120); + } else if(notes[i] == NOTE_SHORT) { + _delay_ms(20); + } else { set_note(notes[i], 4); - _delay_ms(200); + _delay_ms(180); 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); +REG(run); diff --git a/firmware/include/pentabug/hal.h b/firmware/include/pentabug/hal.h index 4a083b0..a1ac34e 100644 --- a/firmware/include/pentabug/hal.h +++ b/firmware/include/pentabug/hal.h @@ -3,12 +3,34 @@ #include -#define BUTTON_L 0 -#define BUTTON_R 1 +#define LEFT 0 +#define RIGHT 1 + +// INITIALIZATION + +// initializes the hardware (timers, ...) void init_hw(void); + +// resets hardware to a state which is convenient for starting applications void reset_hw(void); -int8_t button_state(void); + +// BUTTONS + +// returns 1 if the button is pressed, 0 otherwise +uint8_t button_state(uint8_t btn); + + +// LEDS + +void led_on(uint8_t led); +void led_off(uint8_t led); +void led_inv(uint8_t led); + +// MOTOR + +void motor_on(uint8_t led); +void motor_off(uint8_t led); #endif /* HAL_H */ diff --git a/firmware/include/pentabug/helper.h b/firmware/include/pentabug/helper.h new file mode 100644 index 0000000..275e3da --- /dev/null +++ b/firmware/include/pentabug/helper.h @@ -0,0 +1,6 @@ +#ifndef HELPER_H +#define HELPER_H + +#define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array)) + +#endif /* HELPER_H */ diff --git a/firmware/include/pentabug/music.h b/firmware/include/pentabug/music.h index b8bd20c..ea0b103 100644 --- a/firmware/include/pentabug/music.h +++ b/firmware/include/pentabug/music.h @@ -2,8 +2,9 @@ #define MUSIC_H #include +#include -#define NOTE_PAUSE 0xffff //Pause +#define NOTE_PAUSE 0xffff // Pause #define NOTE_C 30577 // note C #define NOTE_Db 28862 // note C# / Db #define NOTE_D 27242 // note D @@ -17,7 +18,15 @@ #define NOTE_Bb 17161 // note A# / Bb #define NOTE_B 16198 // note B +#define MLDY_PAUSE 0xfffe // user defined pause for melody, the next value is the amount of ms to wait + +// plays the note (see defines above) at the given octave until another note is played or the note is stopped void set_note(uint16_t note, uint8_t octave); + +// plays a melody consisting of the array of tunes of length len with speed ms for each tune +void play_melody(uint16_t melody[], size_t len, uint8_t octave, int speed); + +// stop the currently playing note void stop_note(void); #endif /* MUSIC_H */ diff --git a/firmware/include/pentabug/timer.h b/firmware/include/pentabug/timer.h index 697ac0e..21db3c8 100644 --- a/firmware/include/pentabug/timer.h +++ b/firmware/include/pentabug/timer.h @@ -13,8 +13,11 @@ typedef void (*timer_fun)(void); -void start_timer(uint8_t scaler, uint16_t compare, timer_fun fun); +// start a timer and call fun() after prescaler*compare ticks +// use the defines above for prescaler +void start_timer(uint8_t prescaler, uint16_t compare, timer_fun fun); +// stops the timer void stop_timer(void); #endif /* TIMER_H */ diff --git a/firmware/lib/music.c b/firmware/lib/music.c index c3cd969..1e5bb5c 100644 --- a/firmware/lib/music.c +++ b/firmware/lib/music.c @@ -1,8 +1,11 @@ #include -#include - #include +#define __DELAY_BACKWARD_COMPATIBLE__ +#include + +#include +#include static void tune(void) { PORTB ^= 1 << 7; @@ -19,3 +22,25 @@ void set_note(uint16_t note, uint8_t octave) { void stop_note(void) { stop_timer(); } + +void play_melody(uint16_t notes[], size_t len, uint8_t octave, int speed) { + int pause = speed / 20; + + size_t i; + + // TODO: get away from the int to double conversion to free half of our flash ... + for(i = 0; i < len; ++i) { + if(notes[i] == MLDY_PAUSE) { + ++i; + _delay_ms(notes[i]); + } else { + set_note(notes[i], octave); + test_stop_app(); + _delay_ms(speed); + + stop_note(); + test_stop_app(); + _delay_ms(pause); + } + } +} diff --git a/firmware/main.c b/firmware/main.c index 9ecd98a..0eb4494 100644 --- a/firmware/main.c +++ b/firmware/main.c @@ -5,6 +5,11 @@ #include #include #include +#include +#include + +static uint16_t up_mldy[] = { NOTE_C, NOTE_D, NOTE_F, NOTE_PAUSE }; +static uint16_t down_mldy[] = { NOTE_F, NOTE_E, NOTE_C, NOTE_PAUSE }; static inline void run_app(struct app_t* app) { app_should_stop = 0; @@ -43,13 +48,19 @@ int main(void) { run_app(&apps[app_index]); + reset_hw(); + if(app_direction > 0) { + play_melody(up_mldy, ARRAY_SIZE(up_mldy), 4, 60); + app_index++; if(apps[app_index].run == NULL) { app_index = 0; } } else { + play_melody(down_mldy, ARRAY_SIZE(down_mldy), 4, 60); + if(app_index == 0) { app_index = MAX_APPS - 1; while(apps[app_index].run == NULL) --app_index;