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.
|
||||
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.
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
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
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define NOTE_PAUSE 0xffff // Pause
|
||||
#define NOTE_C 30577 // note C
|
||||
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue
Block a user