added synth to mode1, major cleanup
This commit is contained in:
parent
c654c12385
commit
608ad6e2fe
50
firmware/lib/freq_table.h
Normal file
50
firmware/lib/freq_table.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
const uint16_t freq_table[] PROGMEM = {
|
||||||
|
/*0x00*/ 0,
|
||||||
|
/*0x01*/ 130,
|
||||||
|
/*0x02*/ 137,
|
||||||
|
/*0x03*/ 145,
|
||||||
|
/*0x04*/ 154,
|
||||||
|
/*0x05*/ 163,
|
||||||
|
/*0x06*/ 173,
|
||||||
|
/*0x07*/ 183,
|
||||||
|
/*0x08*/ 194,
|
||||||
|
/*0x09*/ 206,
|
||||||
|
/*0x0a*/ 218,
|
||||||
|
/*0x0b*/ 231,
|
||||||
|
/*0x0c*/ 245,
|
||||||
|
/*0x0d*/ 259,
|
||||||
|
/*0x0e*/ 275,
|
||||||
|
/*0x0f*/ 291,
|
||||||
|
/*0x10*/ 308,
|
||||||
|
/*0x11*/ 327,
|
||||||
|
/*0x12*/ 346,
|
||||||
|
/*0x13*/ 367,
|
||||||
|
/*0x14*/ 388,
|
||||||
|
/*0x15*/ 412,
|
||||||
|
/*0x16*/ 436,
|
||||||
|
/*0x17*/ 462,
|
||||||
|
/*0x18*/ 489,
|
||||||
|
/*0x19*/ 518,
|
||||||
|
/*0x1a*/ 549,
|
||||||
|
/*0x1b*/ 582,
|
||||||
|
/*0x1c*/ 617,
|
||||||
|
/*0x1d*/ 653,
|
||||||
|
/*0x1e*/ 692,
|
||||||
|
/*0x1f*/ 733,
|
||||||
|
/*0x20*/ 777,
|
||||||
|
/*0x21*/ 823,
|
||||||
|
/*0x22*/ 872,
|
||||||
|
/*0x23*/ 924,
|
||||||
|
/*0x24*/ 979,
|
||||||
|
/*0x25*/ 1037,
|
||||||
|
/*0x26*/ 1099,
|
||||||
|
/*0x27*/ 1164,
|
||||||
|
/*0x28*/ 1233,
|
||||||
|
/*0x29*/ 1306,
|
||||||
|
/*0x2a*/ 1384,
|
||||||
|
/*0x2b*/ 1466,
|
||||||
|
/*0x2c*/ 1554,
|
||||||
|
/*0x2d*/ 1646,
|
||||||
|
/*0x2e*/ 1744,
|
||||||
|
/*0x2f*/ 1848,
|
||||||
|
};
|
|
@ -1,204 +1,101 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "synth.h"
|
#include <avr/io.h>
|
||||||
#include "freq_table.h"
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
|
#define __DELAY_BACKWARD_COMPATIBLE__
|
||||||
|
#include <util/delay.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include "freq_table.h"
|
||||||
|
|
||||||
|
|
||||||
|
void synth_init(void){
|
||||||
|
cli();
|
||||||
|
/*
|
||||||
|
* Timer 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* set timer0 to CTC & prescaler 64 → 125kHz increment */
|
||||||
|
TCCR0A = (1 << WGM01);
|
||||||
|
TCCR0B = (1 << CS00) | (1 << CS01);
|
||||||
|
|
||||||
|
OCR0A = 4; /* TOP */
|
||||||
|
TCNT0 = 0;
|
||||||
|
/*enable interrupt */
|
||||||
|
TIMSK0 |= (1 << OCIE0A);
|
||||||
|
|
||||||
|
sei();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void synth_deinit(void) {
|
||||||
|
cli();
|
||||||
|
TIMSK0 = 0;
|
||||||
|
sei();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// sample rate is 8M / (3 * 64)
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
channel_count = 3,
|
SONG_LENGTH = 128,
|
||||||
//tick_length = 400,
|
xxx = 0,
|
||||||
// tick_length = 256,
|
c_0 = 0, cs0 = 1, d_0 = 2, ds0 = 3, e_0 = 4, f_0 = 5,
|
||||||
row_length = 4,
|
fs0 = 6, g_0 = 7, gs0 = 8, a_0 = 9, as0 = 10, b_0 = 11,
|
||||||
pattern_length = 16
|
c_1 = 12, cs1 = 13, d_1 = 14, ds1 = 15, e_1 = 16, f_1 = 17,
|
||||||
|
fs1 = 18, g_1 = 19, gs1 = 20, a_1 = 21, as1 = 22, b_1 = 23,
|
||||||
|
c_2 = 24, cs2 = 25, d_2 = 26, ds2 = 27, e_2 = 28, f_2 = 29,
|
||||||
|
fs2 = 30, g_2 = 31, gs2 = 32, a_2 = 33, as2 = 34, b_2 = 35,
|
||||||
|
c_3 = 36, cs3 = 37, d_3 = 38, ds3 = 39, e_3 = 40, f_3 = 41,
|
||||||
|
fs3 = 42, g_3 = 43, gs3 = 44, a_3 = 45, as3 = 46, b_3 = 47,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const synth_instrument_t instruments[] = { { 1 << 15, 100, 12, 0 }, { 0,
|
const char music_data[2][SONG_LENGTH] PROGMEM = {
|
||||||
100, 12, 0 }, { 0, 200, 10, 0 }, { 1 << 13, 0, 0, 2 }, { 1 << 13, 0, 5,
|
{
|
||||||
2 }, };
|
e_1, xxx, e_2, xxx, e_1, xxx, e_2, xxx, e_1, xxx, e_2, xxx, e_1, xxx, e_2, xxx,
|
||||||
|
a_0, xxx, a_1, xxx, a_0, xxx, a_1, xxx, a_0, xxx, a_1, xxx, a_0, xxx, a_1, xxx,
|
||||||
static const uint8_t wave_table[][2] = { { 0, WAVE_PULSE }, { 3, WAVE_PULSE }, {
|
gs0, xxx, gs1, xxx, gs0, xxx, gs1, xxx, gs0, xxx, gs1, xxx, gs0, xxx, gs1, xxx,
|
||||||
7, WAVE_PULSE }, { 12, WAVE_PULSE }, { 256 - 4, 0xff },
|
a_0, xxx, a_1, xxx, a_0, xxx, a_1, xxx, a_0, xxx, a_0, xxx, b_0, xxx, c_1, xxx,
|
||||||
|
d_1, xxx, d_2, xxx, d_1, xxx, d_2, xxx, d_1, xxx, d_2, xxx, d_1, xxx, d_2, xxx,
|
||||||
{ 0, WAVE_PULSE }, { 2, WAVE_PULSE }, { 7, WAVE_PULSE }, { 10, WAVE_PULSE }, {
|
c_1, xxx, c_2, xxx, c_1, xxx, c_2, xxx, c_1, xxx, c_2, xxx, c_1, xxx, c_2, xxx,
|
||||||
256 - 4, 0xff },
|
b_0, xxx, b_1, xxx, b_0, xxx, b_1, xxx, b_0, xxx, b_1, xxx, b_0, xxx, b_1, xxx,
|
||||||
|
a_0, xxx, a_1, xxx, a_0, xxx, a_1, xxx, a_0, xxx, xxx, xxx, xxx, xxx, xxx, xxx,
|
||||||
{ 0, WAVE_NOISE }, { 0, WAVE_PULSE }, { 0xff, 0xff },
|
}, {
|
||||||
|
e_3, e_3, e_3, e_3, b_2, b_2, c_3, c_3, d_3, d_3, e_3, d_3, c_3, c_3, b_2, b_2,
|
||||||
{ 0, WAVE_PULSE }, { 0xff, 0xff },
|
a_2, a_2, a_2, a_2, a_2, a_2, c_3, c_3, e_3, e_3, e_3, e_3, d_3, d_3, c_3, c_3,
|
||||||
|
b_2, b_2, b_2, b_2, b_2, b_2, c_3, c_3, d_3, d_3, d_3, d_3, e_3, e_3, e_3, e_3,
|
||||||
|
c_3, c_3, c_3, c_3, a_2, a_2, a_2, a_2, a_2, a_2, a_2, a_2, a_2, a_2, a_2, a_2,
|
||||||
|
xxx, xxx, d_3, d_3, d_3, d_3, f_3, f_3, a_3, a_3, a_3, a_3, g_3, g_3, f_3, f_3,
|
||||||
|
e_3, e_3, e_3, e_3, e_3, e_3, c_3, c_3, e_3, e_3, e_3, e_3, d_3, d_3, c_3, c_3,
|
||||||
|
b_2, b_2, b_2, b_2, b_2, b_2, c_3, c_3, d_3, d_3, d_3, d_3, e_3, e_3, e_3, e_3,
|
||||||
|
c_3, c_3, c_3, c_3, a_2, a_2, a_2, a_2, a_2, a_2, a_2, a_2, xxx, xxx, xxx, xxx,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint8_t patterns[][pattern_length][2] PROGMEM = { { }, { { 33 - 12,
|
|
||||||
0 }, { 0, 0 }, { 0xff, 1 }, { 0, 0 }, { 33, 1 }, { 0xff, 1 }, { 33, 1 },
|
|
||||||
{ 0xff, 1 }, { 33, 1 }, { 0xff, 1 }, { 33 - 12, 1 }, { 0xff, 1 }, { 33
|
|
||||||
- 12, 1 }, { 0xff, 1 }, { 33, 1 }, { 0xff, 1 }, }, { { 28 - 12,
|
|
||||||
0 }, { 0, 0 }, { 0xff, 1 }, { 0, 0 }, { 28, 1 }, { 0xff, 1 }, { 28, 1 },
|
|
||||||
{ 0xff, 1 }, { 28, 1 }, { 0xff, 1 }, { 28 - 12, 1 }, { 0xff, 1 }, { 28
|
|
||||||
- 12, 1 }, { 0xff, 1 }, { 28, 1 }, { 0xff, 1 }, }, { { 0, 0 }, {
|
|
||||||
0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, {
|
|
||||||
57, 3 }, }, { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
|
|
||||||
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 57, 4 }, },
|
|
||||||
|
|
||||||
{ { 60, 2 }, }, { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 57, 2 }, { 0, 0 }, {
|
static uint16_t osc0 = 0;
|
||||||
0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 55, 2 }, {
|
static uint16_t osc1 = 0;
|
||||||
0, 0 }, { 57, 2 }, { 0, 0 }, }, { { 55, 2 }, }, { { 0, 0 }, { 0, 0 }, {
|
static uint16_t sample = 0;
|
||||||
0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0,
|
static uint8_t row = 0;
|
||||||
0 }, { 0, 0 }, { 0, 0 }, { 57, 2 }, }, { { 55 - 3, 2 }, },
|
static uint16_t speedtime = 3000;
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
static const uint8_t pattern_table[][channel_count] = { { 1, 0, 5 },
|
ISR(TIMER0_COMPA_vect,ISR_NOBLOCK)
|
||||||
{ 1, 3, 0 }, { 1, 0, 7 }, { 1, 3, 6 }, { 2, 0, 7 }, { 2, 4, 8 }, { 2, 0,
|
{
|
||||||
9 }, { 2, 4, 0 }, };
|
osc0 += pgm_read_word(&freq_table[ pgm_read_byte(&music_data[0][row])]);
|
||||||
enum {
|
osc1 += pgm_read_word(&freq_table[ pgm_read_byte(&music_data[1][row])]);
|
||||||
pattern_table_length = sizeof(pattern_table) / sizeof(pattern_table[0])
|
if (++sample == speedtime ) {
|
||||||
};
|
|
||||||
|
|
||||||
static synth_channel_t channels[channel_count];
|
|
||||||
static int8_t sample;
|
|
||||||
static int8_t tick;
|
|
||||||
static int8_t row;
|
|
||||||
static int8_t seq;
|
|
||||||
|
|
||||||
/* PROTOTYPES */
|
|
||||||
uint8_t synth_mix(void);
|
|
||||||
|
|
||||||
static uint8_t timeslots[SYNTH_BUFSIZE];
|
|
||||||
static uint8_t timeslots_write; // current write head
|
|
||||||
static uint8_t timeslots_read; // current read head
|
|
||||||
|
|
||||||
/*register for atomic ++ and -- */
|
|
||||||
register uint8_t timeslots_fill asm("r2");
|
|
||||||
|
|
||||||
static void enqueue_timeslot(uint8_t synthval);
|
|
||||||
static uint8_t dequeue_timeslot(void);
|
|
||||||
|
|
||||||
void synth_init(void) {
|
|
||||||
sample = 0;
|
sample = 0;
|
||||||
tick = 0;
|
if (speedtime > 600) speedtime -= 4;
|
||||||
|
if (++row == SONG_LENGTH) {
|
||||||
row = 0;
|
row = 0;
|
||||||
seq = 0;
|
if (speedtime <= 600) speedtime = 3000;
|
||||||
timeslots_fill = 0;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (osc0 >= 0x8000) PORTB |= (1 << PORTB2);
|
||||||
|
else PORTB &= ~(1<< PORTB2);
|
||||||
|
if (osc1 >= 0xc000) PORTC |= (1 << PORTC5);
|
||||||
|
else PORTC &= ~(1<< PORTC5);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t synth_mix(void) {
|
|
||||||
if (sample == 0) { // new tick
|
|
||||||
for (int i = 1; i < channel_count; i++) {
|
|
||||||
synth_channel_t* chan = &channels[i];
|
|
||||||
|
|
||||||
const synth_instrument_t* inst = &instruments[chan->inst_nr];
|
|
||||||
|
|
||||||
if (chan->level > inst->decay)
|
|
||||||
chan->level -= inst->decay;
|
|
||||||
else
|
|
||||||
chan->level = 0;
|
|
||||||
|
|
||||||
chan->pulse_width += inst->pulse_sweep;
|
|
||||||
|
|
||||||
chan->pos++;
|
|
||||||
if (wave_table[chan->pos][1] == 0xff)
|
|
||||||
chan->pos += wave_table[chan->pos][0];
|
|
||||||
|
|
||||||
// enter new rol
|
|
||||||
// w
|
|
||||||
if (tick == 0) {
|
|
||||||
uint8_t pattern_nr = pattern_table[seq][i];
|
|
||||||
uint8_t note = pgm_read_byte(&patterns[pattern_nr][row][0]);
|
|
||||||
|
|
||||||
if (note) { // new note, maybe?
|
|
||||||
if (note == 0xff) {
|
|
||||||
chan->level = 0;
|
|
||||||
} else {
|
|
||||||
chan->level = 80; // TODO: less?
|
|
||||||
chan->note = note;
|
|
||||||
chan->inst_nr =
|
|
||||||
pgm_read_byte(&patterns[pattern_nr][row][1]);
|
|
||||||
inst = &instruments[chan->inst_nr];
|
|
||||||
chan->pos = inst->wave_table_pos;
|
|
||||||
if (inst->pulse_width)
|
|
||||||
chan->pulse_width = inst->pulse_width;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (++sample == 0) {
|
|
||||||
if (++tick == row_length) {
|
|
||||||
tick = 0;
|
|
||||||
if (++row == pattern_length) {
|
|
||||||
row = 0;
|
|
||||||
if (++seq == pattern_table_length) {
|
|
||||||
seq = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t output = 0;
|
|
||||||
for (int i = 0; i < channel_count; i++) {
|
|
||||||
synth_channel_t* chan = &channels[i];
|
|
||||||
// const synth_instrument_t* inst = &instruments[chan->inst_nr];
|
|
||||||
|
|
||||||
chan->phase +=
|
|
||||||
pgm_read_word(&freq_table[(uint8_t)(chan->note + wave_table[chan->pos][0])]);
|
|
||||||
|
|
||||||
uint8_t amp;
|
|
||||||
switch (wave_table[chan->pos][1]) {
|
|
||||||
case WAVE_PULSE:
|
|
||||||
amp = -(chan->phase < chan->pulse_width);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WAVE_SAW:
|
|
||||||
amp = (chan->phase >> 8);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WAVE_NOISE: // shitty noise
|
|
||||||
chan->phase = (chan->phase >> 1) ^ (-(chan->phase & 1) & 0xb400);
|
|
||||||
amp = (chan->phase >> 8);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
amp = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
output += (((amp & 0xff) * chan->level) >> 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* fill all the timeslots */
|
|
||||||
inline void synth_poll(void) {
|
|
||||||
/* refill timeslots queue */
|
|
||||||
// while (timeslots_fill < (SYNTH_BUFSIZE-1))
|
|
||||||
if (timeslots_fill < (SYNTH_BUFSIZE - 1))
|
|
||||||
enqueue_timeslot(synth_mix());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* timeslot queue handling */
|
|
||||||
static inline void enqueue_timeslot(uint8_t synthval) {
|
|
||||||
timeslots[timeslots_write & SYNTH_BUFMASK] = synthval;
|
|
||||||
timeslots_fill++;
|
|
||||||
timeslots_write++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint8_t dequeue_timeslot() {
|
|
||||||
uint8_t t = timeslots[timeslots_read & SYNTH_BUFMASK];
|
|
||||||
if (timeslots_fill) {
|
|
||||||
/* buffer not underrun... move forward in readbuffer */
|
|
||||||
|
|
||||||
timeslots_fill--;
|
|
||||||
timeslots_read++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
ISR(TIMER0_COMPA_vect) {
|
|
||||||
/* calculate next analog sample value in synth mixer:*/
|
|
||||||
OCR1B = dequeue_timeslot();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,34 +1,5 @@
|
||||||
#ifndef SYNTH_H
|
|
||||||
#define SYNTH_H
|
|
||||||
|
|
||||||
#define SYNTH_BUFSIZE (16)
|
|
||||||
#define SYNTH_BUFMASK (0b00001111)
|
|
||||||
|
|
||||||
enum {
|
|
||||||
WAVE_OFF, WAVE_PULSE, WAVE_SAW, WAVE_NOISE
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t note;
|
|
||||||
uint8_t inst_nr;
|
|
||||||
uint8_t pos;
|
|
||||||
|
|
||||||
uint16_t phase;
|
|
||||||
uint16_t pulse_width;
|
|
||||||
|
|
||||||
uint8_t level; // envelop level
|
|
||||||
|
|
||||||
} synth_channel_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint16_t pulse_width;
|
|
||||||
uint8_t pulse_sweep;
|
|
||||||
uint8_t wave_table_pos;
|
|
||||||
uint8_t decay;
|
|
||||||
|
|
||||||
} synth_instrument_t;
|
|
||||||
|
|
||||||
void synth_init(void);
|
void synth_init(void);
|
||||||
void synth_poll(void);
|
void synth_deinit(void);
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
225
firmware/main.c
225
firmware/main.c
|
@ -7,10 +7,13 @@
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
|
#define ever (;;) /* awesomnes++ */
|
||||||
|
|
||||||
#include "lib/usart.h"
|
#include "lib/usart.h"
|
||||||
#include "lib/bughal.h"
|
#include "lib/bughal.h"
|
||||||
#include "lib/util.h"
|
#include "lib/util.h"
|
||||||
#include "lib/music.h"
|
#include "lib/music.h"
|
||||||
|
#include "lib/synth.h"
|
||||||
|
|
||||||
//operartion modes
|
//operartion modes
|
||||||
#define MODE0 0
|
#define MODE0 0
|
||||||
|
@ -18,37 +21,40 @@
|
||||||
#define MODE2 2
|
#define MODE2 2
|
||||||
#define MODE3 3
|
#define MODE3 3
|
||||||
#define MODE4 4
|
#define MODE4 4
|
||||||
#define MODE5 5 //lightsensortest
|
#define MODE5 5
|
||||||
#define NUM_MODES 6
|
#define NUM_MODES 6
|
||||||
|
|
||||||
uint8_t OpMode = MODE5; //Operation mode
|
uint8_t OpMode = MODE5;
|
||||||
bool ModeChanged = true;
|
uint8_t NextMode = MODE5;
|
||||||
|
|
||||||
|
bool mode_uninitialized = true;
|
||||||
|
|
||||||
// check if mode should be changed (one of the buttons long pressed)
|
// check if mode should be changed (one of the buttons long pressed)
|
||||||
void modeswitch_poll(void) {
|
void modeswitch_poll(void)
|
||||||
|
{
|
||||||
if (btn_state(BTNST_LUP, BTN_LEFT)) {
|
if (btn_state(BTNST_LUP, BTN_LEFT)) {
|
||||||
//opmode -
|
//opmode -
|
||||||
OpMode = (0 == OpMode) ? (NUM_MODES - 1) : (OpMode - 1);
|
NextMode = (0 == OpMode) ? (NUM_MODES - 1) : (OpMode - 1);
|
||||||
ModeChanged = true;
|
mode_uninitialized = true;
|
||||||
button_clear(BTN_LEFT);
|
button_clear(BTN_LEFT);
|
||||||
};
|
};
|
||||||
if (btn_state(BTNST_LUP, BTN_RIGHT)) {
|
if (btn_state(BTNST_LUP, BTN_RIGHT)) {
|
||||||
//opmode +
|
//opmode +
|
||||||
ModeChanged = true;
|
mode_uninitialized = true;
|
||||||
OpMode = ((NUM_MODES - 1) == OpMode) ? 0 : (OpMode + 1);
|
NextMode = ((NUM_MODES - 1) == OpMode) ? 0 : (OpMode + 1);
|
||||||
button_clear(BTN_RIGHT);
|
button_clear(BTN_RIGHT);
|
||||||
};
|
};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
;
|
|
||||||
|
|
||||||
/* sound detection mode
|
/**
|
||||||
|
* sound detection mode
|
||||||
* beeps,blinks and moves when sound is detected
|
* beeps,blinks and moves when sound is detected
|
||||||
* - beep on/off left switch (short)
|
* - beep on/off left switch (short)
|
||||||
* - motor on/off right switch (short)
|
* - motor on/off right switch (short)
|
||||||
*/
|
*/
|
||||||
|
void do_mode0(void)
|
||||||
void do_mode0(void) {
|
{
|
||||||
static timer_t mytimer;
|
static timer_t mytimer;
|
||||||
static uint16_t maxval; //maximum of ADC values read during the las timer interval
|
static uint16_t maxval; //maximum of ADC values read during the las timer interval
|
||||||
static uint16_t lastmaxval; //maximum of values during last timer interval
|
static uint16_t lastmaxval; //maximum of values during last timer interval
|
||||||
|
@ -57,17 +63,17 @@ void do_mode0(void) {
|
||||||
static bool sound_on; //should sound be on when signaling
|
static bool sound_on; //should sound be on when signaling
|
||||||
static bool motor_on; //should motor be on when signaling
|
static bool motor_on; //should motor be on when signaling
|
||||||
|
|
||||||
if (ModeChanged) { //init after mode change
|
if (mode_uninitialized) { //init after mode change
|
||||||
maxval = 0;
|
maxval = 0;
|
||||||
lastmaxval = 000;
|
lastmaxval = 000;
|
||||||
ModeChanged = false;
|
mode_uninitialized = false;
|
||||||
signaling = false;
|
signaling = false;
|
||||||
sound_on = true;
|
sound_on = true;
|
||||||
motor_on = true;
|
motor_on = true;
|
||||||
init_mic();
|
init_mic();
|
||||||
init_leds();
|
init_leds();
|
||||||
timer_set(&mytimer, 10);
|
timer_set(&mytimer, 10);
|
||||||
};
|
}
|
||||||
|
|
||||||
// single ADC measurement
|
// single ADC measurement
|
||||||
curval = ADCW; // read result
|
curval = ADCW; // read result
|
||||||
|
@ -107,57 +113,48 @@ void do_mode0(void) {
|
||||||
timer_set(&mytimer, 5); //sound duration
|
timer_set(&mytimer, 5); //sound duration
|
||||||
} else {
|
} else {
|
||||||
timer_set(&mytimer, 1);
|
timer_set(&mytimer, 1);
|
||||||
};
|
}
|
||||||
lastmaxval = maxval;
|
lastmaxval = maxval;
|
||||||
maxval = 0;
|
maxval = 0;
|
||||||
}; //end if soundon
|
} //end if soundon
|
||||||
|
|
||||||
}; //end if timer_expired
|
} //end if timer_expired
|
||||||
|
|
||||||
}
|
} /* end mode0 */
|
||||||
;
|
|
||||||
//end do_mode0
|
|
||||||
|
|
||||||
/* soundtest mode, just play single tone
|
/**
|
||||||
* - left buttn: lower frequency
|
* do crazy sytesizer mode
|
||||||
* - right buttn: increase frequency
|
*
|
||||||
*/
|
*/
|
||||||
|
void do_mode1(void)
|
||||||
|
{
|
||||||
|
if (mode_uninitialized) {
|
||||||
|
mode_uninitialized = false;
|
||||||
|
synth_init();
|
||||||
|
}
|
||||||
|
|
||||||
void do_mode1(void) {
|
/*deinialisation required*/
|
||||||
static uint16_t tone;
|
if(OpMode != NextMode){
|
||||||
if (ModeChanged) {
|
synth_deinit();
|
||||||
ModeChanged = false;
|
}
|
||||||
tone = 1000;
|
return;
|
||||||
music_setNote(tone, 0);
|
|
||||||
init_leds();
|
|
||||||
led_off(LED_L | LED_R);
|
|
||||||
};
|
|
||||||
if (btn_state(BTNST_SUP, BTN_LEFT)) {
|
|
||||||
button_clear(BTN_LEFT);
|
|
||||||
tone += 10;
|
|
||||||
music_setNote(tone, 0);
|
|
||||||
};
|
|
||||||
if (btn_state(BTNST_SUP, BTN_RIGHT)) {
|
|
||||||
button_clear(BTN_RIGHT);
|
|
||||||
tone -= 10;
|
|
||||||
music_setNote(tone, 0);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
;
|
|
||||||
|
|
||||||
/* crazymoves mode
|
|
||||||
|
/**
|
||||||
|
* crazymoves mode
|
||||||
* - play random sounds and move in random fashion
|
* - play random sounds and move in random fashion
|
||||||
*/
|
*/
|
||||||
|
void do_mode2(void)
|
||||||
void do_mode2(void) {
|
{
|
||||||
static timer_t mytimer;
|
static timer_t mytimer;
|
||||||
uint8_t max = 50;
|
uint8_t max = 50;
|
||||||
uint8_t min = 5;
|
uint8_t min = 5;
|
||||||
uint16_t maxfreq = 5000;
|
uint16_t maxfreq = 5000;
|
||||||
uint16_t minfreq = 1000;
|
uint16_t minfreq = 1000;
|
||||||
|
|
||||||
if (ModeChanged) {
|
if (mode_uninitialized) {
|
||||||
ModeChanged = false;
|
mode_uninitialized = false;
|
||||||
music_setNote(NOTE_PAUSE, 4); //mute
|
music_setNote(NOTE_PAUSE, 4); //mute
|
||||||
timer_set(&mytimer, 10);
|
timer_set(&mytimer, 10);
|
||||||
init_leds();
|
init_leds();
|
||||||
|
@ -189,31 +186,32 @@ void do_mode2(void) {
|
||||||
|
|
||||||
//decide if to play sound (70% chance)
|
//decide if to play sound (70% chance)
|
||||||
if (rand() % 10 > 2) {
|
if (rand() % 10 > 2) {
|
||||||
music_setNote((rand() % (maxfreq - minfreq)) + minfreq, 0);
|
music_setNote((rand() % (maxfreq - minfreq)) + minfreq,
|
||||||
|
0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
timer_set(&mytimer, (rand() % (max - min)) + min);
|
timer_set(&mytimer, (rand() % (max - min)) + min);
|
||||||
}; //end if timer_expired
|
}//end if timer_expired
|
||||||
|
|
||||||
}
|
}
|
||||||
;
|
|
||||||
|
|
||||||
/* just blink mode
|
|
||||||
|
/**
|
||||||
|
* just blink mode
|
||||||
* - left/right button switch motor off/on
|
* - left/right button switch motor off/on
|
||||||
*/
|
*/
|
||||||
|
void do_mode3(void)
|
||||||
void do_mode3(void) {
|
{
|
||||||
static timer_t mytimer;
|
static timer_t mytimer;
|
||||||
static bool blink;
|
static bool blink;
|
||||||
if (ModeChanged) {
|
if (mode_uninitialized) {
|
||||||
init_leds();
|
init_leds();
|
||||||
ModeChanged = false;
|
mode_uninitialized = false;
|
||||||
music_setNote(NOTE_PAUSE, 4); //mute
|
music_setNote(NOTE_PAUSE, 4); //mute
|
||||||
set_motor(MOTOR_OFF);
|
set_motor(MOTOR_OFF);
|
||||||
timer_set(&mytimer, 10);
|
timer_set(&mytimer, 10);
|
||||||
blink = false;
|
blink = false;
|
||||||
};
|
}
|
||||||
|
|
||||||
if (timer_expired(&mytimer)) {
|
if (timer_expired(&mytimer)) {
|
||||||
if (!blink) {
|
if (!blink) {
|
||||||
|
@ -234,30 +232,31 @@ void do_mode3(void) {
|
||||||
button_clear(BTN_LEFT);
|
button_clear(BTN_LEFT);
|
||||||
set_motor(MOTOR_OFF);
|
set_motor(MOTOR_OFF);
|
||||||
|
|
||||||
};
|
}
|
||||||
if (btn_state(BTNST_SUP, BTN_RIGHT)) {
|
if (btn_state(BTNST_SUP, BTN_RIGHT)) {
|
||||||
button_clear(BTN_RIGHT);
|
button_clear(BTN_RIGHT);
|
||||||
set_motor(MOTOR_ON);
|
set_motor(MOTOR_ON);
|
||||||
};
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
;
|
|
||||||
|
|
||||||
|
|
||||||
/* ggrbug mode
|
|
||||||
|
/**
|
||||||
|
* ggrbug mode
|
||||||
* - simulate geiger counter sounds
|
* - simulate geiger counter sounds
|
||||||
*/
|
*/
|
||||||
|
void do_mode4(void)
|
||||||
void do_mode4(void) {
|
{
|
||||||
uint8_t max = 200;
|
uint8_t max = 200;
|
||||||
uint8_t min = 10;
|
uint8_t min = 10;
|
||||||
|
|
||||||
static timer_t mytimer;
|
static timer_t mytimer;
|
||||||
static bool blink;
|
static bool blink;
|
||||||
if (ModeChanged) {
|
if (mode_uninitialized) {
|
||||||
init_leds();
|
init_leds();
|
||||||
music_setNote(NOTE_PAUSE, 0);
|
music_setNote(NOTE_PAUSE, 0);
|
||||||
ModeChanged = false;
|
mode_uninitialized = false;
|
||||||
timer_set(&mytimer, 10);
|
timer_set(&mytimer, 10);
|
||||||
blink = false;
|
blink = false;
|
||||||
};
|
};
|
||||||
|
@ -287,81 +286,75 @@ void do_mode4(void) {
|
||||||
set_motor(MOTOR_OFF);
|
set_motor(MOTOR_OFF);
|
||||||
music_setNote(NOTE_PAUSE, 0);
|
music_setNote(NOTE_PAUSE, 0);
|
||||||
timer_set(&mytimer, (rand() % (max - min)) + min);
|
timer_set(&mytimer, (rand() % (max - min)) + min);
|
||||||
|
|
||||||
blink = false;
|
blink = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
} //end if timer_expired
|
} //end if timer_expired
|
||||||
|
|
||||||
}
|
}
|
||||||
;
|
|
||||||
void do_mode5(void) {
|
|
||||||
|
|
||||||
|
void do_mode5(void)
|
||||||
|
{
|
||||||
static bool discharge;
|
static bool discharge;
|
||||||
static timer_t mytimer;
|
static timer_t mytimer;
|
||||||
uint16_t led1;
|
uint16_t led1;
|
||||||
uint16_t led2;
|
uint16_t led2;
|
||||||
|
|
||||||
|
if (mode_uninitialized) {
|
||||||
if (ModeChanged) { //init after mode change
|
mode_uninitialized = false;
|
||||||
ModeChanged = false;
|
|
||||||
set_motor(MOTOR_OFF);
|
set_motor(MOTOR_OFF);
|
||||||
ADMUX = (1<<REFS0); //use VCC reference
|
ADMUX = (1 << REFS0); //use VCC reference
|
||||||
ADCSRA = (1<<ADPS1) | (1<<ADPS0);// prescaler F_CPU/8
|
ADCSRA = (1 << ADPS1) | (1 << ADPS0); // prescaler F_CPU/8
|
||||||
ADCSRA |= (1<<ADEN); // ADC enable - turn it on
|
ADCSRA |= (1 << ADEN); // ADC enable - turn it on
|
||||||
// do one conversion
|
// do one conversion
|
||||||
ADCSRA |= (1<<ADSC);
|
ADCSRA |= (1 << ADSC);
|
||||||
while (ADCSRA & (1<<ADSC) ) {} //wait for conversion to end
|
while (ADCSRA & (1 << ADSC)) {
|
||||||
uint16_t __attribute__((unused)) dummy = ADCW; //read once
|
} //wait for conversion to end
|
||||||
|
uint16_t __attribute__ ((unused)) dummy = ADCW; //read once
|
||||||
timer_set(&mytimer, 10);
|
timer_set(&mytimer, 10);
|
||||||
discharge = true;
|
discharge = true;
|
||||||
};
|
}
|
||||||
if (timer_expired(&mytimer)) {
|
if (timer_expired(&mytimer)) {
|
||||||
if (discharge){
|
if (discharge) {
|
||||||
//discharge LED
|
//discharge LED
|
||||||
//enable LED channels as output
|
//enable LED channels as output
|
||||||
DDRC |= (1 << PORTC0) | (1 << PORTC1) | (1 << PORTC2) | (1 << PORTC3);
|
DDRC |= (1 << PORTC0) | (1 << PORTC1) |
|
||||||
|
(1 << PORTC2) | (1 << PORTC3) ;
|
||||||
// discharge
|
// discharge
|
||||||
PORTC = (PORTC & 0b11110000);
|
PORTC = (PORTC & 0b11110000);
|
||||||
//set C0 and C2 to input (disable pullups)
|
//set C0 and C2 to input (disable pullups)
|
||||||
DDRC &= ~( (1 << PORTC0) | (1 << PORTC2));
|
DDRC &= ~((1 << PORTC0) | (1 << PORTC2));
|
||||||
//pull ups off
|
//pull ups off
|
||||||
PORTC &= ~( (1 << PORTC0) | (1 << PORTC2));
|
PORTC &= ~((1 << PORTC0) | (1 << PORTC2));
|
||||||
discharge = false;
|
discharge = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
//make a measurement
|
|
||||||
// single measurement
|
// single measurement
|
||||||
ADMUX = (ADMUX & ~(0x1F)) | 0; // select channel 0
|
ADMUX = (ADMUX & ~(0x1F)) | 0; // select channel 0
|
||||||
ADCSRA |= (1<<ADSC); // start single conversion
|
ADCSRA |= (1 << ADSC); // start single conversion
|
||||||
while (ADCSRA & (1<<ADSC) ) {}; // wait for conversion to end
|
while (ADCSRA & (1 << ADSC)) ; // wait for conversion to end
|
||||||
led1 =ADCW; // read result
|
led1 = ADCW; // read result
|
||||||
ADMUX = (ADMUX & ~(0x1F)) | 2; // select channel 2
|
ADMUX = (ADMUX & ~(0x1F)) | 2; // select channel 2
|
||||||
ADCSRA |= (1<<ADSC); // start single conversion
|
ADCSRA |= (1 << ADSC); // start single conversion
|
||||||
while (ADCSRA & (1<<ADSC) ) {}; // wait for conversion to end
|
while (ADCSRA & (1 << ADSC)) ; // wait for conversion to end
|
||||||
led2 =ADCW; // read result
|
led2 = ADCW; // read result
|
||||||
// USART0_putc('1');USART0_putc(':');USART0_put_uint16(led1);USART0_crlf();
|
#if 0
|
||||||
// USART0_putc('2');USART0_putc(':');USART0_put_uint16(led2);USART0_crlf();
|
USART0_putc('1');USART0_putc(':');USART0_put_uint16(led1);USART0_crlf();
|
||||||
music_setNote(400+((0x1ff-led1)+(0x1ff-led2))*5,0);
|
USART0_putc('2');USART0_putc(':');USART0_put_uint16(led2);USART0_crlf();
|
||||||
|
#endif
|
||||||
|
music_setNote(400 +((0x1ff - led1) + (0x1ff - led2)) * 5, 0);
|
||||||
discharge = true;
|
discharge = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
timer_set(&mytimer, 2); //relaunch timer
|
||||||
|
}//end if timer_expired
|
||||||
|
|
||||||
|
}//end mode5
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
timer_set(&mytimer, 2);
|
void __attribute__ ((noreturn))
|
||||||
}; //end if timer_expired
|
main(void)
|
||||||
|
{
|
||||||
}
|
|
||||||
;
|
|
||||||
//end do_mode5
|
|
||||||
|
|
||||||
/* our main method
|
|
||||||
* things happen right here
|
|
||||||
*/
|
|
||||||
|
|
||||||
void __attribute__((noreturn))
|
|
||||||
main(void) {
|
|
||||||
/* hardware initialisation: */
|
/* hardware initialisation: */
|
||||||
init_leds();
|
init_leds();
|
||||||
init_buzzr();
|
init_buzzr();
|
||||||
|
@ -372,10 +365,10 @@ main(void) {
|
||||||
timer_init();
|
timer_init();
|
||||||
music_init();
|
music_init();
|
||||||
|
|
||||||
/* here the show begins:*/sei();
|
/* here the show begins: */
|
||||||
|
sei();
|
||||||
|
|
||||||
for (;;) /* ever */{
|
for ever {
|
||||||
//do something
|
|
||||||
//main polling loop;
|
//main polling loop;
|
||||||
button_poll();
|
button_poll();
|
||||||
modeswitch_poll();
|
modeswitch_poll();
|
||||||
|
@ -398,11 +391,9 @@ main(void) {
|
||||||
default:
|
default:
|
||||||
do_mode0();
|
do_mode0();
|
||||||
break;
|
break;
|
||||||
};
|
}
|
||||||
|
OpMode = NextMode;
|
||||||
};
|
}
|
||||||
|
|
||||||
/* never return 0; */
|
|
||||||
}
|
}
|
||||||
;
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user