Add interrupts, music and much more stuff

This commit is contained in:
Thammi 2013-08-26 20:39:15 +02:00
parent 33f4345e46
commit cbecd7ef38
12 changed files with 287 additions and 43 deletions

View File

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

46
firmware/apps/music.c Normal file
View File

@ -0,0 +1,46 @@
#include <stdlib.h>
#include <avr/io.h>
#define __DELAY_BACKWARD_COMPATIBLE__
#include <util/delay.h>
#include <pentabug/app.h>
#include <pentabug/lifecycle.h>
#include <pentabug/music.h>
#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);

15
firmware/apps/test.c Normal file
View File

@ -0,0 +1,15 @@
#include <stdlib.h>
#include <avr/io.h>
#define __DELAY_BACKWARD_COMPATIBLE__
#include <util/delay.h>
#include <pentabug/app.h>
#include <pentabug/lifecycle.h>
static void tester(void) {
PORTD ^= 1 << 4;
_delay_ms(100);
}
REG(tester);

View File

@ -0,0 +1,14 @@
#ifndef HAL_H
#define HAL_H
#include <stdint.h>
#define BUTTON_L 0
#define BUTTON_R 1
void init_hw(void);
void reset_hw(void);
int8_t button_state(void);
#endif /* HAL_H */

View File

@ -5,7 +5,8 @@
#include <stdint.h>
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 */

View File

@ -0,0 +1,23 @@
#ifndef MUSIC_H
#define MUSIC_H
#include <stdint.h>
#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 */

View File

@ -0,0 +1,20 @@
#ifndef TIMER_H
#define TIMER_H
#include <stdint.h>
// 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 */

87
firmware/lib/hal.c Normal file
View File

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

View File

@ -1,4 +1,5 @@
#include <pentabug/lifecycle.h>
jmp_buf app_jmp_buf;
volatile uint8_t should_stop;
volatile uint8_t app_should_stop = 0;
volatile int8_t app_direction = 1;

21
firmware/lib/music.c Normal file
View File

@ -0,0 +1,21 @@
#include <pentabug/music.h>
#include <pentabug/timer.h>
#include <avr/io.h>
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();
}

32
firmware/lib/timer.c Normal file
View File

@ -0,0 +1,32 @@
#include <pentabug/timer.h>
#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>
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();
}
}

View File

@ -2,28 +2,16 @@
#include <stdint.h>
#include <stdlib.h>
#include <avr/io.h>
#include <pentabug/hal.h>
#include <pentabug/app.h>
#include <pentabug/lifecycle.h>
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) {