Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
2151 lines (1854 sloc) 57.1 KB
/* issues
- preset save blip with internal timer vs ext trig
*/
#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"
// this
#include "conf_board.h"
#include "ii.h"
#define FIRSTRUN_KEY 0x22
const u16 SCALES[24][16] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // ZERO
{0, 68, 136, 170, 238, 306, 375, 409, 477, 545, 579, 647, 715, 784, 818, 886}, // ionian [2, 2, 1, 2, 2, 2, 1]
{0, 68, 102, 170, 238, 306, 340, 409, 477, 511, 579, 647, 715, 750, 818, 886}, // dorian [2, 1, 2, 2, 2, 1, 2]
{0, 34, 102, 170, 238, 272, 340, 409, 443, 511, 579, 647, 681, 750, 818, 852}, // phrygian [1, 2, 2, 2, 1, 2, 2]
{0, 68, 136, 204, 238, 306, 375, 409, 477, 545, 613, 647, 715, 784, 818, 886}, // lydian [2, 2, 2, 1, 2, 2, 1]
{0, 68, 136, 170, 238, 306, 340, 409, 477, 545, 579, 647, 715, 750, 818, 886}, // mixolydian [2, 2, 1, 2, 2, 1, 2]
{0, 68, 136, 170, 238, 306, 340, 409, 477, 545, 579, 647, 715, 750, 818, 886}, // aeolian [2, 1, 2, 2, 1, 2, 2]
{0, 34, 102, 170, 204, 272, 340, 409, 443, 511, 579, 613, 681, 750, 818, 852}, // locrian [1, 2, 2, 1, 2, 2, 2]
{0, 34, 68, 102, 136, 170, 204, 238, 272, 306, 341, 375, 409, 443, 477, 511}, // chromatic
{0, 68, 136, 204, 272, 341, 409, 477, 545, 613, 682, 750, 818, 886, 954, 1022}, // whole
{0, 170, 340, 511, 681, 852, 1022, 1193, 1363, 1534, 1704, 1875, 2045, 2215, 2386, 2556}, // fourths
{0, 238, 477, 715, 954, 1193, 1431, 1670, 1909, 2147, 2386, 2625, 2863, 3102, 3340, 3579}, // fifths
{0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255}, // quarter
{0, 8, 17, 25, 34, 42, 51, 59, 68, 76, 85, 93, 102, 110, 119, 127}, // eighth
{0, 61, 122, 163, 245, 327, 429, 491, 552, 613, 654, 736, 818, 920, 982, 1105}, // just
{0, 61, 130, 163, 245, 337, 441, 491, 552, 621, 654, 736, 828, 932, 982, 1105}, // pythagorean
{0, 272, 545, 818, 1090, 1363, 1636, 1909, 2181, 2454, 2727, 3000, 3272, 3545, 3818, 4091}, // equal 10v
{0, 136, 272, 409, 545, 682, 818, 955, 1091, 1228, 1364, 1501, 1637, 1774, 1910, 2047}, // equal 5v
{0, 68, 136, 204, 272, 341, 409, 477, 545, 613, 682, 750, 818, 886, 954, 1023}, // equal 2.5v
{0, 34, 68, 102, 136, 170, 204, 238, 272, 306, 340, 374, 408, 442, 476, 511}, // equal 1.25v
{0, 53, 118, 196, 291, 405, 542, 708, 908, 1149, 1441, 1792, 2216, 2728, 3345, 4091}, // log-ish 10v
{0, 136, 272, 409, 545, 682, 818, 955, 1091, 1228, 1364, 1501, 1637, 1774, 1910, 2047}, // log-ish 5v
{0, 745, 1362, 1874, 2298, 2649, 2941, 3182, 3382, 3548, 3685, 3799, 3894, 3972, 4037, 4091}, // exp-ish 10v
{0, 372, 681, 937, 1150, 1325, 1471, 1592, 1692, 1775, 1844, 1901, 1948, 1987, 2020, 2047} // exp-ish 5v
};
typedef enum {
mTrig, mMap, mSeries
} edit_modes;
typedef enum {
mForward=0, mReverse, mDrunk, mRandom, mPing, mPingRep
} step_modes;
typedef enum {
mPingFwd = 1,
mPingRev = -1
} ping_direction;
typedef struct {
u8 loop_start, loop_end, loop_len, loop_dir;
u16 step_choice;
u8 cv_mode[2];
u8 tr_mode;
step_modes step_mode;
ping_direction ping_dir;
u8 steps[16];
u8 step_probs[16];
u16 cv_values[16];
u16 cv_steps[2][16];
u16 cv_curves[2][16];
u8 cv_probs[2][16];
} whale_pattern;
typedef struct {
whale_pattern wp[16];
u16 series_list[64];
u8 series_start, series_end;
u8 tr_mute[4];
u8 cv_mute[2];
} whale_set;
typedef const struct {
u8 fresh;
edit_modes edit_mode;
u8 preset_select;
u8 glyph[8][8];
whale_set w[8];
} nvram_data_t;
whale_set w;
u8 preset_mode, preset_select, front_timer;
u8 glyph[8];
edit_modes edit_mode;
u8 edit_cv_step, edit_cv_ch;
s8 edit_cv_value;
u8 edit_prob, live_in, scale_select;
u8 pattern, next_pattern, pattern_jump, ping_pattern_jump;
u8 series_pos, series_next, series_jump, series_playing, scroll_pos;
u8 key_alt, key_meta, center;
u8 held_keys[32], key_count, key_times[256];
u8 keyfirst_pos, keysecond_pos;
s8 keycount_pos, keycount_series, keycount_cv;
s8 pos, cut_pos, next_pos, drunk_step, triggered;
u8 cv_chosen[2];
u16 cv0, cv1;
u8 param_accept, *param_dest8;
u16 clip;
u16 *param_dest;
u8 quantize_in;
u8 clock_phase;
u16 clock_time, clock_temp;
u8 series_step;
u16 adc[4];
u8 SIZE, LENGTH, VARI;
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);
static void ww_process_ii(uint8_t *data, uint8_t l);
u8 flash_is_fresh(void);
void flash_unfresh(void);
void flash_write(void);
void flash_read(void);
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// application clock code
void clock(u8 phase) {
static u8 i1, count;
static u16 found[16];
if(phase) {
gpio_set_gpio_pin(B10);
if(pattern_jump) {
pattern = next_pattern;
next_pos = w.wp[pattern].loop_start;
pattern_jump = 0;
}
// for series mode and delayed pattern change
if(series_jump) {
series_pos = series_next;
if(series_pos == w.series_end)
series_next = w.series_start;
else {
series_next++;
if(series_next>63)
series_next = w.series_start;
}
// print_dbg("\r\nSERIES next ");
// print_dbg_ulong(series_next);
// print_dbg(" pos ");
// print_dbg_ulong(series_pos);
count = 0;
for(i1=0;i1<16;i1++) {
if((w.series_list[series_pos] >> i1) & 1) {
found[count] = i1;
count++;
}
}
if(count == 1)
next_pattern = found[0];
else {
next_pattern = found[rnd()%count];
}
pattern = next_pattern;
series_playing = pattern;
if(w.wp[pattern].step_mode == mReverse)
next_pos = w.wp[pattern].loop_end;
else {
next_pos = w.wp[pattern].loop_start;
w.wp[pattern].ping_dir = mPingFwd;
}
series_jump = 0;
series_step = 0;
}
pos = next_pos;
// live param record
if(param_accept && live_in) {
param_dest = &w.wp[pattern].cv_curves[edit_cv_ch][pos];
w.wp[pattern].cv_curves[edit_cv_ch][pos] = adc[1];
}
// calc next step
if(w.wp[pattern].step_mode == mForward) { // FORWARD
if(pos == w.wp[pattern].loop_end)
next_pos = w.wp[pattern].loop_start;
else if(pos >= LENGTH) next_pos = 0;
else next_pos++;
cut_pos = 0;
}
else if(w.wp[pattern].step_mode == mReverse) { // REVERSE
if(pos == w.wp[pattern].loop_start)
next_pos = w.wp[pattern].loop_end;
else if(pos <= 0)
next_pos = LENGTH;
else next_pos--;
cut_pos = 0;
}
else if(w.wp[pattern].step_mode == mDrunk) { // DRUNK
drunk_step += (rnd() % 3) - 1; // -1 to 1
if(drunk_step < -1) drunk_step = -1;
else if(drunk_step > 1) drunk_step = 1;
next_pos += drunk_step;
if(next_pos < 0)
next_pos = LENGTH;
else if(next_pos > LENGTH)
next_pos = 0;
else if(w.wp[pattern].loop_dir == 1 && next_pos < w.wp[pattern].loop_start)
next_pos = w.wp[pattern].loop_end;
else if(w.wp[pattern].loop_dir == 1 && next_pos > w.wp[pattern].loop_end)
next_pos = w.wp[pattern].loop_start;
else if(w.wp[pattern].loop_dir == 2 && next_pos < w.wp[pattern].loop_start && next_pos > w.wp[pattern].loop_end) {
if(drunk_step == 1)
next_pos = w.wp[pattern].loop_start;
else
next_pos = w.wp[pattern].loop_end;
}
cut_pos = 1;
}
else if(w.wp[pattern].step_mode == mRandom) { // RANDOM
next_pos = (rnd() % (w.wp[pattern].loop_len + 1)) + w.wp[pattern].loop_start;
// print_dbg("\r\nnext pos:");
// print_dbg_ulong(next_pos);
if(next_pos > LENGTH) next_pos -= LENGTH + 1;
cut_pos = 1;
}
else if(w.wp[pattern].step_mode == mPing) { // PING, 12343212
if(pos == w.wp[pattern].loop_end && mPingFwd == w.wp[pattern].ping_dir) {
w.wp[pattern].ping_dir = mPingRev;
next_pos += w.wp[pattern].ping_dir;
}
else if(pos == w.wp[pattern].loop_start && mPingRev == w.wp[pattern].ping_dir) {
w.wp[pattern].ping_dir = mPingFwd;
// set this here because this step changes the state needed to identify the switch
ping_pattern_jump = 1;
next_pos += w.wp[pattern].ping_dir;
}
else if(pos >= LENGTH) next_pos = 0;
else next_pos += w.wp[pattern].ping_dir;
cut_pos = 0;
}
else if(w.wp[pattern].step_mode == mPingRep) { // PINGREP, 1234432112
if(pos == w.wp[pattern].loop_end && mPingFwd == w.wp[pattern].ping_dir) {
w.wp[pattern].ping_dir = mPingRev;
}
else if(pos == w.wp[pattern].loop_end && mPingRev == w.wp[pattern].ping_dir) {
next_pos += w.wp[pattern].ping_dir;
}
else if(pos == w.wp[pattern].loop_start && mPingRev == w.wp[pattern].ping_dir) {
w.wp[pattern].ping_dir = mPingFwd;
// set this here because this step changes the state needed to identify the switch
ping_pattern_jump = 1;
}
else if(pos == w.wp[pattern].loop_start && mPingFwd == w.wp[pattern].ping_dir) {
next_pos += w.wp[pattern].ping_dir;
}
else if(pos >= LENGTH) next_pos = 0;
else next_pos += w.wp[pattern].ping_dir;
cut_pos = 0;
}
// guard against -ve next_pos from skip back
if (next_pos < 0) {
next_pos = 0;
}
// next pattern?
if(pos == w.wp[pattern].loop_end && w.wp[pattern].step_mode == mForward) {
if(edit_mode == mSeries)
series_jump++;
else if(next_pattern != pattern)
pattern_jump++;
}
else if(pos == w.wp[pattern].loop_start && w.wp[pattern].step_mode == mReverse) {
if(edit_mode == mSeries)
series_jump++;
else if(next_pattern != pattern)
pattern_jump++;
}
else if(ping_pattern_jump == 1 && (w.wp[pattern].step_mode == mPing || w.wp[pattern].step_mode == mPingRep)) {
if(edit_mode == mSeries)
series_jump++;
else if(next_pattern != pattern)
pattern_jump++;
}
else if(series_step == w.wp[pattern].loop_len && w.wp[pattern].step_mode != mPing && w.wp[pattern].step_mode != mPingRep) {
series_jump++;
}
// reset this
ping_pattern_jump = 0;
if(edit_mode == mSeries)
series_step++;
// PARAM 0
if((rnd() % 255) < w.wp[pattern].cv_probs[0][pos] && w.cv_mute[0]) {
if(w.wp[pattern].cv_mode[0] == 0) {
cv0 = w.wp[pattern].cv_curves[0][pos];
}
else {
count = 0;
for(i1=0;i1<16;i1++)
if(w.wp[pattern].cv_steps[0][pos] & (1<<i1)) {
found[count] = i1;
count++;
}
if(count == 1)
cv_chosen[0] = found[0];
else
cv_chosen[0] = found[rnd() % count];
cv0 = w.wp[pattern].cv_values[cv_chosen[0]];
}
}
// PARAM 1
if((rnd() % 255) < w.wp[pattern].cv_probs[1][pos] && w.cv_mute[1]) {
if(w.wp[pattern].cv_mode[1] == 0) {
cv1 = w.wp[pattern].cv_curves[1][pos];
}
else {
count = 0;
for(i1=0;i1<16;i1++)
if(w.wp[pattern].cv_steps[1][pos] & (1<<i1)) {
found[count] = i1;
count++;
}
if(count == 1)
cv_chosen[1] = found[0];
else
cv_chosen[1] = found[rnd() % count];
cv1 = w.wp[pattern].cv_values[cv_chosen[1]];
}
}
// write to DAC
spi_selectChip(DAC_SPI,DAC_SPI_NPCS);
// spi_write(SPI,0x39); // update both
spi_write(DAC_SPI,0x31); // update A
// spi_write(SPI,0x38); // update B
// spi_write(SPI,pos*15); // send position
// spi_write(SPI,0);
spi_write(DAC_SPI,cv0>>4);
spi_write(DAC_SPI,cv0<<4);
spi_unselectChip(DAC_SPI,DAC_SPI_NPCS);
spi_selectChip(DAC_SPI,DAC_SPI_NPCS);
spi_write(DAC_SPI,0x38); // update B
spi_write(DAC_SPI,cv1>>4);
spi_write(DAC_SPI,cv1<<4);
spi_unselectChip(SPI,DAC_SPI_NPCS);
// TRIGGER
triggered = 0;
if((rnd() % 255) < w.wp[pattern].step_probs[pos]) {
if(w.wp[pattern].step_choice & 1<<pos) {
count = 0;
for(i1=0;i1<4;i1++)
if(w.wp[pattern].steps[pos] >> i1 & 1) {
found[count] = i1;
count++;
}
if(count == 0)
triggered = 0;
else if(count == 1)
triggered = 1<<found[0];
else
triggered = 1<<found[rnd()%count];
}
else {
triggered = w.wp[pattern].steps[pos];
}
if(w.wp[pattern].tr_mode == 0) {
if(triggered & 0x1 && w.tr_mute[0]) gpio_set_gpio_pin(B00);
if(triggered & 0x2 && w.tr_mute[1]) gpio_set_gpio_pin(B01);
if(triggered & 0x4 && w.tr_mute[2]) gpio_set_gpio_pin(B02);
if(triggered & 0x8 && w.tr_mute[3]) gpio_set_gpio_pin(B03);
} else {
if(w.tr_mute[0]) {
if(triggered & 0x1) gpio_set_gpio_pin(B00);
else gpio_clr_gpio_pin(B00);
}
if(w.tr_mute[1]) {
if(triggered & 0x2) gpio_set_gpio_pin(B01);
else gpio_clr_gpio_pin(B01);
}
if(w.tr_mute[2]) {
if(triggered & 0x4) gpio_set_gpio_pin(B02);
else gpio_clr_gpio_pin(B02);
}
if(w.tr_mute[3]) {
if(triggered & 0x8) gpio_set_gpio_pin(B03);
else gpio_clr_gpio_pin(B03);
}
}
}
monomeFrameDirty++;
}
else {
gpio_clr_gpio_pin(B10);
if(w.wp[pattern].tr_mode == 0) {
gpio_clr_gpio_pin(B00);
gpio_clr_gpio_pin(B01);
gpio_clr_gpio_pin(B02);
gpio_clr_gpio_pin(B03);
}
}
// print_dbg("\r\n pos: ");
// print_dbg_ulong(pos);
}
////////////////////////////////////////////////////////////////////////////////
// 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) {
// static event_t e;
// e.type = kEventTimer;
// e.data = 0;
// event_post(&e);
if(clock_external == 0) {
// print_dbg("\r\ntimer.");
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) {
u8 i1;
// print_dbg("\r\n// monome connect /////////////////");
keycount_pos = 0;
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;
for(i1=0;i1<16;i1++)
if(w.wp[i1].loop_end > LENGTH)
w.wp[i1].loop_end = LENGTH;
// 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_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_PollADC(s32 data) {
u16 i;
adc_convert(&adc);
// CLOCK POT INPUT
i = adc[0];
i = i>>2;
if(i != clock_temp) {
// 1000ms - 24ms
clock_time = 25000 / (i + 25);
// print_dbg("\r\nnew clock (ms): ");
// print_dbg_ulong(clock_time);
timer_set(&clockTimer, clock_time);
}
clock_temp = i;
// PARAM POT INPUT
if(param_accept && edit_prob) {
*param_dest8 = adc[1] >> 4; // scale to 0-255;
// print_dbg("\r\nnew prob: ");
// print_dbg_ulong(*param_dest8);
// print_dbg("\t" );
// print_dbg_ulong(adc[1]);
}
else if(param_accept) {
if(quantize_in)
*param_dest = (adc[1] / 34) * 34;
else
*param_dest = adc[1];
monomeFrameDirty++;
}
else if(key_meta) {
i = adc[1]>>6;
if(i > 58)
i = 58;
if(i != scroll_pos) {
scroll_pos = i;
monomeFrameDirty++;
// print_dbg("\r scroll pos: ");
// print_dbg_ulong(scroll_pos);
}
}
}
static void handler_SaveFlash(s32 data) {
flash_write();
}
static void handler_KeyTimer(s32 data) {
static u16 i1,x,n1;
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(edit_mode != mSeries && preset_mode == 0) {
// preset copy
if(held_keys[i1] / 16 == 2) {
x = held_keys[i1] % 16;
for(n1=0;n1<16;n1++) {
w.wp[x].steps[n1] = w.wp[pattern].steps[n1];
w.wp[x].step_probs[n1] = w.wp[pattern].step_probs[n1];
w.wp[x].cv_values[n1] = w.wp[pattern].cv_values[n1];
w.wp[x].cv_steps[0][n1] = w.wp[pattern].cv_steps[0][n1];
w.wp[x].cv_curves[0][n1] = w.wp[pattern].cv_curves[0][n1];
w.wp[x].cv_probs[0][n1] = w.wp[pattern].cv_probs[0][n1];
w.wp[x].cv_steps[1][n1] = w.wp[pattern].cv_steps[1][n1];
w.wp[x].cv_curves[1][n1] = w.wp[pattern].cv_curves[1][n1];
w.wp[x].cv_probs[1][n1] = w.wp[pattern].cv_probs[1][n1];
}
w.wp[x].cv_mode[0] = w.wp[pattern].cv_mode[0];
w.wp[x].cv_mode[1] = w.wp[pattern].cv_mode[1];
w.wp[x].loop_start = w.wp[pattern].loop_start;
w.wp[x].loop_end = w.wp[pattern].loop_end;
w.wp[x].loop_len = w.wp[pattern].loop_len;
w.wp[x].loop_dir = w.wp[pattern].loop_dir;
w.wp[x].tr_mode = w.wp[pattern].tr_mode;
w.wp[x].step_mode = w.wp[pattern].step_mode;
w.wp[x].ping_dir = w.wp[pattern].ping_dir;
pattern = x;
next_pattern = x;
monomeFrameDirty++;
// print_dbg("\r\n saved pattern: ");
// print_dbg_ulong(x);
}
}
else 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) {
clock(data);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// application grid code
static void handler_MonomeGridKey(s32 data) {
u8 x, y, z, index, i1, found, count;
s16 delta;
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(edit_mode != mSeries && preset_mode == 0) {
if(index/16 == 2) {
i1 = index % 16;
if(key_alt)
next_pattern = i1;
else {
pattern = i1;
next_pattern = i1;
}
}
}
// PRESET MODE FAST PRESS DETECT
else 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;
}
}
// 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 {
// OPTIMIZE: order this if-branch by common priority/use
//// SORT
// cut position
if(y == 1) {
keycount_pos += z * 2 - 1;
if(keycount_pos < 0) keycount_pos = 0;
// print_dbg("\r\nkeycount: ");
// print_dbg_ulong(keycount_pos);
if(keycount_pos == 1 && z) {
if(key_alt == 0) {
if(key_meta != 1) {
next_pos = x;
cut_pos++;
monomeFrameDirty++;
}
keyfirst_pos = x;
}
else if(key_alt == 1) {
if ((LENGTH > 8 && (LENGTH - x) <= mPingRep) || ((LENGTH - x) <= mPing)) {
// Step modes, mPingRep not available on 8x8 grid
w.wp[pattern].step_mode = LENGTH-x;
w.wp[pattern].ping_dir = mPingFwd;
}
// FIXME
else if(x == 0) {
if(pos == w.wp[pattern].loop_start)
next_pos = w.wp[pattern].loop_end;
else if(pos == 0)
next_pos = LENGTH;
else next_pos--;
cut_pos = 1;
monomeFrameDirty++;
}
// FIXME
else if(x == 1) {
if(pos == w.wp[pattern].loop_end) next_pos = w.wp[pattern].loop_start;
else if(pos == LENGTH) next_pos = 0;
else next_pos++;
cut_pos = 1;
monomeFrameDirty++;
}
else if(x == 2 ) {
next_pos = (rnd() % (w.wp[pattern].loop_len + 1)) + w.wp[pattern].loop_start;
cut_pos = 1;
monomeFrameDirty++;
}
}
}
else if(keycount_pos == 2 && z) {
w.wp[pattern].loop_start = keyfirst_pos;
w.wp[pattern].loop_end = x;
monomeFrameDirty++;
if(w.wp[pattern].loop_start > w.wp[pattern].loop_end) w.wp[pattern].loop_dir = 2;
else if(w.wp[pattern].loop_start == 0 && w.wp[pattern].loop_end == LENGTH) w.wp[pattern].loop_dir = 0;
else w.wp[pattern].loop_dir = 1;
w.wp[pattern].loop_len = w.wp[pattern].loop_end - w.wp[pattern].loop_start;
if(w.wp[pattern].loop_dir == 2)
w.wp[pattern].loop_len = (LENGTH - w.wp[pattern].loop_start) + w.wp[pattern].loop_end + 1;
// print_dbg("\r\nloop_len: ");
// print_dbg_ulong(w.wp[pattern].loop_len);
}
}
// top row
else if(y == 0) {
if(x == LENGTH) {
key_alt = z;
if(z == 0) {
param_accept = 0;
live_in = 0;
}
monomeFrameDirty++;
}
else if(x < 4 && z) {
if(key_alt)
w.wp[pattern].tr_mode ^= 1;
else if(key_meta)
w.tr_mute[x] ^= 1;
else
edit_mode = mTrig;
edit_prob = 0;
param_accept = 0;
monomeFrameDirty++;
}
else if(SIZE==16 && x > 3 && x < 12 && z) {
param_accept = 0;
edit_cv_ch = (x-4)/4;
edit_prob = 0;
if(key_alt)
w.wp[pattern].cv_mode[edit_cv_ch] ^= 1;
else if(key_meta)
w.cv_mute[edit_cv_ch] ^= 1;
else
edit_mode = mMap;
monomeFrameDirty++;
}
else if(SIZE==8 && (x == 4 || x == 5) && z) {
param_accept = 0;
edit_cv_ch = x-4;
edit_mode = mMap;
edit_prob = 0;
if(key_alt)
w.wp[pattern].cv_mode[edit_cv_ch] ^= 1;
else if(key_meta)
w.cv_mute[edit_cv_ch] ^= 1;
monomeFrameDirty++;
}
else if(x == LENGTH-1 && z && key_alt) {
edit_mode = mSeries;
monomeFrameDirty++;
}
else if(x == LENGTH-1)
key_meta = z;
}
// toggle steps and prob control
else if(edit_mode == mTrig) {
if(z && y>3 && edit_prob == 0) {
if(key_alt)
w.wp[pattern].steps[pos] |= 1 << (y-4);
else if(key_meta) {
w.wp[pattern].step_choice ^= (1<<x);
}
else
w.wp[pattern].steps[x] ^= (1<<(y-4));
monomeFrameDirty++;
}
// step probs
else if(z && y==3) {
if(key_alt)
edit_prob = 1;
else {
if(w.wp[pattern].step_probs[x] == 255) w.wp[pattern].step_probs[x] = 0;
else w.wp[pattern].step_probs[x] = 255;
}
monomeFrameDirty++;
}
else if(edit_prob == 1) {
if(z) {
if(y == 4) w.wp[pattern].step_probs[x] = 192;
else if(y == 5) w.wp[pattern].step_probs[x] = 128;
else if(y == 6) w.wp[pattern].step_probs[x] = 64;
else w.wp[pattern].step_probs[x] = 0;
}
}
}
// edit map and probs
else if(edit_mode == mMap) {
// step probs
if(z && y==3) {
if(key_alt)
edit_prob = 1;
else {
if(w.wp[pattern].cv_probs[edit_cv_ch][x] == 255) w.wp[pattern].cv_probs[edit_cv_ch][x] = 0;
else w.wp[pattern].cv_probs[edit_cv_ch][x] = 255;
}
monomeFrameDirty++;
}
// edit data
else if(edit_prob == 0) {
// CURVES
if(w.wp[pattern].cv_mode[edit_cv_ch] == 0) {
if(y == 4 && z) {
if(center)
delta = 3;
else if(key_alt)
delta = 409;
else
delta = 34;
if(key_meta == 0) {
// saturate
if(w.wp[pattern].cv_curves[edit_cv_ch][x] + delta < 4092)
w.wp[pattern].cv_curves[edit_cv_ch][x] += delta;
else
w.wp[pattern].cv_curves[edit_cv_ch][x] = 4092;
}
else {
for(i1=0;i1<16;i1++) {
// saturate
if(w.wp[pattern].cv_curves[edit_cv_ch][i1] + delta < 4092)
w.wp[pattern].cv_curves[edit_cv_ch][i1] += delta;
else
w.wp[pattern].cv_curves[edit_cv_ch][i1] = 4092;
}
}
}
else if(y == 6 && z) {
if(center)
delta = 3;
else if(key_alt)
delta = 409;
else
delta = 34;
if(key_meta == 0) {
// saturate
if(w.wp[pattern].cv_curves[edit_cv_ch][x] > delta)
w.wp[pattern].cv_curves[edit_cv_ch][x] -= delta;
else
w.wp[pattern].cv_curves[edit_cv_ch][x] = 0;
}
else {
for(i1=0;i1<16;i1++) {
// saturate
if(w.wp[pattern].cv_curves[edit_cv_ch][i1] > delta)
w.wp[pattern].cv_curves[edit_cv_ch][i1] -= delta;
else
w.wp[pattern].cv_curves[edit_cv_ch][i1] = 0;
}
}
}
else if(y == 5) {
if(z == 1) {
center = 1;
if(quantize_in)
quantize_in = 0;
else if(key_alt)
w.wp[pattern].cv_curves[edit_cv_ch][x] = clip;
else
clip = w.wp[pattern].cv_curves[edit_cv_ch][x];
}
else
center = 0;
}
else if(y == 7) {
if(key_alt && z) {
param_dest = &w.wp[pattern].cv_curves[edit_cv_ch][pos];
w.wp[pattern].cv_curves[edit_cv_ch][pos] = (adc[1] / 34) * 34;
quantize_in = 1;
param_accept = 1;
live_in = 1;
}
else if(center && z) {
if(key_meta == 0)
w.wp[pattern].cv_curves[edit_cv_ch][x] = rand() % ((adc[1] / 34) * 34 + 1);
else {
for(i1=0;i1<16;i1++) {
w.wp[pattern].cv_curves[edit_cv_ch][i1] = rand() % ((adc[1] / 34) * 34 + 1);
}
}
}
else {
param_accept = z;
param_dest = &w.wp[pattern].cv_curves[edit_cv_ch][x];
if(z) {
w.wp[pattern].cv_curves[edit_cv_ch][x] = (adc[1] / 34) * 34;
quantize_in = 1;
}
else
quantize_in = 0;
}
monomeFrameDirty++;
}
}
// MAP
else {
if(scale_select && z) {
// index -= 64;
index = (y-4) * 8 + x;
if(index < 24 && y<8) {
for(i1=0;i1<16;i1++)
w.wp[pattern].cv_values[i1] = SCALES[index][i1];
print_dbg("\rNEW SCALE ");
print_dbg_ulong(index);
}
scale_select = 0;
monomeFrameDirty++;
}
else {
if(z && y==4) {
edit_cv_step = x;
count = 0;
for(i1=0;i1<16;i1++)
if((w.wp[pattern].cv_steps[edit_cv_ch][edit_cv_step] >> i1) & 1) {
count++;
edit_cv_value = i1;
}
if(count>1)
edit_cv_value = -1;
keycount_cv = 0;
monomeFrameDirty++;
}
// load scale
else if(key_alt && y==7 && x == 0 && z) {
scale_select++;
monomeFrameDirty++;
}
// read pot
else if(y==7 && key_alt && edit_cv_value != -1 && x==LENGTH) {
param_accept = z;
param_dest = &(w.wp[pattern].cv_values[edit_cv_value]);
// print_dbg("\r\nparam: ");
// print_dbg_ulong(*param_dest);
}
else if((y == 5 || y == 6) && z && x<4 && edit_cv_step != -1) {
delta = 0;
if(x == 0)
delta = 409;
else if(x == 1)
delta = 239;
else if(x == 2)
delta = 34;
else if(x == 3)
delta = 3;
if(y == 6)
delta *= -1;
if(key_alt) {
for(i1=0;i1<16;i1++) {
if(w.wp[pattern].cv_values[i1] + delta > 4092)
w.wp[pattern].cv_values[i1] = 4092;
else if(delta < 0 && w.wp[pattern].cv_values[i1] < -1*delta)
w.wp[pattern].cv_values[i1] = 0;
else
w.wp[pattern].cv_values[i1] += delta;
}
}
else {
if(w.wp[pattern].cv_values[edit_cv_value] + delta > 4092)
w.wp[pattern].cv_values[edit_cv_value] = 4092;
else if(delta < 0 && w.wp[pattern].cv_values[edit_cv_value] < -1*delta)
w.wp[pattern].cv_values[edit_cv_value] = 0;
else
w.wp[pattern].cv_values[edit_cv_value] += delta;
}
monomeFrameDirty++;
}
// choose values
else if(y==7) {
keycount_cv += z*2-1;
if(keycount_cv < 0)
keycount_cv = 0;
if(z) {
count = 0;
for(i1=0;i1<16;i1++)
if((w.wp[pattern].cv_steps[edit_cv_ch][edit_cv_step] >> i1) & 1)
count++;
// single press toggle
if(keycount_cv == 1 && count < 2) {
w.wp[pattern].cv_steps[edit_cv_ch][edit_cv_step] = (1<<x);
edit_cv_value = x;
}
// multiselect
else if(keycount_cv > 1 || count > 1) {
w.wp[pattern].cv_steps[edit_cv_ch][edit_cv_step] ^= (1<<x);
if(!w.wp[pattern].cv_steps[edit_cv_ch][edit_cv_step])
w.wp[pattern].cv_steps[edit_cv_ch][edit_cv_step] = (1<<x);
count = 0;
for(i1=0;i1<16;i1++)
if((w.wp[pattern].cv_steps[edit_cv_ch][edit_cv_step] >> i1) & 1) {
count++;
edit_cv_value = i1;
}
if(count > 1)
edit_cv_value = -1;
}
monomeFrameDirty++;
}
}
}
}
}
else if(edit_prob == 1) {
if(z) {
if(y == 4) w.wp[pattern].cv_probs[edit_cv_ch][x] = 192;
else if(y == 5) w.wp[pattern].cv_probs[edit_cv_ch][x] = 128;
else if(y == 6) w.wp[pattern].cv_probs[edit_cv_ch][x] = 64;
else w.wp[pattern].cv_probs[edit_cv_ch][x] = 0;
}
}
}
// series mode
else if(edit_mode == mSeries) {
if(z && key_alt) {
if(x == 0)
series_next = y-2+scroll_pos;
else if(x == LENGTH-1)
w.series_start = y-2+scroll_pos;
else if(x == LENGTH)
w.series_end = y-2+scroll_pos;
if(w.series_end < w.series_start)
w.series_end = w.series_start;
}
else {
keycount_series += z*2-1;
if(keycount_series < 0)
keycount_series = 0;
if(z) {
count = 0;
for(i1=0;i1<16;i1++)
count += (w.series_list[y-2+scroll_pos] >> i1) & 1;
// single press toggle
if(keycount_series == 1 && count < 2) {
w.series_list[y-2+scroll_pos] = (1<<x);
}
// multi-select
else if(keycount_series > 1 || count > 1) {
w.series_list[y-2+scroll_pos] ^= (1<<x);
// ensure not fully clear
if(!w.series_list[y-2+scroll_pos])
w.series_list[y-2+scroll_pos] = (1<<x);
}
}
}
monomeFrameDirty++;
}
}
}
////////////////////////////////////////////////////////////////////////////////
// application grid redraw
static void refresh() {
u8 i1,i2;
// clear top, cut, pattern, prob
for(i1=0;i1<16;i1++) {
monomeLedBuffer[i1] = 0;
monomeLedBuffer[16+i1] = 0;
monomeLedBuffer[32+i1] = 4;
monomeLedBuffer[48+i1] = 0;
}
// dim mode
if(edit_mode == mTrig) {
monomeLedBuffer[0] = 4;
monomeLedBuffer[1] = 4;
monomeLedBuffer[2] = 4;
monomeLedBuffer[3] = 4;
}
else if(edit_mode == mMap) {
if(SIZE==16) {
monomeLedBuffer[4+(edit_cv_ch*4)] = 4;
monomeLedBuffer[5+(edit_cv_ch*4)] = 4;
monomeLedBuffer[6+(edit_cv_ch*4)] = 4;
monomeLedBuffer[7+(edit_cv_ch*4)] = 4;
}
else
monomeLedBuffer[4+edit_cv_ch] = 4;
}
else if(edit_mode == mSeries) {
monomeLedBuffer[LENGTH-1] = 7;
}
// alt
monomeLedBuffer[LENGTH] = 4;
if(key_alt) monomeLedBuffer[LENGTH] = 11;
// show mutes or on steps
if(key_meta) {
if(w.tr_mute[0]) monomeLedBuffer[0] = 11;
if(w.tr_mute[1]) monomeLedBuffer[1] = 11;
if(w.tr_mute[2]) monomeLedBuffer[2] = 11;
if(w.tr_mute[3]) monomeLedBuffer[3] = 11;
}
else if(triggered) {
if(triggered & 0x1 && w.tr_mute[0]) monomeLedBuffer[0] = 11 - 4 * w.wp[pattern].tr_mode;
if(triggered & 0x2 && w.tr_mute[1]) monomeLedBuffer[1] = 11 - 4 * w.wp[pattern].tr_mode;
if(triggered & 0x4 && w.tr_mute[2]) monomeLedBuffer[2] = 11 - 4 * w.wp[pattern].tr_mode;
if(triggered & 0x8 && w.tr_mute[3]) monomeLedBuffer[3] = 11 - 4 * w.wp[pattern].tr_mode;
}
// cv indication
if(key_meta) {
if(SIZE==16) {
if(w.cv_mute[0]) {
monomeLedBuffer[4] = 11;
monomeLedBuffer[5] = 11;
monomeLedBuffer[6] = 11;
monomeLedBuffer[7] = 11;
}
if(w.cv_mute[1]) {
monomeLedBuffer[8] = 11;
monomeLedBuffer[9] = 11;
monomeLedBuffer[10] = 11;
monomeLedBuffer[11] = 11;
}
}
else {
if(w.cv_mute[0])
monomeLedBuffer[4] = 11;
if(w.cv_mute[1])
monomeLedBuffer[5] = 11;
}
}
else if(SIZE==16) {
monomeLedBuffer[cv0 / 1024 + 4] = 11;
monomeLedBuffer[cv1 / 1024 + 8] = 11;
}
// show pos loop dim
if(w.wp[pattern].loop_dir) {
for(i1=0;i1<SIZE;i1++) {
if(w.wp[pattern].loop_dir == 1 && i1 >= w.wp[pattern].loop_start && i1 <= w.wp[pattern].loop_end)
monomeLedBuffer[16+i1] = 4;
else if(w.wp[pattern].loop_dir == 2 && (i1 <= w.wp[pattern].loop_end || i1 >= w.wp[pattern].loop_start))
monomeLedBuffer[16+i1] = 4;
}
}
// show position and next cut
if(cut_pos) monomeLedBuffer[16+next_pos] = 7;
monomeLedBuffer[16+pos] = 15;
// show pattern
monomeLedBuffer[32+pattern] = 11;
if(pattern != next_pattern) monomeLedBuffer[32+next_pattern] = 7;
// show step data
if(edit_mode == mTrig) {
if(edit_prob == 0) {
for(i1=0;i1<SIZE;i1++) {
for(i2=0;i2<4;i2++) {
if((w.wp[pattern].steps[i1] & (1<<i2)) && i1 == pos && (triggered & 1<<i2) && w.tr_mute[i2]) monomeLedBuffer[(i2+4)*16+i1] = 11;
else if(w.wp[pattern].steps[i1] & (1<<i2) && (w.wp[pattern].step_choice & 1<<i1)) monomeLedBuffer[(i2+4)*16+i1] = 4;
else if(w.wp[pattern].steps[i1] & (1<<i2)) monomeLedBuffer[(i2+4)*16+i1] = 7;
else if(i1 == pos) monomeLedBuffer[(i2+4)*16+i1] = 4;
else monomeLedBuffer[(i2+4)*16+i1] = 0;
}
// probs
if(w.wp[pattern].step_probs[i1] == 255) monomeLedBuffer[48+i1] = 11;
else if(w.wp[pattern].step_probs[i1] > 0) monomeLedBuffer[48+i1] = 4;
}
}
else if(edit_prob == 1) {
for(i1=0;i1<SIZE;i1++) {
monomeLedBuffer[64+i1] = 4;
monomeLedBuffer[80+i1] = 4;
monomeLedBuffer[96+i1] = 4;
monomeLedBuffer[112+i1] = 4;
if(w.wp[pattern].step_probs[i1] == 255)
monomeLedBuffer[48+i1] = 11;
else if(w.wp[pattern].step_probs[i1] == 0) {
monomeLedBuffer[48+i1] = 0;
monomeLedBuffer[112+i1] = 7;
}
else if(w.wp[pattern].step_probs[i1]) {
monomeLedBuffer[48+i1] = 4;
monomeLedBuffer[64+16*(3-(w.wp[pattern].step_probs[i1]>>6))+i1] = 7;
}
}
}
}
// show map
else if(edit_mode == mMap) {
if(edit_prob == 0) {
// CURVES
if(w.wp[pattern].cv_mode[edit_cv_ch] == 0) {
for(i1=0;i1<SIZE;i1++) {
// probs
if(w.wp[pattern].cv_probs[edit_cv_ch][i1] == 255) monomeLedBuffer[48+i1] = 11;
else if(w.wp[pattern].cv_probs[edit_cv_ch][i1] > 0) monomeLedBuffer[48+i1] = 7;
monomeLedBuffer[112+i1] = (w.wp[pattern].cv_curves[edit_cv_ch][i1] > 1023) * 7;
monomeLedBuffer[96+i1] = (w.wp[pattern].cv_curves[edit_cv_ch][i1] > 2047) * 7;
monomeLedBuffer[80+i1] = (w.wp[pattern].cv_curves[edit_cv_ch][i1] > 3071) * 7;
monomeLedBuffer[64+i1] = 0;
monomeLedBuffer[64+16*(3-(w.wp[pattern].cv_curves[edit_cv_ch][i1]>>10))+i1] = (w.wp[pattern].cv_curves[edit_cv_ch][i1]>>7) & 0x7;
}
// play step highlight
monomeLedBuffer[64+pos] += 4;
monomeLedBuffer[80+pos] += 4;
monomeLedBuffer[96+pos] += 4;
monomeLedBuffer[112+pos] += 4;
}
// MAP
else {
if(!scale_select) {
for(i1=0;i1<SIZE;i1++) {
// probs
if(w.wp[pattern].cv_probs[edit_cv_ch][i1] == 255) monomeLedBuffer[48+i1] = 11;
else if(w.wp[pattern].cv_probs[edit_cv_ch][i1] > 0) monomeLedBuffer[48+i1] = 7;
// clear edit select line
monomeLedBuffer[64+i1] = 4;
// show current edit value, selected
if(edit_cv_value != -1) {
if((w.wp[pattern].cv_values[edit_cv_value] >> 8) >= i1)
monomeLedBuffer[80+i1] = 7;
else
monomeLedBuffer[80+i1] = 0;
if(((w.wp[pattern].cv_values[edit_cv_value] >> 4) & 0xf) >= i1)
monomeLedBuffer[96+i1] = 4;
else
monomeLedBuffer[96+i1] = 0;
}
else {
monomeLedBuffer[80+i1] = 0;
monomeLedBuffer[96+i1] = 0;
}
// show steps
if(w.wp[pattern].cv_steps[edit_cv_ch][edit_cv_step] & (1<<i1)) monomeLedBuffer[112+i1] = 7;
else monomeLedBuffer[112+i1] = 0;
}
// show play position
monomeLedBuffer[64+pos] = 7;
// show edit position
monomeLedBuffer[64+edit_cv_step] = 11;
// show playing note
monomeLedBuffer[112+cv_chosen[edit_cv_ch]] = 11;
}
else {
for(i1=0;i1<SIZE;i1++) {
// probs
if(w.wp[pattern].cv_probs[edit_cv_ch][i1] == 255) monomeLedBuffer[48+i1] = 11;
else if(w.wp[pattern].cv_probs[edit_cv_ch][i1] > 0) monomeLedBuffer[48+i1] = 7;
monomeLedBuffer[64+i1] = (i1<8) * 4;
monomeLedBuffer[80+i1] = (i1<8) * 4;
monomeLedBuffer[96+i1] = (i1<8) * 4;
monomeLedBuffer[112+i1] = 0;
}
monomeLedBuffer[112] = 7;
}
}
}
else if(edit_prob == 1) {
for(i1=0;i1<SIZE;i1++) {
monomeLedBuffer[64+i1] = 4;
monomeLedBuffer[80+i1] = 4;
monomeLedBuffer[96+i1] = 4;
monomeLedBuffer[112+i1] = 4;
if(w.wp[pattern].cv_probs[edit_cv_ch][i1] == 255)
monomeLedBuffer[48+i1] = 11;
else if(w.wp[pattern].cv_probs[edit_cv_ch][i1] == 0) {
monomeLedBuffer[48+i1] = 0;
monomeLedBuffer[112+i1] = 7;
}
else if(w.wp[pattern].cv_probs[edit_cv_ch][i1]) {
monomeLedBuffer[48+i1] = 4;
monomeLedBuffer[64+16*(3-(w.wp[pattern].cv_probs[edit_cv_ch][i1]>>6))+i1] = 7;
}
}
}
}
// series
else if(edit_mode == mSeries) {
for(i1 = 0;i1<6;i1++) {
for(i2=0;i2<SIZE;i2++) {
// start/end bars, clear
if(i1+scroll_pos == w.series_start || i1+scroll_pos == w.series_end) monomeLedBuffer[32+i1*16+i2] = 4;
else monomeLedBuffer[32+i1*16+i2] = 0;
}
// scroll position helper
monomeLedBuffer[32+i1*16+((scroll_pos+i1)/(64/SIZE))] = 4;
// sidebar selection indicators
if(i1+scroll_pos > w.series_start && i1+scroll_pos < w.series_end) {
monomeLedBuffer[32+i1*16] = 4;
monomeLedBuffer[32+i1*16+LENGTH] = 4;
}
for(i2=0;i2<SIZE;i2++) {
// show possible states
if((w.series_list[i1+scroll_pos] >> i2) & 1)
monomeLedBuffer[32+(i1*16)+i2] = 7;
}
}
// highlight playhead
if(series_pos >= scroll_pos && series_pos < scroll_pos+6) {
monomeLedBuffer[32+(series_pos-scroll_pos)*16+series_playing] = 11;
}
}
monome_set_quadrant_flag(0);
monome_set_quadrant_flag(1);
}
// application grid redraw without varibright
static void refresh_mono() {
u8 i1,i2;
// clear top, cut, pattern, prob
for(i1=0;i1<16;i1++) {
monomeLedBuffer[i1] = 0;
monomeLedBuffer[16+i1] = 0;
monomeLedBuffer[32+i1] = 0;
monomeLedBuffer[48+i1] = 0;
}
// show mode
if(edit_mode == mTrig) {
monomeLedBuffer[0] = 11;
monomeLedBuffer[1] = 11;
monomeLedBuffer[2] = 11;
monomeLedBuffer[3] = 11;
}
else if(edit_mode == mMap) {
if(SIZE==16) {
monomeLedBuffer[4+(edit_cv_ch*4)] = 11;
monomeLedBuffer[5+(edit_cv_ch*4)] = 11;
monomeLedBuffer[6+(edit_cv_ch*4)] = 11;
monomeLedBuffer[7+(edit_cv_ch*4)] = 11;
}
else
monomeLedBuffer[4+edit_cv_ch] = 11;
}
else if(edit_mode == mSeries) {
monomeLedBuffer[LENGTH-1] = 11;
}
if(key_meta) {
monomeLedBuffer[0] = 11 * w.tr_mute[0];
monomeLedBuffer[1] = 11 * w.tr_mute[1];
monomeLedBuffer[2] = 11 * w.tr_mute[2];
monomeLedBuffer[3] = 11 * w.tr_mute[3];
if(SIZE == 16) {
monomeLedBuffer[4] = 11 * w.cv_mute[0];
monomeLedBuffer[5] = 11 * w.cv_mute[0];
monomeLedBuffer[6] = 11 * w.cv_mute[0];
monomeLedBuffer[7] = 11 * w.cv_mute[0];
monomeLedBuffer[8] = 11 * w.cv_mute[1];
monomeLedBuffer[9] = 11 * w.cv_mute[1];
monomeLedBuffer[10] = 11 * w.cv_mute[1];
monomeLedBuffer[11] = 11 * w.cv_mute[1];
} else {
monomeLedBuffer[4] = 11 * w.cv_mute[0];
monomeLedBuffer[5] = 11 * w.cv_mute[1];
}
}
// alt
if(key_alt) monomeLedBuffer[LENGTH] = 11;
// show position
monomeLedBuffer[16+pos] = 15;
// show pattern
monomeLedBuffer[32+pattern] = 11;
// show step data
if(edit_mode == mTrig) {
if(edit_prob == 0) {
for(i1=0;i1<SIZE;i1++) {
for(i2=0;i2<4;i2++) {
if(w.wp[pattern].steps[i1] & (1<<i2)) monomeLedBuffer[(i2+4)*16+i1] = 11;
else monomeLedBuffer[(i2+4)*16+i1] = 0;
}
// probs
if(w.wp[pattern].step_probs[i1] > 0) monomeLedBuffer[48+i1] = 11;
}
}
else if(edit_prob == 1) {
for(i1=0;i1<SIZE;i1++) {
monomeLedBuffer[64+i1] = 0;
monomeLedBuffer[80+i1] = 0;
monomeLedBuffer[96+i1] = 0;
monomeLedBuffer[112+i1] = 0;
if(w.wp[pattern].step_probs[i1] == 255)
monomeLedBuffer[48+i1] = 11;
else if(w.wp[pattern].step_probs[i1] == 0) {
monomeLedBuffer[48+i1] = 0;
monomeLedBuffer[112+i1] = 11;
}
else if(w.wp[pattern].step_probs[i1]) {
monomeLedBuffer[48+i1] = 11;
monomeLedBuffer[64+16*(3-(w.wp[pattern].step_probs[i1]>>6))+i1] = 11;
}
}
}
}
// show map
else if(edit_mode == mMap) {
if(edit_prob == 0) {
// CURVES
if(w.wp[pattern].cv_mode[edit_cv_ch] == 0) {
for(i1=0;i1<SIZE;i1++) {
// probs
if(w.wp[pattern].cv_probs[edit_cv_ch][i1] > 0) monomeLedBuffer[48+i1] = 11;
monomeLedBuffer[112+i1] = (w.wp[pattern].cv_curves[edit_cv_ch][i1] > 511) * 11;
monomeLedBuffer[96+i1] = (w.wp[pattern].cv_curves[edit_cv_ch][i1] > 1535) * 11;
monomeLedBuffer[80+i1] = (w.wp[pattern].cv_curves[edit_cv_ch][i1] > 2559) * 11;
monomeLedBuffer[64+i1] = (w.wp[pattern].cv_curves[edit_cv_ch][i1] > 3583) * 11;
}
}
// MAP
else {
if(!scale_select) {
for(i1=0;i1<SIZE;i1++) {
// probs
if(w.wp[pattern].cv_probs[edit_cv_ch][i1] > 0) monomeLedBuffer[48+i1] = 11;
// clear edit row
monomeLedBuffer[64+i1] = 0;
// show current edit value, selected
if(edit_cv_value != -1) {
if((w.wp[pattern].cv_values[edit_cv_value] >> 8) >= i1)
monomeLedBuffer[80+i1] = 11;
else
monomeLedBuffer[80+i1] = 0;
if(((w.wp[pattern].cv_values[edit_cv_value] >> 4) & 0xf) >= i1)
monomeLedBuffer[96+i1] = 11;
else
monomeLedBuffer[96+i1] = 0;
}
else {
monomeLedBuffer[80+i1] = 0;
monomeLedBuffer[96+i1] = 0;
}
// show steps
if(w.wp[pattern].cv_steps[edit_cv_ch][edit_cv_step] & (1<<i1)) monomeLedBuffer[112+i1] = 11;
else monomeLedBuffer[112+i1] = 0;
}
// show edit position
monomeLedBuffer[64+edit_cv_step] = 11;
// show playing note
monomeLedBuffer[112+cv_chosen[edit_cv_ch]] = 11;
}
else {
for(i1=0;i1<SIZE;i1++) {
// probs
if(w.wp[pattern].cv_probs[edit_cv_ch][i1] > 0) monomeLedBuffer[48+i1] = 11;
monomeLedBuffer[64+i1] = 0;
monomeLedBuffer[80+i1] = 0;
monomeLedBuffer[96+i1] = 0;
monomeLedBuffer[112+i1] = 0;
}
monomeLedBuffer[112] = 11;
}
}
}
else if(edit_prob == 1) {
for(i1=0;i1<SIZE;i1++) {
monomeLedBuffer[64+i1] = 0;
monomeLedBuffer[80+i1] = 0;
monomeLedBuffer[96+i1] = 0;
monomeLedBuffer[112+i1] = 0;
if(w.wp[pattern].cv_probs[edit_cv_ch][i1] == 255)
monomeLedBuffer[48+i1] = 11;
else if(w.wp[pattern].cv_probs[edit_cv_ch][i1] == 0) {
monomeLedBuffer[48+i1] = 0;
monomeLedBuffer[112+i1] = 11;
}
else if(w.wp[pattern].cv_probs[edit_cv_ch][i1]) {
monomeLedBuffer[48+i1] = 11;
monomeLedBuffer[64+16*(3-(w.wp[pattern].cv_probs[edit_cv_ch][i1]>>6))+i1] = 11;
}
}
}
}
// series
else if(edit_mode == mSeries) {
for(i1 = 0;i1<6;i1++) {
for(i2=0;i2<SIZE;i2++) {
// start/end bars, clear
if((key_meta || key_alt) && (i1+scroll_pos == w.series_start || i1+scroll_pos == w.series_end)) monomeLedBuffer[32+i1*16+i2] = 11;
else monomeLedBuffer[32+i1*16+i2] = 0;
}
// scroll position helper
// monomeLedBuffer[32+i1*16+((scroll_pos+i1)/(64/SIZE))] = 4;
// sidebar selection indicators
if((key_meta || key_alt) && i1+scroll_pos > w.series_start && i1+scroll_pos < w.series_end) {
monomeLedBuffer[32+i1*16] = 11;
monomeLedBuffer[32+i1*16+LENGTH] = 11;
}
for(i2=0;i2<SIZE;i2++) {
// show possible states
if((w.series_list[i1+scroll_pos] >> i2) & 1)
monomeLedBuffer[32+(i1*16)+i2] = 11;
}
}
// highlight playhead
if(series_pos >= scroll_pos && series_pos < scroll_pos+6 && (pos & 1)) {
monomeLedBuffer[32+(series_pos-scroll_pos)*16+series_playing] = 0;
}
}
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);
}
/*
{"WW.MUTE1",WW_MUTE1},
{"WW.MUTE2",WW_MUTE2},
{"WW.MUTE3",WW_MUTE3},
{"WW.MUTE4",WW_MUTE4},
{"WW.MUTEA",WW_MUTEA},
{"WW.MUTEB",WW_MUTEB},
*/
static void ww_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 WW_PRESET:
if(d<0 || d>7)
break;
preset_select = d;
flash_read();
break;
case WW_POS:
if(d<0 || d>15)
break;
next_pos = d;
cut_pos++;
monomeFrameDirty++;
break;
case WW_SYNC:
if(d<0 || d>15)
break;
next_pos = d;
cut_pos++;
timer_set(&clockTimer,clock_time);
clock_phase = 1;
(*clock_pulse)(clock_phase);
break;
case WW_START:
if(d<0 || d>15)
break;
w.wp[pattern].loop_start = d;
if(w.wp[pattern].loop_start > w.wp[pattern].loop_end) w.wp[pattern].loop_dir = 2;
else if(w.wp[pattern].loop_start == 0 && w.wp[pattern].loop_end == LENGTH) w.wp[pattern].loop_dir = 0;
else w.wp[pattern].loop_dir = 1;
w.wp[pattern].loop_len = w.wp[pattern].loop_end - w.wp[pattern].loop_start;
if(w.wp[pattern].loop_dir == 2)
w.wp[pattern].loop_len = (LENGTH - w.wp[pattern].loop_start) + w.wp[pattern].loop_end + 1;
monomeFrameDirty++;
break;
case WW_END:
if(d<0 || d>15)
break;
w.wp[pattern].loop_end = d;
if(w.wp[pattern].loop_start > w.wp[pattern].loop_end) w.wp[pattern].loop_dir = 2;
else if(w.wp[pattern].loop_start == 0 && w.wp[pattern].loop_end == LENGTH) w.wp[pattern].loop_dir = 0;
else w.wp[pattern].loop_dir = 1;
w.wp[pattern].loop_len = w.wp[pattern].loop_end - w.wp[pattern].loop_start;
if(w.wp[pattern].loop_dir == 2)
w.wp[pattern].loop_len = (LENGTH - w.wp[pattern].loop_start) + w.wp[pattern].loop_end + 1;
monomeFrameDirty++;
break;
case WW_PMODE:
if(d<mForward || d>mPingRep)
break;
w.wp[pattern].step_mode = d;
break;
case WW_PATTERN:
if(d<0 || d>15)
break;
pattern = d;
next_pattern = d;
monomeFrameDirty++;
break;
case WW_QPATTERN:
if(d<0 || d>15)
break;
next_pattern = d;
monomeFrameDirty++;
break;
case WW_MUTE1:
if(d) w.tr_mute[0] = 1;
else w.tr_mute[0] = 0;
break;
case WW_MUTE2:
if(d) w.tr_mute[1] = 1;
else w.tr_mute[1] = 0;
break;
case WW_MUTE3:
if(d) w.tr_mute[2] = 1;
else w.tr_mute[2] = 0;
break;
case WW_MUTE4:
if(d) w.tr_mute[3] = 1;
else w.tr_mute[3] = 0;
break;
case WW_MUTEA:
if(d) w.cv_mute[0] = 1;
else w.cv_mute[0] = 0;
break;
case WW_MUTEB:
if(d) w.cv_mute[1] = 1;
else w.cv_mute[1] = 0;
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[ kEventTimer ] = &handler_Timer;
app_event_handlers[ kEventPollADC ] = &handler_PollADC;
app_event_handlers[ kEventKeyTimer ] = &handler_KeyTimer;
app_event_handlers[ kEventSaveFlash ] = &handler_SaveFlash;
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.w[preset_select], &w, sizeof(w), true);
flashc_memcpy((void *)&flashy.glyph[preset_select], &glyph, sizeof(glyph), true);
flashc_memset8((void*)&(flashy.preset_select), preset_select, 1, true);
flashc_memset32((void*)&(flashy.edit_mode), edit_mode, 4, true);
}
void flash_read(void) {
u8 i1, i2;
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].ping_dir = flashy.w[preset_select].wp[i1].ping_dir;
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];
w.wp[i1].tr_mode = flashy.w[preset_select].wp[i1].tr_mode;
}
w.series_start = flashy.w[preset_select].series_start;
w.series_end = flashy.w[preset_select].series_end;
w.tr_mute[0] = flashy.w[preset_select].tr_mute[0];
w.tr_mute[1] = flashy.w[preset_select].tr_mute[1];
w.tr_mute[2] = flashy.w[preset_select].tr_mute[2];
w.tr_mute[3] = flashy.w[preset_select].tr_mute[3];
w.cv_mute[0] = flashy.w[preset_select].cv_mute[0];
w.cv_mute[1] = flashy.w[preset_select].cv_mute[1];
for(i1=0;i1<64;i1++)
w.series_list[i1] = flashy.w[preset_select].series_list[i1];
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// main
int main(void)
{
u8 i1,i2;
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_slave(0x10);
print_dbg("\r\n\n// white whale //////////////////////////////// ");
print_dbg_ulong(sizeof(flashy));
print_dbg(" ");
print_dbg_ulong(sizeof(w));
print_dbg(" ");
print_dbg_ulong(sizeof(glyph));
if(flash_is_fresh()) {
print_dbg("\r\nfirst run.");
flash_unfresh();
flashc_memset8((void*)&(flashy.edit_mode), mTrig, 4, true);
flashc_memset32((void*)&(flashy.preset_select), 0, 4, true);
// clear out some reasonable defaults
for(i1=0;i1<16;i1++) {
for(i2=0;i2<16;i2++) {
w.wp[i1].steps[i2] = 0;
w.wp[i1].step_probs[i2] = 255;
w.wp[i1].cv_probs[0][i2] = 255;
w.wp[i1].cv_probs[1][i2] = 255;
w.wp[i1].cv_curves[0][i2] = 0;
w.wp[i1].cv_curves[1][i2] = 0;
w.wp[i1].cv_values[i2] = SCALES[2][i2];
w.wp[i1].cv_steps[0][i2] = 1<<i2;
w.wp[i1].cv_steps[1][i2] = 1<<i2;
}
w.wp[i1].step_choice = 0;
w.wp[i1].loop_end = 15;
w.wp[i1].loop_len = 15;
w.wp[i1].loop_start = 0;
w.wp[i1].loop_dir = 0;
w.wp[i1].step_mode = mForward;
w.wp[i1].ping_dir = mPingFwd;
w.wp[i1].cv_mode[0] = 0;
w.wp[i1].cv_mode[1] = 0;
w.wp[i1].tr_mode = 0;
}
w.series_start = 0;
w.series_end = 3;
w.tr_mute[0] = 1;
w.tr_mute[1] = 1;
w.tr_mute[2] = 1;
w.tr_mute[3] = 1;
w.cv_mute[0] = 1;
w.cv_mute[1] = 1;
for(i1=0;i1<64;i1++)
w.series_list[i1] = 1;
// save all presets, clear glyphs
for(i1=0;i1<8;i1++) {
flashc_memcpy((void *)&flashy.w[i1], &w, sizeof(w), 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;
edit_mode = flashy.edit_mode;
flash_read();
for(i1=0;i1<8;i1++)
glyph[i1] = flashy.glyph[preset_select][i1];
}
LENGTH = 15;
SIZE = 16;
re = &refresh;
process_ii = &ww_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
// setup daisy chain for two dacs
// spi_selectChip(SPI,DAC_SPI);
// spi_write(SPI,0x80);
// spi_write(SPI,0xff);
// spi_write(SPI,0xff);
// spi_unselectChip(SPI,DAC_SPI);
while (true) {
check_events();
}
}