Add melody support and hal stubs
This commit is contained in:
parent
09c76867a4
commit
7916037199
|
@ -1,4 +1,8 @@
|
||||||
## Firmware
|
# Firmware
|
||||||
|
|
||||||
|
## Flashing
|
||||||
|
|
||||||
|
## General
|
||||||
|
|
||||||
This firmware is to be flashed to the atmega88 of the pentabug.
|
This firmware is to be flashed to the atmega88 of the pentabug.
|
||||||
The Makefile supports 2 different ways of flashing the firmware image:
|
The Makefile supports 2 different ways of flashing the firmware image:
|
||||||
|
@ -9,8 +13,8 @@ With the
|
||||||
|
|
||||||
make serflash
|
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
|
### the isp way
|
||||||
|
|
||||||
|
@ -21,4 +25,17 @@ With the
|
||||||
target of the Makefile you can flash the microcontroler via an isp programmer.
|
target of the Makefile you can flash the microcontroler via an isp programmer.
|
||||||
Adjust the avrdude settings to Your programmers needs beforehand.
|
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.
|
||||||
|
|
||||||
|
|
|
@ -8,39 +8,35 @@
|
||||||
#include <pentabug/lifecycle.h>
|
#include <pentabug/lifecycle.h>
|
||||||
#include <pentabug/music.h>
|
#include <pentabug/music.h>
|
||||||
|
|
||||||
#define NOTE_SHORT 0xfffe
|
#define NOTE_BREAK 0xfffe
|
||||||
|
#define NOTE_SHORT 0xfffd
|
||||||
|
|
||||||
static uint16_t notes[] = {
|
static uint16_t notes[] = {
|
||||||
NOTE_C, NOTE_D, NOTE_E, NOTE_F, NOTE_G, NOTE_G, 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_G, NOTE_SHORT,
|
NOTE_A, NOTE_A, NOTE_A, NOTE_A, NOTE_SHORT, NOTE_G, NOTE_BREAK,
|
||||||
NOTE_A, NOTE_A, NOTE_A, NOTE_A, NOTE_G, NOTE_SHORT,
|
NOTE_A, NOTE_A, NOTE_A, NOTE_A, NOTE_SHORT, NOTE_G, NOTE_BREAK,
|
||||||
NOTE_F, NOTE_F, NOTE_F, NOTE_F, NOTE_E, NOTE_E, NOTE_SHORT,
|
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_C, NOTE_SHORT,
|
NOTE_D, NOTE_D, NOTE_D, NOTE_D, NOTE_SHORT, NOTE_C, NOTE_BREAK,
|
||||||
NOTE_PAUSE, NOTE_PAUSE, NOTE_PAUSE,
|
NOTE_PAUSE, NOTE_PAUSE, NOTE_PAUSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void init(void) {
|
|
||||||
PORTC ^= 1 << 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void run(void) {
|
static void run(void) {
|
||||||
size_t i;
|
size_t i;
|
||||||
for(i = 0; i < sizeof(notes) / sizeof(*notes); ++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);
|
set_note(notes[i], 4);
|
||||||
_delay_ms(200);
|
_delay_ms(180);
|
||||||
test_stop_app();
|
test_stop_app();
|
||||||
|
|
||||||
stop_note();
|
stop_note();
|
||||||
_delay_ms(10);
|
_delay_ms(10);
|
||||||
test_stop_app();
|
test_stop_app();
|
||||||
} else {
|
|
||||||
_delay_ms(100);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PORTD ^= 1 << 4;
|
|
||||||
PORTC ^= 1 << 2;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER(run, init, NULL);
|
REG(run);
|
||||||
|
|
|
@ -3,12 +3,34 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#define BUTTON_L 0
|
#define LEFT 0
|
||||||
#define BUTTON_R 1
|
#define RIGHT 1
|
||||||
|
|
||||||
|
|
||||||
|
// INITIALIZATION
|
||||||
|
|
||||||
|
// initializes the hardware (timers, ...)
|
||||||
void init_hw(void);
|
void init_hw(void);
|
||||||
|
|
||||||
|
// resets hardware to a state which is convenient for starting applications
|
||||||
void reset_hw(void);
|
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 */
|
#endif /* HAL_H */
|
||||||
|
|
6
firmware/include/pentabug/helper.h
Normal file
6
firmware/include/pentabug/helper.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#ifndef HELPER_H
|
||||||
|
#define HELPER_H
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(array) (sizeof(array)/sizeof(*array))
|
||||||
|
|
||||||
|
#endif /* HELPER_H */
|
|
@ -2,6 +2,7 @@
|
||||||
#define MUSIC_H
|
#define MUSIC_H
|
||||||
|
|
||||||
#include <stdint.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_C 30577 // note C
|
||||||
|
@ -17,7 +18,15 @@
|
||||||
#define NOTE_Bb 17161 // note A# / Bb
|
#define NOTE_Bb 17161 // note A# / Bb
|
||||||
#define NOTE_B 16198 // note B
|
#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);
|
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);
|
void stop_note(void);
|
||||||
|
|
||||||
#endif /* MUSIC_H */
|
#endif /* MUSIC_H */
|
||||||
|
|
|
@ -13,8 +13,11 @@
|
||||||
|
|
||||||
typedef void (*timer_fun)(void);
|
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);
|
void stop_timer(void);
|
||||||
|
|
||||||
#endif /* TIMER_H */
|
#endif /* TIMER_H */
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
#include <pentabug/music.h>
|
#include <pentabug/music.h>
|
||||||
|
|
||||||
#include <pentabug/timer.h>
|
|
||||||
|
|
||||||
#include <avr/io.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) {
|
static void tune(void) {
|
||||||
PORTB ^= 1 << 7;
|
PORTB ^= 1 << 7;
|
||||||
|
@ -19,3 +22,25 @@ void set_note(uint16_t note, uint8_t octave) {
|
||||||
void stop_note(void) {
|
void stop_note(void) {
|
||||||
stop_timer();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
#include <pentabug/hal.h>
|
#include <pentabug/hal.h>
|
||||||
#include <pentabug/app.h>
|
#include <pentabug/app.h>
|
||||||
#include <pentabug/lifecycle.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) {
|
static inline void run_app(struct app_t* app) {
|
||||||
app_should_stop = 0;
|
app_should_stop = 0;
|
||||||
|
@ -43,13 +48,19 @@ int main(void) {
|
||||||
|
|
||||||
run_app(&apps[app_index]);
|
run_app(&apps[app_index]);
|
||||||
|
|
||||||
|
reset_hw();
|
||||||
|
|
||||||
if(app_direction > 0) {
|
if(app_direction > 0) {
|
||||||
|
play_melody(up_mldy, ARRAY_SIZE(up_mldy), 4, 60);
|
||||||
|
|
||||||
app_index++;
|
app_index++;
|
||||||
|
|
||||||
if(apps[app_index].run == NULL) {
|
if(apps[app_index].run == NULL) {
|
||||||
app_index = 0;
|
app_index = 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
play_melody(down_mldy, ARRAY_SIZE(down_mldy), 4, 60);
|
||||||
|
|
||||||
if(app_index == 0) {
|
if(app_index == 0) {
|
||||||
app_index = MAX_APPS - 1;
|
app_index = MAX_APPS - 1;
|
||||||
while(apps[app_index].run == NULL) --app_index;
|
while(apps[app_index].run == NULL) --app_index;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user