Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
1076 lines (903 sloc) 25.3 KB
#include <stdio.h>
// asf
#include "delay.h"
#include "compiler.h"
#include "flashc.h"
#include "preprocessor.h"
#include "print_funcs.h"
#include "intc.h"
#include "pm.h"
#include "gpio.h"
#include "spi.h"
#include "sysclk.h"
// skeleton
#include "types.h"
#include "events.h"
#include "i2c.h"
#include "init_trilogy.h"
#include "init_common.h"
#include "monome.h"
#include "timers.h"
#include "adc.h"
#include "util.h"
#include "ftdi.h"
#include "twi.h"
// this
#include "conf_board.h"
#include "ii.h"
#define FIRSTRUN_KEY 0x22
#define L2 12
#define L1 8
#define L0 4
u8 edit_row, key_count = 0, mode = 0, prev_mode = 0;
s8 kcount = 0;
s8 scount[8] = {0,0,0,0,0,0,0,0};
const u8 sign[8][8] = {{0,0,0,0,0,0,0,0}, // o
{0,24,24,126,126,24,24,0}, // +
{0,0,0,126,126,0,0,0}, // -
{0,96,96,126,126,96,96,0}, // >
{0,6,6,126,126,6,6,0}, // <
{0,102,102,24,24,102,102,0}, // * rnd
{0,120,120,102,102,30,30,0}, // <> up/down
{0,126,126,102,102,126,126,0}}; // [] sync
const u8 outs[8] = {B00, B01, B02, B03, B04, B05, B06, B07};
u8 state[8] = {0,0,0,0,0,0,0,0};
u8 clear[8] = {0,0,0,0,0,0,0,0};
typedef struct {
u8 count[8]; // length of cycle
s8 position[8]; // current position in cycle
s8 speed[8]; // speed of cycle
u8 tick[8]; // position in speed countdown
u8 min[8];
u8 max[8];
u8 trigger[8];
u8 toggle[8];
u8 rules[8];
u8 rule_dests[8];
u8 sync[8]; // if true, reset dest rule to count
u8 sound;
u8 pushed[8];
u8 rule_dest_targets[8];
u8 smin[8];
u8 smax[8];
} mp_set;
typedef const struct {
u8 fresh;
u8 preset_select;
u8 glyph[8][8];
mp_set m[8];
} nvram_data_t;
mp_set m;
u8 preset_mode, preset_select, front_timer;
u8 glyph[8];
u8 clock_phase;
u16 clock_time, clock_temp;
u8 divknob, divmode;
s8 divtime;
u32 clockdivtime;
u8 clockdivcount;
u16 adc[4];
u8 SIZE, LENGTH, VARI;
u8 held_keys[32], key_times[256];
typedef void(*re_t)(void);
re_t re;
// NVRAM data structure located in the flash array.
__attribute__((__section__(".flash_nvram")))
static nvram_data_t flashy;
////////////////////////////////////////////////////////////////////////////////
// prototypes
static void refresh(void);
static void refresh_mono(void);
static void refresh_preset(void);
static void clock(u8 phase);
// start/stop monome polling/refresh timers
extern void timers_set_monome(void);
extern void timers_unset_monome(void);
// check the event queue
static void check_events(void);
// handler protos
static void handler_None(s32 data) { ;; }
static void handler_KeyTimer(s32 data);
static void handler_Front(s32 data);
static void handler_ClockNormal(s32 data);
static void handler_ClockExt(s32 data);
u8 flash_is_fresh(void);
void flash_unfresh(void);
void flash_write(void);
void flash_read(void);
static void mp_process_ii(uint8_t *data, uint8_t l);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// application clock code
void clock(u8 phase) {
static u8 i;
if(phase) {
gpio_set_gpio_pin(B10);
for(i=0;i<8;i++) {
if(m.pushed[i]) {
for(int n=0;n<8;n++) {
if(m.sync[i] & (1<<n)) {
m.position[n] = m.count[n];
m.tick[n] = m.speed[n];
}
if(m.trigger[i] & (1<<n)) {
state[n] = 1;
clear[n] = 1;
}
else if(m.toggle[i] & (1<<n)) {
state[n] ^= 1;
}
}
m.pushed[i] = 0;
}
if(m.tick[i] == 0) {
m.tick[i] = m.speed[i];
if(m.position[i] == 0) {
// RULES
if(m.rules[i] == 1) { // inc
if(m.rule_dest_targets[i] & 1) {
m.count[m.rule_dests[i]]++;
if(m.count[m.rule_dests[i]] > m.max[m.rule_dests[i]]) {
m.count[m.rule_dests[i]] = m.min[m.rule_dests[i]];
}
}
if(m.rule_dest_targets[i] & 2) {
m.speed[m.rule_dests[i]]++;
if(m.speed[m.rule_dests[i]] > m.smax[m.rule_dests[i]]) {
m.speed[m.rule_dests[i]] = m.smin[m.rule_dests[i]];
}
}
}
else if(m.rules[i] == 2) { // dec
if(m.rule_dest_targets[i] & 1) {
m.count[m.rule_dests[i]]--;
if(m.count[m.rule_dests[i]] < m.min[m.rule_dests[i]]) {
m.count[m.rule_dests[i]] = m.max[m.rule_dests[i]];
}
}
if(m.rule_dest_targets[i] & 2) {
m.speed[m.rule_dests[i]]--;
if(m.speed[m.rule_dests[i]] < m.smin[m.rule_dests[i]]) {
m.speed[m.rule_dests[i]] = m.smax[m.rule_dests[i]];
}
}
}
else if(m.rules[i] == 3) { // max
if(m.rule_dest_targets[i] & 1)
m.count[m.rule_dests[i]] = m.max[m.rule_dests[i]];
if(m.rule_dest_targets[i] & 2)
m.speed[m.rule_dests[i]] = m.smax[m.rule_dests[i]];
}
else if(m.rules[i] == 4) { // min
if(m.rule_dest_targets[i] & 1)
m.count[m.rule_dests[i]] = m.min[m.rule_dests[i]];
if(m.rule_dest_targets[i] & 2)
m.speed[m.rule_dests[i]] = m.smin[m.rule_dests[i]];
}
else if(m.rules[i] == 5) { // rnd
if(m.rule_dest_targets[i] & 1)
m.count[m.rule_dests[i]] =
(rnd() % (m.max[m.rule_dests[i]] - m.min[m.rule_dests[i]] + 1)) + m.min[m.rule_dests[i]];
if(m.rule_dest_targets[i] & 2)
m.speed[m.rule_dests[i]] =
(rnd() % (m.smax[m.rule_dests[i]] - m.smin[m.rule_dests[i]] + 1)) + m.smin[m.rule_dests[i]];
// print_dbg("\r\n RANDOM: ");
// print_dbg_hex(m.count[m.rule_dests[i]]);
// print_dbg_hex(rnd() % 11);
}
else if(m.rules[i] == 6) { // pole
if(m.rule_dest_targets[i] & 1) {
if(abs(m.count[m.rule_dests[i]] - m.min[m.rule_dests[i]]) <
abs(m.count[m.rule_dests[i]] - m.max[m.rule_dests[i]]) ) {
m.count[m.rule_dests[i]] = m.max[m.rule_dests[i]];
}
else {
m.count[m.rule_dests[i]] = m.min[m.rule_dests[i]];
}
}
if(m.rule_dest_targets[i] & 2) {
if(abs(m.speed[m.rule_dests[i]] - m.smin[m.rule_dests[i]]) <
abs(m.speed[m.rule_dests[i]] - m.smax[m.rule_dests[i]]) ) {
m.speed[m.rule_dests[i]] = m.smax[m.rule_dests[i]];
}
else {
m.speed[m.rule_dests[i]] = m.smin[m.rule_dests[i]];
}
}
}
else if(m.rules[i] == 7) { // stop
if(m.rule_dest_targets[i] & 1)
m.position[m.rule_dests[i]] = -1;
}
m.position[i]--;
for(int n=0;n<8;n++) {
if(m.sync[i] & (1<<n)) {
m.position[n] = m.count[n];
m.tick[n] = m.speed[n];
}
if(m.trigger[i] & (1<<n)) {
state[n] = 1;
clear[n] = 1;
}
else if(m.toggle[i] & (1<<n)) {
state[n] ^= 1;
}
}
}
else if(m.position[i] > 0) m.position[i]--;
}
else m.tick[i]--;
}
for(i=0;i<8;i++)
if(state[i])
gpio_set_gpio_pin(outs[i]);
else
gpio_clr_gpio_pin(outs[i]);
monomeFrameDirty++;
}
else {
gpio_clr_gpio_pin(B10);
for(i=0;i<8;i++) {
if(clear[i]) {
gpio_clr_gpio_pin(outs[i]);
state[i] = 0;
}
clear[i] = 0;
}
}
}
////////////////////////////////////////////////////////////////////////////////
// timers
static softTimer_t clockTimer = { .next = NULL, .prev = NULL };
static softTimer_t keyTimer = { .next = NULL, .prev = NULL };
static softTimer_t adcTimer = { .next = NULL, .prev = NULL };
static softTimer_t monomePollTimer = { .next = NULL, .prev = NULL };
static softTimer_t monomeRefreshTimer = { .next = NULL, .prev = NULL };
static void clockTimer_callback(void* o) {
if(clock_external == 0 || (clock_external && !divmode)) {
clock_phase++;
if(clock_phase>1)
clock_phase=0;
(*clock_pulse)(clock_phase);
}
}
static void keyTimer_callback(void* o) {
static event_t e;
e.type = kEventKeyTimer;
e.data = 0;
event_post(&e);
}
static void adcTimer_callback(void* o) {
static event_t e;
e.type = kEventPollADC;
e.data = 0;
event_post(&e);
}
// monome polling callback
static void monome_poll_timer_callback(void* obj) {
// asynchronous, non-blocking read
// UHC callback spawns appropriate events
ftdi_read();
}
// monome refresh callback
static void monome_refresh_timer_callback(void* obj) {
if(monomeFrameDirty > 0) {
static event_t e;
e.type = kEventMonomeRefresh;
event_post(&e);
}
}
// monome: start polling
void timers_set_monome(void) {
// print_dbg("\r\n setting monome timers");
timer_add(&monomePollTimer, 20, &monome_poll_timer_callback, NULL );
timer_add(&monomeRefreshTimer, 30, &monome_refresh_timer_callback, NULL );
}
// monome stop polling
void timers_unset_monome(void) {
// print_dbg("\r\n unsetting monome timers");
timer_remove( &monomePollTimer );
timer_remove( &monomeRefreshTimer );
}
////////////////////////////////////////////////////////////////////////////////
// event handlers
static void handler_FtdiConnect(s32 data) { ftdi_setup(); }
static void handler_FtdiDisconnect(s32 data) {
timers_unset_monome();
// event_t e = { .type = kEventMonomeDisconnect };
// event_post(&e);
}
static void handler_MonomeConnect(s32 data) {
// print_dbg("\r\n// monome connect /////////////////");
key_count = 0;
SIZE = monome_size_x();
LENGTH = SIZE - 1;
// print_dbg("\r monome size: ");
// print_dbg_ulong(SIZE);
VARI = monome_is_vari();
// print_dbg("\r monome vari: ");
// print_dbg_ulong(VARI);
if(VARI) re = &refresh;
else re = &refresh_mono;
// monome_set_quadrant_flag(0);
// monome_set_quadrant_flag(1);
timers_set_monome();
}
static void handler_MonomePoll(s32 data) { monome_read_serial(); }
static void handler_MonomeRefresh(s32 data) {
if(monomeFrameDirty) {
if(preset_mode == 0) (*re)(); //refresh_mono();
else refresh_preset();
(*monome_refresh)();
}
}
static void handler_PollADC(s32 data) {
u16 i;
adc_convert(&adc);
if(clock_external) {
i = adc[0] / 455;
if(i != divknob) {
divknob = i;
divtime = divknob - 4;
if(divtime <= 0) {
divmode = 1;
divtime = -1 * divtime;
}
else {
divmode = 0;
}
divtime = 1 << divtime;
}
}
else {
// CLOCK POT INPUT
i = adc[0];
i = i>>2;
if(i != clock_temp) {
// 500ms - 12ms
clock_time = 12500 / (i + 25);
// print_dbg("\r\nclock (ms): ");
// print_dbg_ulong(clock_time);
timer_set(&clockTimer, clock_time);
}
clock_temp = i;
}
}
static void handler_Front(s32 data) {
print_dbg("\r\n FRONT HOLD");
if(data == 0) {
front_timer = 15;
if(preset_mode) preset_mode = 0;
else preset_mode = 1;
}
else {
front_timer = 0;
}
monomeFrameDirty++;
}
static void handler_SaveFlash(s32 data) {
flash_write();
}
static void handler_KeyTimer(s32 data) {
static u16 i1;
if(front_timer) {
if(front_timer == 1) {
static event_t e;
e.type = kEventSaveFlash;
event_post(&e);
preset_mode = 0;
front_timer--;
}
else front_timer--;
}
for(i1=0;i1<key_count;i1++) {
if(key_times[held_keys[i1]])
if(--key_times[held_keys[i1]]==0) {
if(preset_mode == 1) {
if(held_keys[i1] % 16 == 0) {
preset_select = held_keys[i1] / 16;
// flash_write();
static event_t e;
e.type = kEventSaveFlash;
event_post(&e);
preset_mode = 0;
}
}
// print_dbg("\rlong press: ");
// print_dbg_ulong(held_keys[i1]);
}
}
}
static void handler_ClockNormal(s32 data) {
clock_external = !gpio_get_pin_value(B09);
}
static void handler_ClockExt(s32 data) {
clockdivtime = time_now();
time_clear();
// div by 9. 16 8 4 2 0 2 4 8 16
if(divmode && divtime == 1)
clock(data);
else if(divmode && data) {
clockdivcount++;
if(clockdivcount == (divtime >> 1)) {
clock(0);
}
else if(clockdivcount >= divtime) {
clock(1);
clockdivcount = 0;
}
}
else if(data) {
clockdivtime = (clockdivtime / divtime);
timer_reset_set(&clockTimer, clockdivtime);
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// application grid code
static void handler_MonomeGridKey(s32 data) {
u8 x, y, z, index, i1, found;
monome_grid_key_parse_event_data(data, &x, &y, &z);
// print_dbg("\r\n monome event; x: ");
// print_dbg_hex(x);
// print_dbg("; y: 0x");
// print_dbg_hex(y);
// print_dbg("; z: 0x");
// print_dbg_hex(z);
//// TRACK LONG PRESSES
index = y*16 + x;
if(z) {
held_keys[key_count] = index;
key_count++;
key_times[index] = 10; //// THRESHOLD key hold time
} else {
found = 0; // "found"
for(i1 = 0; i1<key_count; i1++) {
if(held_keys[i1] == index)
found++;
if(found)
held_keys[i1] = held_keys[i1+1];
}
key_count--;
// FAST PRESS
if(key_times[index] > 0) {
if(preset_mode == 1) {
if(x == 0 && y != preset_select) {
preset_select = y;
for(i1=0;i1<8;i1++)
glyph[i1] = flashy.glyph[preset_select][i1];
}
else if(x==0 && y == preset_select) {
flash_read();
preset_mode = 0;
}
monomeFrameDirty++;
}
// print_dbg("\r\nfast press: ");
// print_dbg_ulong(index);
// print_dbg(": ");
// print_dbg_ulong(key_times[index]);
}
}
// PRESET SCREEN
if(preset_mode) {
// glyph magic
if(z && x>7) {
glyph[y] ^= 1<<(x-8);
}
monomeFrameDirty++;
}
// NOT PRESET
else {
prev_mode = mode;
// mode check
if(x == 0) {
kcount += (z<<1)-1;
if(kcount < 0)
kcount = 0;
// print_dbg("\r\nkey count: ");
// print_dbg_ulong(kcount);
if(kcount == 1 && z == 1)
mode = 1;
else if(kcount == 0) {
mode = 0;
scount[y] = 0;
}
if(z == 1 && mode == 1) {
edit_row = y;
}
}
else if(x == 1 && mode != 0) {
if(mode == 1 && z == 1) {
mode = 2;
edit_row = y;
}
else if(mode == 2 && z == 0)
mode = 1;
}
// set position / minmax / stop
else if(mode == 0) {
scount[y] += (z<<1)-1;
if(scount[y]<0) scount[y] = 0; // in case of grid glitch?
if(z == 1 && scount[y] == 1) {
m.position[y] = x;
m.count[y] = x;
m.min[y] = x;
m.max[y] = x;
m.tick[y] = m.speed[y];
if(m.sound) {
m.pushed[y] = 1;
}
}
else if(z == 1 && scount[y] == 2) {
if(x < m.count[y]) {
m.min[y] = x;
m.max[y] = m.count[y];
}
else {
m.max[y] = x;
m.min[y] = m.count[y];
}
}
}
// set speeds and trig/tog
else if(mode == 1) {
scount[y] += (z<<1)-1;
if(scount[y]<0) scount[y] = 0;
if(z==1) {
if(x > 7) {
if(scount[y] == 1) {
m.smin[y] = x-8;
m.smax[y] = x-8;
m.speed[y] = x-8;
m.tick[y] = m.speed[y];
}
else if(scount[y] == 2) {
if(x-8 < m.smin[y]) {
m.smax[y] = m.smin[y];
m.smin[y] = x-8;
}
else
m.smax[y] = x-8;
}
}
else if(x == 5) {
m.toggle[edit_row] ^= 1<<y;
m.trigger[edit_row] &= ~(1<<y);
}
else if(x == 6) {
m.trigger[edit_row] ^= 1<<y;
m.toggle[edit_row] &= ~(1<<y);
}
else if(x == 4) {
m.sound ^= 1;
}
else if(x == 2) {
if(m.position[y] == -1) {
m.position[y] = m.count[y];
}
else {
m.position[y] = -1;
}
}
else if(x == 3) {
m.sync[edit_row] ^= (1<<y);
}
}
}
else if(mode == 2 && z == 1) {
if(x > 3 && x < 7) {
m.rule_dests[edit_row] = y;
m.rule_dest_targets[edit_row] = x-3;
// post("\nrule_dests", edit_row, ":", rule_dests[edit_row]);
}
else if(x > 6) {
m.rules[edit_row] = y;
// post("\nrules", edit_row, ":", rules[edit_row]);
}
}
monomeFrameDirty++;
}
}
////////////////////////////////////////////////////////////////////////////////
// application grid redraw
static void refresh() {
u8 i1, i2, i3;
// clear grid
for(i1=0;i1<128;i1++)
monomeLedBuffer[i1] = 0;
// SHOW POSITIONS
if(mode == 0) {
for(i1=0;i1<8;i1++) {
for(i2=m.min[i1];i2<=m.max[i1];i2++)
monomeLedBuffer[i1*16 + i2] = L0;
monomeLedBuffer[i1*16 + m.count[i1]] = L1;
if(m.position[i1] >= 0) {
monomeLedBuffer[i1*16 + m.position[i1]] = L2;
}
}
}
// SHOW SPEED
else if(mode == 1) {
for(i1=0;i1<8;i1++) {
if(m.position[i1] >= 0)
monomeLedBuffer[i1*16 + m.position[i1]] = L0;
if(m.position[i1] != -1)
monomeLedBuffer[i1*16 + 2] = 2;
for(i2=m.smin[i1];i2<=m.smax[i1];i2++)
monomeLedBuffer[i1*16 + i2+8] = L0;
monomeLedBuffer[i1*16 + m.speed[i1]+8] = L1;
if(m.sound)
monomeLedBuffer[i1*16 + 4] = 2;
if(m.toggle[edit_row] & (1 << i1))
monomeLedBuffer[i1*16 + 5] = L2;
else
monomeLedBuffer[i1*16 + 5] = L0;
if(m.trigger[edit_row] & (1 << i1))
monomeLedBuffer[i1*16 + 6] = L2;
else
monomeLedBuffer[i1*16 + 6] = L0;
if(m.sync[edit_row] & (1<<i1))
monomeLedBuffer[i1*16 + 3] = L1;
else
monomeLedBuffer[i1*16 + 3] = L0;
}
monomeLedBuffer[edit_row * 16] = L2;
}
// SHOW RULES
else if(mode == 2) {
for(i1=0;i1<8;i1++)
if(m.position[i1] >= 0)
monomeLedBuffer[i1*16 + m.position[i1]] = L0;
monomeLedBuffer[edit_row * 16] = L1;
monomeLedBuffer[edit_row * 16 + 1] = L1;
if(m.rule_dest_targets[edit_row] == 1) {
monomeLedBuffer[m.rule_dests[edit_row] * 16 + 4] = L2;
monomeLedBuffer[m.rule_dests[edit_row] * 16 + 5] = L0;
monomeLedBuffer[m.rule_dests[edit_row] * 16 + 6] = L0;
}
else if (m.rule_dest_targets[edit_row] == 2) {
monomeLedBuffer[m.rule_dests[edit_row] * 16 + 4] = L0;
monomeLedBuffer[m.rule_dests[edit_row] * 16 + 5] = L2;
monomeLedBuffer[m.rule_dests[edit_row] * 16 + 6] = L0;
}
else {
monomeLedBuffer[m.rule_dests[edit_row] * 16 + 4] = L2;
monomeLedBuffer[m.rule_dests[edit_row] * 16 + 5] = L2;
monomeLedBuffer[m.rule_dests[edit_row] * 16 + 6] = L0;
}
for(i1=8;i1<16;i1++)
monomeLedBuffer[m.rules[edit_row] * 16 + i1] = L0;
for(i1=0;i1<8;i1++) {
i3 = sign[m.rules[edit_row]][i1];
for(i2=0;i2<8;i2++) {
if((i3 & (1<<i2)) != 0)
monomeLedBuffer[i1*16 + 8 + i2] = L2;
}
}
}
monome_set_quadrant_flag(0);
monome_set_quadrant_flag(1);
}
// application grid redraw without varibright
static void refresh_mono() {
refresh();
// monome_set_quadrant_flag(0);
// monome_set_quadrant_flag(1);
}
static void refresh_preset() {
u8 i1,i2;
for(i1=0;i1<128;i1++)
monomeLedBuffer[i1] = 0;
monomeLedBuffer[preset_select * 16] = 11;
for(i1=0;i1<8;i1++)
for(i2=0;i2<8;i2++)
if(glyph[i1] & (1<<i2))
monomeLedBuffer[i1*16+i2+8] = 11;
monome_set_quadrant_flag(0);
monome_set_quadrant_flag(1);
}
static void mp_process_ii(uint8_t *data, uint8_t l) {
uint8_t i;
int d;
i = data[0];
d = (data[1] << 8) + data[2];
switch(i) {
case MP_PRESET:
if(d<0 || d>7)
break;
preset_select = d;
flash_read();
break;
case MP_RESET:
if(d>0 && d<9) {
d--;
m.position[d] = m.count[d];
m.tick[d] = m.speed[d];
}
else if(d==0) {
for(int n=0;n<8;n++) {
m.position[n] = m.count[n];
m.tick[n] = m.speed[n];
}
}
break;
case MP_STOP:
if(d>0 && d<9) {
d--;
m.position[d] = -1;
}
else if(d==0) {
for(int n=0;n<8;n++)
m.position[n] = -1;
}
break;
default:
break;
}
// print_dbg("\r\nmp: ");
// print_dbg_ulong(i);
// print_dbg(" ");
// print_dbg_ulong(d);
}
// assign event handlers
static inline void assign_main_event_handlers(void) {
app_event_handlers[ kEventFront ] = &handler_Front;
app_event_handlers[ kEventKeyTimer ] = &handler_KeyTimer;
app_event_handlers[ kEventSaveFlash ] = &handler_SaveFlash;
app_event_handlers[ kEventPollADC ] = &handler_PollADC;
app_event_handlers[ kEventClockNormal ] = &handler_ClockNormal;
app_event_handlers[ kEventClockExt ] = &handler_ClockExt;
app_event_handlers[ kEventFtdiConnect ] = &handler_FtdiConnect ;
app_event_handlers[ kEventFtdiDisconnect ] = &handler_FtdiDisconnect ;
app_event_handlers[ kEventMonomeConnect ] = &handler_MonomeConnect ;
app_event_handlers[ kEventMonomeDisconnect ] = &handler_None ;
app_event_handlers[ kEventMonomePoll ] = &handler_MonomePoll ;
app_event_handlers[ kEventMonomeRefresh ] = &handler_MonomeRefresh ;
app_event_handlers[ kEventMonomeGridKey ] = &handler_MonomeGridKey ;
}
// app event loop
void check_events(void) {
static event_t e;
if( event_next(&e) ) {
(app_event_handlers)[e.type](e.data);
}
}
// flash commands
u8 flash_is_fresh(void) {
return (flashy.fresh != FIRSTRUN_KEY);
// flashc_memcpy((void *)&flashy.fresh, &i, sizeof(flashy.fresh), true);
// flashc_memset32((void*)&(flashy.fresh), fresh_MAGIC, 4, true);
// flashc_memset((void *)nvram_data, 0x00, 8, sizeof(*nvram_data), true);
}
// write fresh status
void flash_unfresh(void) {
flashc_memset8((void*)&(flashy.fresh), FIRSTRUN_KEY, 4, true);
}
void flash_write(void) {
// print_dbg("\r write preset ");
// print_dbg_ulong(preset_select);
flashc_memcpy((void *)&flashy.m[preset_select], &m, sizeof(m), true);
flashc_memcpy((void *)&flashy.glyph[preset_select], &glyph, sizeof(glyph), true);
flashc_memset8((void*)&(flashy.preset_select), preset_select, 1, true);
}
void flash_read(void) {
u8 i1;
print_dbg("\r\n read preset ");
print_dbg_ulong(preset_select);
// for(i1=0;i1<16;i1++) {
// for(i2=0;i2<16;i2++) {
// w.wp[i1].steps[i2] = flashy.w[preset_select].wp[i1].steps[i2];
// w.wp[i1].step_probs[i2] = flashy.w[preset_select].wp[i1].step_probs[i2];
// w.wp[i1].cv_probs[0][i2] = flashy.w[preset_select].wp[i1].cv_probs[0][i2];
// w.wp[i1].cv_probs[1][i2] = flashy.w[preset_select].wp[i1].cv_probs[1][i2];
// w.wp[i1].cv_curves[0][i2] = flashy.w[preset_select].wp[i1].cv_curves[0][i2];
// w.wp[i1].cv_curves[1][i2] = flashy.w[preset_select].wp[i1].cv_curves[1][i2];
// w.wp[i1].cv_steps[0][i2] = flashy.w[preset_select].wp[i1].cv_steps[0][i2];
// w.wp[i1].cv_steps[1][i2] = flashy.w[preset_select].wp[i1].cv_steps[1][i2];
// w.wp[i1].cv_values[i2] = flashy.w[preset_select].wp[i1].cv_values[i2];
// }
// w.wp[i1].step_choice = flashy.w[preset_select].wp[i1].step_choice;
// w.wp[i1].loop_end = flashy.w[preset_select].wp[i1].loop_end;
// w.wp[i1].loop_len = flashy.w[preset_select].wp[i1].loop_len;
// w.wp[i1].loop_start = flashy.w[preset_select].wp[i1].loop_start;
// w.wp[i1].loop_dir = flashy.w[preset_select].wp[i1].loop_dir;
// w.wp[i1].step_mode = flashy.w[preset_select].wp[i1].step_mode;
// w.wp[i1].cv_mode[0] = flashy.w[preset_select].wp[i1].cv_mode[0];
// w.wp[i1].cv_mode[1] = flashy.w[preset_select].wp[i1].cv_mode[1];
// }
for(i1=0;i1<8;i1++) {
m.count[i1] = flashy.m[preset_select].count[i1];
m.position[i1] = flashy.m[preset_select].position[i1];
m.speed[i1] = flashy.m[preset_select].speed[i1];
m.tick[i1] = flashy.m[preset_select].tick[i1];
m.min[i1] = flashy.m[preset_select].min[i1];
m.max[i1] = flashy.m[preset_select].max[i1];
m.trigger[i1] = flashy.m[preset_select].trigger[i1];
m.toggle[i1] = flashy.m[preset_select].toggle[i1];
m.rules[i1] = flashy.m[preset_select].rules[i1];
m.rule_dests[i1] = flashy.m[preset_select].rule_dests[i1];
m.sync[i1] = flashy.m[preset_select].sync[i1];
m.rule_dest_targets[i1] = flashy.m[preset_select].rule_dest_targets[i1];
m.smin[i1] = flashy.m[preset_select].smin[i1];
m.smax[i1] = flashy.m[preset_select].smax[i1];
}
m.sound = flashy.m[preset_select].sound;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// main
int main(void) {
u8 i1;
sysclk_init();
init_dbg_rs232(FMCK_HZ);
init_gpio();
assign_main_event_handlers();
init_events();
init_tc();
init_spi();
init_adc();
irq_initialize_vectors();
register_interrupts();
cpu_irq_enable();
init_usb_host();
init_monome();
init_i2c_follower(0x30);
print_dbg("\r\n\n// meadowphysics //////////////////////////////// ");
print_dbg_ulong(sizeof(flashy));
print_dbg(" ");
print_dbg_ulong(sizeof(m));
if(flash_is_fresh()) {
print_dbg("\r\nfirst run.");
flash_unfresh();
flashc_memset32((void*)&(flashy.preset_select), 0, 4, true);
// clear out some reasonable defaults
for(i1=0;i1<8;i1++) {
m.count[i1] = 7+i1;
m.position[i1] = 7+i1;
m.speed[i1] = 0;
m.tick[i1] = 0;
m.min[i1] = 7+i1;
m.max[i1] = 7+i1;
m.trigger[i1] = (1<<i1);
m.toggle[i1] = 0;
m.rules[i1] = 1;
m.rule_dests[i1] = i1;
m.sync[i1] = (1<<i1);
m.rule_dest_targets[i1] = 3;
m.smin[i1] = 0;
m.smax[i1] = 0;
}
// save all presets, clear glyphs
for(i1=0;i1<8;i1++) {
flashc_memcpy((void *)&flashy.m[i1], &m, sizeof(m), true);
glyph[i1] = (1<<i1);
flashc_memcpy((void *)&flashy.glyph[i1], &glyph, sizeof(glyph), true);
}
}
else {
// load from flash at startup
preset_select = flashy.preset_select;
flash_read();
for(i1=0;i1<8;i1++)
glyph[i1] = flashy.glyph[preset_select][i1];
}
LENGTH = 15;
SIZE = 16;
re = &refresh;
process_ii = &mp_process_ii;
clock_pulse = &clock;
clock_external = !gpio_get_pin_value(B09);
timer_add(&clockTimer,120,&clockTimer_callback, NULL);
timer_add(&keyTimer,50,&keyTimer_callback, NULL);
timer_add(&adcTimer,100,&adcTimer_callback, NULL);
clock_temp = 10000; // out of ADC range to force tempo
while (true) {
check_events();
}
}