Add melody support and hal stubs

This commit is contained in:
Thammi 2013-08-27 00:22:38 +02:00
parent 09c76867a4
commit 7916037199
8 changed files with 117 additions and 28 deletions

View File

@ -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.

View File

@ -8,39 +8,35 @@
#include <pentabug/lifecycle.h>
#include <pentabug/music.h>
#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);

View File

@ -3,12 +3,34 @@
#include <stdint.h>
#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 */

View File

@ -0,0 +1,6 @@
#ifndef HELPER_H
#define HELPER_H
#define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
#endif /* HELPER_H */

View File

@ -2,8 +2,9 @@
#define MUSIC_H
#include <stdint.h>
#include <stdlib.h>
#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 */

View File

@ -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 */

View File

@ -1,8 +1,11 @@
#include <pentabug/music.h>
#include <pentabug/timer.h>
#include <avr/io.h>
#define __DELAY_BACKWARD_COMPATIBLE__
#include <util/delay.h>
#include <pentabug/timer.h>
#include <pentabug/lifecycle.h>
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);
}
}
}

View File

@ -5,6 +5,11 @@
#include <pentabug/hal.h>
#include <pentabug/app.h>
#include <pentabug/lifecycle.h>
#include <pentabug/music.h>
#include <pentabug/helper.h>
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;