Skip to content
Permalink
master
Go to file
 
 
Cannot retrieve contributors at this time
1764 lines (1562 sloc) 35.8 KB
#include <string.h>
#include <stdio.h> // printf
#include <stdlib.h> // rand, strtol
#include <ctype.h> // isdigit
#include <stdint.h> // types
#include "teletype.h"
#include "table.h"
#include "util.h"
#include "ii.h"
#include "euclidean/euclidean.h"
#ifdef SIM
#define DBG printf("%s",dbg);
#else
#include "print_funcs.h"
#define DBG print_dbg(dbg);
#endif
static const char * errordesc[] = {
"OK",
WELCOME,
"UNKNOWN WORD",
"COMMAND TOO LONG",
"NOT ENOUGH PARAMS",
"TOO MANY PARAMS",
"MOD NOT ALLOWED HERE",
"EXTRA SEPARATOR",
"NEED SEPARATOR",
"BAD SEPARATOR",
"MOVE LEFT"
};
const char * tele_error(error_t e) {
return errordesc[e];
}
// static char dbg[32];
static char pcmd[32];
int16_t output, output_new;
char error_detail[16];
uint8_t mutes[8];
tele_command_t temp;
tele_pattern_t tele_patterns[4];
static uint8_t pn;
static char condition;
static tele_command_t tele_stack[TELE_STACK_SIZE];
static uint8_t tele_stack_top;
static uint8_t left;
volatile update_metro_t update_metro;
volatile update_tr_t update_tr;
volatile update_cv_t update_cv;
volatile update_cv_slew_t update_cv_slew;
volatile update_delay_t update_delay;
volatile update_s_t update_s;
volatile update_cv_off_t update_cv_off;
volatile update_ii_t update_ii;
volatile update_scene_t update_scene;
volatile update_pi_t update_pi;
volatile update_kill_t update_kill;
volatile update_mute_t update_mute;
volatile update_input_t update_input;
volatile run_script_t run_script;
volatile uint8_t input_states[8];
const char * to_v(int16_t);
/////////////////////////////////////////////////////////////////
// STACK ////////////////////////////////////////////////////////
static int16_t pop(void);
static void push(int16_t);
static int16_t top;
static int16_t stack[STACK_SIZE];
int16_t pop() {
top--;
// sprintf(dbg,"\r\npop %d", stack[top]);
return stack[top];
}
void push(int16_t data) {
stack[top] = data;
// sprintf(dbg,"\r\npush %d", stack[top]);
top++;
}
/////////////////////////////////////////////////////////////////
// VARS ARRAYS KEYS /////////////////////////////////////////////
#define KEYS 47
static tele_key_t tele_keys[KEYS] = {
{"WW.PRESET",WW_PRESET},
{"WW.POS",WW_POS},
{"WW.SYNC",WW_SYNC},
{"WW.START",WW_START},
{"WW.END",WW_END},
{"WW.PMODE",WW_PMODE},
{"WW.PATTERN",WW_PATTERN},
{"WW.QPATTERN",WW_QPATTERN},
{"WW.MUTE1",WW_MUTE1},
{"WW.MUTE2",WW_MUTE2},
{"WW.MUTE3",WW_MUTE3},
{"WW.MUTE4",WW_MUTE4},
{"WW.MUTEA",WW_MUTEA},
{"WW.MUTEB",WW_MUTEB},
{"MP.PRESET",MP_PRESET},
{"MP.RESET",MP_RESET},
{"MP.SYNC",MP_SYNC},
{"MP.MUTE",MP_MUTE},
{"MP.UNMUTE",MP_UNMUTE},
{"MP.FREEZE",MP_FREEZE},
{"MP.UNFREEZE",MP_UNFREEZE},
{"MP.STOP",MP_STOP},
{"ES.PRESET",ES_PRESET},
{"ES.MODE",ES_MODE},
{"ES.CLOCK",ES_CLOCK},
{"ES.RESET",ES_RESET},
{"ES.PATTERN",ES_PATTERN},
{"ES.TRANS",ES_TRANS},
{"ES.STOP",ES_STOP},
{"ES.TRIPLE",ES_TRIPLE},
{"ES.MAGIC",ES_MAGIC},
{"OR.TRK",ORCA_TRACK},
{"OR.CLK",ORCA_CLOCK},
{"OR.DIV",ORCA_DIVISOR},
{"OR.PHASE",ORCA_PHASE},
{"OR.RST",ORCA_RESET},
{"OR.WGT",ORCA_WEIGHT},
{"OR.MUTE",ORCA_MUTE},
{"OR.SCALE",ORCA_SCALE},
{"OR.BANK",ORCA_BANK},
{"OR.PRESET",ORCA_PRESET},
{"OR.RELOAD",ORCA_RELOAD},
{"OR.ROTS",ORCA_ROTATES},
{"OR.ROTW",ORCA_ROTATEW},
{"OR.GRST",ORCA_GRESET},
{"OR.CVA",ORCA_CVA},
{"OR.CVB",ORCA_CVB}
};
// {NAME,VAL}
// ENUM IN HEADER
static void v_P_N(uint8_t);
static void v_M(uint8_t);
static void v_M_ACT(uint8_t);
static void v_P_L(uint8_t);
static void v_P_I(uint8_t);
static void v_P_HERE(uint8_t);
static void v_P_NEXT(uint8_t);
static void v_P_PREV(uint8_t);
static void v_P_WRAP(uint8_t);
static void v_P_START(uint8_t);
static void v_P_END(uint8_t);
static void v_O(uint8_t);
static void v_DRUNK(uint8_t);
static void v_Q(uint8_t);
static void v_Q_N(uint8_t);
static void v_Q_AVG(uint8_t);
static void v_SCENE(uint8_t);
static void v_FLIP(uint8_t);
static int16_t tele_q[16];
#define VARS 39
static tele_var_t tele_vars[VARS] = {
{"I",NULL,0}, // gets overwritten by ITER
{"TIME",NULL,0},
{"TIME.ACT",NULL,1},
{"IN",NULL,0},
{"PARAM",NULL,0},
{"PRESET",NULL,0},
{"M",v_M,1000},
{"M.ACT",v_M_ACT,1},
{"X",NULL,0},
{"Y",NULL,0},
{"Z",NULL,0},
{"T",NULL,0},
{"A",NULL,1},
{"B",NULL,2},
{"C",NULL,3},
{"D",NULL,4},
{"O",v_O,0},
{"DRUNK",v_DRUNK,0},
{"Q",v_Q,0},
{"Q.N",v_Q_N,1},
{"Q.AVG",v_Q_AVG,0},
{"SCENE",v_SCENE,0},
{"P.N",v_P_N,0},
{"P.L",v_P_L,0},
{"P.I",v_P_I,0},
{"P.HERE",v_P_HERE,0},
{"P.NEXT",v_P_NEXT,0},
{"P.PREV",v_P_PREV,0},
{"P.WRAP",v_P_WRAP,0},
{"P.START",v_P_START,0},
{"P.END",v_P_END,0},
{"FLIP",v_FLIP,0},
{"O.MIN",NULL,0},
{"O.MAX",NULL,63},
{"O.WRAP",NULL,1},
{"O.DIR",NULL,1},
{"DRUNK.MIN",NULL,0},
{"DRUNK.MAX",NULL,255},
{"DRUNK.WRAP",NULL,0}
};
static void v_M(uint8_t n) {
if(left || top == 0)
push(tele_vars[V_M].v);
else {
tele_vars[V_M].v = pop();
if(tele_vars[V_M].v < 10) tele_vars[V_M].v = 10;
(*update_metro)(tele_vars[V_M].v, tele_vars[V_M_ACT].v, 0);
}
}
static void v_M_ACT(uint8_t n) {
if(left || top == 0)
push(tele_vars[V_M_ACT].v);
else {
tele_vars[V_M_ACT].v = pop();
if(tele_vars[V_M_ACT].v != 0)
tele_vars[V_M_ACT].v = 1;
(*update_metro)(tele_vars[V_M].v, tele_vars[V_M_ACT].v, 0);
}
}
static void v_P_N(uint8_t n) {
int16_t a;
if(left || top == 0) {
push(pn);
}
else {
a = pop();
if(a < 0) pn = 0;
else if(a > 3) pn = 3;
else pn = a;
}
}
static void v_P_L(uint8_t n) {
int16_t a;
if(left || top == 0) {
push(tele_patterns[pn].l);
}
else {
a = pop();
if(a < 0) tele_patterns[pn].l = 0;
else if(a > 63) tele_patterns[pn].l = 63;
else tele_patterns[pn].l = a;
}
}
static void v_P_I(uint8_t n) {
int16_t a;
if(left || top == 0) {
push(tele_patterns[pn].i);
}
else {
a = pop();
if(a < 0) tele_patterns[pn].i = 0;
else if(a > tele_patterns[pn].l) tele_patterns[pn].i = tele_patterns[pn].l;
else tele_patterns[pn].i = a;
(*update_pi)();
}
}
static void v_P_HERE(uint8_t n) {
int16_t a;
if(left || top == 0) {
push(tele_patterns[pn].v[tele_patterns[pn].i]);
}
else {
a = pop();
tele_patterns[pn].v[tele_patterns[pn].i] = a;
}
}
static void v_P_NEXT(uint8_t n) {
int16_t a;
if((tele_patterns[pn].i == (tele_patterns[pn].l - 1)) || (tele_patterns[pn].i == tele_patterns[pn].end)) {
if(tele_patterns[pn].wrap)
tele_patterns[pn].i = tele_patterns[pn].start;
}
else
tele_patterns[pn].i++;
if(tele_patterns[pn].i > tele_patterns[pn].l)
tele_patterns[pn].i = 0;
if(left || top == 0) {
push(tele_patterns[pn].v[tele_patterns[pn].i]);
}
else {
a = pop();
tele_patterns[pn].v[tele_patterns[pn].i] = a;
}
(*update_pi)();
}
static void v_P_PREV(uint8_t n) {
int16_t a;
if((tele_patterns[pn].i == 0) || (tele_patterns[pn].i == tele_patterns[pn].start)) {
if(tele_patterns[pn].wrap) {
if(tele_patterns[pn].end < tele_patterns[pn].l)
tele_patterns[pn].i = tele_patterns[pn].end;
else
tele_patterns[pn].i = tele_patterns[pn].l - 1;
}
}
else
tele_patterns[pn].i--;
if(left || top == 0) {
push(tele_patterns[pn].v[tele_patterns[pn].i]);
}
else {
a = pop();
tele_patterns[pn].v[tele_patterns[pn].i] = a;
}
(*update_pi)();
}
static void v_P_WRAP(uint8_t n) {
int16_t a;
if(left || top == 0) {
push(tele_patterns[pn].wrap);
}
else {
a = pop();
if(a < 0) tele_patterns[pn].wrap = 0;
else if(a > 1) tele_patterns[pn].wrap = 1;
else tele_patterns[pn].wrap = a;
}
}
static void v_P_START(uint8_t n) {
int16_t a;
if(left || top == 0) {
push(tele_patterns[pn].start);
}
else {
a = pop();
if(a < 0) tele_patterns[pn].start = 0;
else if(a > 63) tele_patterns[pn].start = 1;
else tele_patterns[pn].start = a;
}
}
static void v_P_END(uint8_t n) {
int16_t a;
if(left || top == 0) {
push(tele_patterns[pn].end);
}
else {
a = pop();
if(a < 0) tele_patterns[pn].end = 0;
else if(a > 63) tele_patterns[pn].end = 1;
else tele_patterns[pn].end = a;
}
}
static void v_O(uint8_t n) {
if(left || top == 0) {
tele_vars[V_O].v += tele_vars[V_O_DIR].v;
if(tele_vars[V_O].v > tele_vars[V_O_MAX].v) {
if(tele_vars[V_O_WRAP].v)
tele_vars[V_O].v = tele_vars[V_O_MIN].v;
else
tele_vars[V_O].v = tele_vars[V_O_MAX].v;
}
else if(tele_vars[V_O].v < tele_vars[V_O_MIN].v) {
if(tele_vars[V_O_WRAP].v)
tele_vars[V_O].v = tele_vars[V_O_MAX].v;
else
tele_vars[V_O].v = tele_vars[V_O_MIN].v;
}
push(tele_vars[V_O].v);
}
else {
tele_vars[V_O].v = pop();
}
}
static void v_DRUNK(uint8_t n) {
if(left || top == 0) {
tele_vars[V_DRUNK].v += (rand() % 3) - 1;
if(tele_vars[V_DRUNK].v < tele_vars[V_DRUNK_MIN].v) {
if(tele_vars[V_DRUNK_WRAP].v)
tele_vars[V_DRUNK].v = tele_vars[V_DRUNK_MAX].v;
else
tele_vars[V_DRUNK].v = tele_vars[V_DRUNK_MIN].v;
}
else if(tele_vars[V_DRUNK].v > tele_vars[V_DRUNK_MAX].v) {
if(tele_vars[V_DRUNK_WRAP].v)
tele_vars[V_DRUNK].v = tele_vars[V_DRUNK_MIN].v;
else
tele_vars[V_DRUNK].v = tele_vars[V_DRUNK_MAX].v;
}
push(tele_vars[V_DRUNK].v);
}
else {
tele_vars[V_DRUNK].v = pop();
}
}
static void v_Q(uint8_t n) {
if(left || top == 0) {
push(tele_q[tele_vars[V_Q_N].v-1]);
}
else {
for(int16_t i = 15;i>0;i--)
tele_q[i] = tele_q[i-1];
tele_q[0] = pop();
}
}
static void v_Q_N(uint8_t n) {
if(left || top == 0) {
push(tele_vars[V_Q_N].v);
}
else {
int16_t a = pop();
if(a<1) a = 1;
else if(a>16) a = 16;
tele_vars[V_Q_N].v = a;
}
}
static void v_Q_AVG(uint8_t n) {
if(left || top == 0) {
int32_t avg = 0;
for(int16_t i = 0;i<tele_vars[V_Q_N].v;i++)
avg += tele_q[i];
avg /= tele_vars[V_Q_N].v;
push(avg);
}
else {
int16_t a = pop();
for(int16_t i=0;i<16;i++)
tele_q[i] = a;
}
}
static void v_SCENE(uint8_t n) {
if(left || top == 0) {
push(tele_vars[V_SCENE].v);
}
else {
tele_vars[V_SCENE].v = pop();
(*update_scene)(tele_vars[V_SCENE].v);
}
}
static void v_FLIP(uint8_t n) {
if(left || top == 0) {
push(tele_vars[V_O].v);
tele_vars[V_O].v = (tele_vars[V_O].v == 0);
}
else {
tele_vars[V_O].v = (pop() != 0);
}
}
static void a_TR(uint8_t);
static void a_CV(uint8_t);
static void a_CV_SLEW(uint8_t);
static void a_CV_OFF(uint8_t);
static void a_TR_TIME(uint8_t);
static void a_TR_POL(uint8_t);
#define MAKEARRAY(name, func) {#name, {0,0,0,0}, func}
#define ARRAYS 6
static tele_array_t tele_arrays[ARRAYS] = {
MAKEARRAY(TR,a_TR),
MAKEARRAY(CV,a_CV),
MAKEARRAY(CV.SLEW,a_CV_SLEW),
MAKEARRAY(CV.OFF,a_CV_OFF),
{"TR.TIME", {100,100,100,100}, a_TR_TIME},
{"TR.POL", {1,1,1,1}, a_TR_POL}
};
static void a_TR(uint8_t i) {
int16_t a = pop();
a = (a != 0);
tele_arrays[0].v[i] = a;
(*update_tr)(i, a);
}
static void a_CV(uint8_t i) {
int16_t a = pop();
if(a<0) a = 0;
else if(a > 16383) a = 16383;
tele_arrays[1].v[i] = a;
(*update_cv)(i, a, 1);
}
static void a_CV_SLEW(uint8_t i) {
int16_t a = pop();
if(a<1) a = 1; // min slew = 1
else if(a > 32767) a = 32767;
tele_arrays[2].v[i] = a;
(*update_cv_slew)(i, a);
}
static void a_CV_OFF(uint8_t i) {
int16_t a = pop();
tele_arrays[3].v[i] = a;
(*update_cv_off)(i, a);
(*update_cv)(i, tele_arrays[1].v[i], 1);
}
static void a_TR_TIME(uint8_t i) {
int16_t a = pop();
if(a<0) a = 0; // 0 = no pulse
tele_arrays[4].v[i] = a;
}
static void a_TR_POL(uint8_t i) {
int16_t a = pop();
if(a>1) a = 1;
else if(a<0) a = 0;
tele_arrays[5].v[i] = a;
}
/////////////////////////////////////////////////////////////////
// DELAY ////////////////////////////////////////////////////////
static tele_command_t delay_c[TELE_D_SIZE];
static int16_t delay_t[TELE_D_SIZE];
static uint8_t delay_count;
static int16_t tr_pulse[4];
static void process_delays(uint8_t);
void clear_delays(void);
static void process_delays(uint8_t v) {
for(int16_t i=0;i<TELE_D_SIZE;i++) {
if(delay_t[i]) {
delay_t[i] -= v;
if(delay_t[i] <= 0) {
// sprintf(dbg,"\r\ndelay %d", i);
// DBG
process(&delay_c[i]);
delay_t[i] = 0;
delay_count--;
if(delay_count == 0)
(*update_delay)(0);
}
}
}
for(int16_t i=0;i<4;i++) {
if(tr_pulse[i]) {
tr_pulse[i] -= v;
if(tr_pulse[i] <= 0) {
tr_pulse[i] = 0;
// if(tele_arrays[0].v[i]) tele_arrays[0].v[i] = 0;
tele_arrays[0].v[i] = (tele_arrays[5].v[i] == 0);
(*update_tr)(i,tele_arrays[0].v[i]);
}
}
}
}
void clear_delays(void) {
for(int16_t i=0;i<4;i++)
tr_pulse[i] = 0;
for(int16_t i=0;i<TELE_D_SIZE;i++) {
delay_t[i] = 0;
}
delay_count = 0;
tele_stack_top = 0;
(*update_delay)(0);
(*update_s)(0);
}
/////////////////////////////////////////////////////////////////
// MOD //////////////////////////////////////////////////////////
static void mod_PROB(tele_command_t *);
static void mod_DEL(tele_command_t *);
static void mod_S(tele_command_t *);
static void mod_IF(tele_command_t *);
static void mod_ELIF(tele_command_t *);
static void mod_ELSE(tele_command_t *);
static void mod_L (tele_command_t *);
#define MAKEMOD(name, params, doc) {#name, mod_ ## name, params, doc}
#define MODS 7
static const tele_mod_t tele_mods[MODS] = {
MAKEMOD(PROB, 1, "PROBABILITY TO CONTINUE EXECUTING LINE"),
MAKEMOD(DEL, 1, "DELAY THIS COMMAND"),
MAKEMOD(S, 0, "ADD COMMAND TO STACK"),
MAKEMOD(IF, 1, "IF CONDITION FOR COMMAND"),
MAKEMOD(ELIF, 1, "ELSE IF"),
MAKEMOD(ELSE, 0, "ELSE"),
MAKEMOD(L, 2, "LOOPED COMMAND WITH ITERATION")
};
void mod_PROB(tele_command_t *c) {
int16_t a = pop();
tele_command_t cc;
if(rand() % 101 < a) {
cc.l = c->l - c->separator - 1;
cc.separator = -1;
memcpy(cc.data, &c->data[c->separator+1], cc.l * sizeof(tele_data_t));
// sprintf(dbg,"\r\nsub-length: %d", cc.l);
process(&cc);
}
}
void mod_DEL(tele_command_t *c) {
int16_t i = 0;
int16_t a = pop();
if(a < 1) a = 1;
while(delay_t[i] != 0 && i != TELE_D_SIZE)
i++;
if(i < TELE_D_SIZE) {
delay_count++;
if(delay_count == 1)
(*update_delay)(1);
delay_t[i] = a;
delay_c[i].l = c->l - c->separator - 1;
delay_c[i].separator = -1;
memcpy(delay_c[i].data, &c->data[c->separator+1], delay_c[i].l * sizeof(tele_data_t));
}
}
void mod_S(tele_command_t *c) {
if(tele_stack_top < TELE_STACK_SIZE) {
tele_stack[tele_stack_top].l = c->l - c->separator - 1;
memcpy(tele_stack[tele_stack_top].data, &c->data[c->separator+1], tele_stack[tele_stack_top].l * sizeof(tele_data_t));
tele_stack[tele_stack_top].separator = -1;
tele_stack_top++;
if(tele_stack_top == 1)
(*update_s)(1);
}
}
void mod_IF(tele_command_t *c) {
condition = FALSE;
tele_command_t cc;
if(pop()) {
condition = TRUE;
cc.l = c->l - c->separator - 1;
cc.separator = -1;
memcpy(cc.data, &c->data[c->separator+1], cc.l * sizeof(tele_data_t));
// sprintf(dbg,"\r\nsub-length: %d", cc.l);
process(&cc);
}
}
void mod_ELIF(tele_command_t *c) {
tele_command_t cc;
if(!condition) {
if(pop()) {
condition = TRUE;
cc.l = c->l - c->separator - 1;
cc.separator = -1;
memcpy(cc.data, &c->data[c->separator+1], cc.l * sizeof(tele_data_t));
// sprintf(dbg,"\r\nsub-length: %d", cc.l);
process(&cc);
}
}
}
void mod_ELSE(tele_command_t *c) {
tele_command_t cc;
if(!condition) {
condition = TRUE;
cc.l = c->l - c->separator - 1;
cc.separator = -1;
memcpy(cc.data, &c->data[c->separator+1], cc.l * sizeof(tele_data_t));
// sprintf(dbg,"\r\nsub-length: %d", cc.l);
process(&cc);
}
}
void mod_L(tele_command_t *c) {
int16_t a, b, d, i;
tele_command_t cc;
a = pop();
b = pop();
if(a < b) {
d = b - a + 1;
for(i = 0; i<d; i++) {
tele_vars[V_I].v = a + i;
cc.l = c->l - c->separator - 1;
cc.separator = -1;
memcpy(cc.data, &c->data[c->separator+1], cc.l * sizeof(tele_data_t));
// sprintf(dbg,"\r\nsub-length: %d", cc.l);
process(&cc);
}
}
else {
d = a - b + 1;
for(i = 0; i<d; i++) {
tele_vars[V_I].v = a - i;
cc.l = c->l - c->separator - 1;
cc.separator = -1;
memcpy(cc.data, &c->data[c->separator+1], cc.l * sizeof(tele_data_t));
// sprintf(dbg,"\r\nsub-length: %d", cc.l);
process(&cc);
}
}
}
/////////////////////////////////////////////////////////////////
// OPS //////////////////////////////////////////////////////////
static void op_ADD(void);
static void op_SUB(void);
static void op_MUL(void);
static void op_DIV(void);
static void op_MOD(void);
static void op_RAND(void);
static void op_RRAND(void);
static void op_TOSS(void);
static void op_MIN(void);
static void op_MAX(void);
static void op_LIM(void);
static void op_WRAP(void);
static void op_QT(void);
static void op_AVG(void);
static void op_EQ(void);
static void op_NE(void);
static void op_LT(void);
static void op_GT(void);
static void op_NZ(void);
static void op_EZ(void);
static void op_TR_TOG(void);
static void op_N(void);
static void op_S_ALL(void);
static void op_S_POP(void);
static void op_S_CLR(void);
static void op_DEL_CLR(void);
static void op_M_RESET(void);
static void op_V(void);
static void op_VV(void);
static void op_P(void);
static void op_P_INS(void);
static void op_P_RM(void);
static void op_P_PUSH(void);
static void op_P_POP(void);
static void op_PN(void);
static void op_TR_PULSE(void);
static void op_II(void);
static void op_RSH(void);
static void op_LSH(void);
static void op_S_L(void);
static void op_CV_SET(void);
static void op_EXP(void);
static void op_ABS(void);
static void op_AND(void);
static void op_OR(void);
static void op_XOR(void);
static void op_JI(void);
static void op_SCRIPT(void);
static void op_KILL(void);
static void op_MUTE(void);
static void op_UNMUTE(void);
static void op_SCALE(void);
static void op_STATE(void);
static void op_ER(void);
#define MAKEOP(name, params, returns, doc) {#name, op_ ## name, params, returns, doc}
#define OPS 54
// DO NOT INSERT in the middle. there's a hack in validate() for P and PN
static const tele_op_t tele_ops[OPS] = {
MAKEOP(ADD, 2, 1,"[A B] ADD A TO B"),
MAKEOP(SUB, 2, 1,"[A B] SUBTRACT B FROM A"),
MAKEOP(MUL, 2, 1,"[A B] MULTIPLY TWO VALUES"),
MAKEOP(DIV, 2, 1,"[A B] DIVIDE FIRST BY SECOND"),
MAKEOP(MOD, 2, 1,"[A B] MOD FIRST BY SECOND"),
MAKEOP(RAND, 1, 1,"[A] RETURN RANDOM NUMBER UP TO A"),
MAKEOP(RRAND, 2, 1,"[A B] RETURN RANDOM NUMBER BETWEEN A AND B"),
MAKEOP(TOSS, 0, 1,"RETURN RANDOM STATE"),
MAKEOP(MIN, 2, 1,"RETURN LESSER OF TWO VALUES"),
MAKEOP(MAX, 2, 1,"RETURN GREATER OF TWO VALUES"),
MAKEOP(LIM, 3, 1,"[A B C] LIMIT C TO RANGE A TO B"),
MAKEOP(WRAP, 3, 1,"[A B C] WRAP C WITHIN RANGE A TO B"),
MAKEOP(QT, 2, 1,"[A B] QUANTIZE A TO STEP SIZE B"),
MAKEOP(AVG, 2, 1,"AVERAGE TWO VALUES"),
MAKEOP(EQ, 2, 1,"LOGIC: EQUAL"),
MAKEOP(NE, 2, 1,"LOGIC: NOT EQUAL"),
MAKEOP(LT, 2, 1,"LOGIC: LESS THAN"),
MAKEOP(GT, 2, 1,"LOGIC: GREATER THAN"),
MAKEOP(NZ, 1, 1,"LOGIC: NOT ZERO"),
MAKEOP(EZ, 1, 1,"LOGIC: EQUALS ZERO"),
{"TR.TOG", op_TR_TOG, 1, 0, "[A] TOGGLE TRIGGER A"},
MAKEOP(N, 1, 1, "TABLE FOR NOTE VALUES"),
{"S.ALL", op_S_ALL, 0, 0, "S: EXECUTE ALL"},
{"S.POP", op_S_POP, 0, 0, "S: POP LAST"},
{"S.CLR", op_S_CLR, 0, 0, "S: FLUSH"},
{"DEL.CLR", op_DEL_CLR, 0, 0, "DELAY: FLUSH"},
{"M.RESET", op_M_RESET, 0, 0, "METRO: RESET"},
MAKEOP(V, 1, 1, "TO VOLT"),
MAKEOP(VV, 1, 1, "TO VOLT WITH PRECISION"),
{"P", op_P, 1, 1, "PATTERN: GET/SET"},
{"P.INS", op_P_INS, 2, 0, "PATTERN: INSERT"},
{"P.RM", op_P_RM, 1, 1, "PATTERN: REMOVE"},
{"P.PUSH", op_P_PUSH, 1, 0, "PATTERN: PUSH"},
{"P.POP", op_P_POP, 0, 1, "PATTERN: POP"},
{"PN", op_PN, 2, 1, "PATTERN: GET/SET N"},
{"TR.PULSE", op_TR_PULSE, 1, 0, "PULSE TRIGGER"},
{"II", op_II, 2, 0, "II"},
{"RSH", op_RSH, 2, 1, "RIGHT SHIFT"},
{"LSH", op_LSH, 2, 1, "LEFT SHIFT"},
{"S.L", op_S_L, 0, 1, "STACK LENGTH"},
{"CV.SET", op_CV_SET, 2, 0, "CV SET"},
MAKEOP(EXP, 1, 1, "EXPONENTIATE"),
MAKEOP(ABS, 1, 1, "ABSOLUTE VALUE"),
MAKEOP(AND, 2, 1,"LOGIC: AND"),
MAKEOP(OR, 2, 1,"LOGIC: OR"),
MAKEOP(XOR, 2, 1,"LOGIC: XOR"),
MAKEOP(JI, 2, 1,"JUST INTONE DIVISON"),
MAKEOP(SCRIPT, 1, 0,"CALL SCRIPT"),
MAKEOP(KILL, 0, 0,"CLEAR DELAYS, STACK, SLEW"),
MAKEOP(MUTE, 1, 0,"MUTE INPUT"),
MAKEOP(UNMUTE, 1, 0,"UNMUTE INPUT"),
MAKEOP(SCALE, 5, 1,"SCALE NUMBER RANGES"),
MAKEOP(STATE, 1, 1,"GET INPUT STATE"),
MAKEOP(ER, 3, 1,"EUCLIDEAN RHYTHMS")
};
static void op_ADD() {
push(pop() + pop());
}
static void op_SUB() {
push(pop() - pop());
}
static void op_MUL() {
push(pop() * pop());
}
static void op_DIV() {
push(pop() / pop());
}
// can be optimized:
static void op_MOD() {
push(pop() % pop());
}
static void op_RAND() {
int16_t a = pop();
if(a == -1)
push(0);
else
push(rand() % (a+1));
}
static void op_RRAND() {
int16_t a, b, min, max, range;
a = pop();
b = pop();
if(a < b) {
min = a;
max = b;
}
else {
min = b;
max = a;
}
range = max - min + 1;
if(range == 0) push(a);
else
push(rand() % range + min);
}
static void op_TOSS() {
push(rand() & 1);
}
static void op_MIN() {
int16_t a, b;
a = pop();
b = pop();
if(b > a) push(a);
else push(b);
}
static void op_MAX() {
int16_t a, b;
a = pop();
b = pop();
if(a > b) push(a);
else push(b);
}
static void op_LIM() {
int16_t a, b, i;
i = pop();
a = pop();
b = pop();
if(i < a) push(a);
else if(i > b) push(b);
else push(i);
}
static void op_WRAP() {
int16_t a, b, i, c;
i = pop();
a = pop();
b = pop();
if(a < b) {
c = b - a + 1;
while(i >= b)
i -= c;
while(i < a)
i += c;
}
else {
c = a - b + 1;
while(i >= a)
i -= c;
while(i < b)
i += c;
}
push(i);
}
static void op_QT() {
// this rounds negative numbers rather than quantize (choose closer)
int16_t a, b, c, d, e;
b = pop();
a = pop();
c = b / a;
d = c * a;
e = (c+1) * a;
if(abs(b-d) < abs(b-e)) push(d);
else push(e);
}
static void op_AVG() {
push((pop() + pop()) >> 1);
}
static void op_EQ() {
push(pop() == pop());
}
static void op_NE() {
push(pop() != pop());
}
static void op_LT() {
push(pop() < pop());
}
static void op_GT() {
push(pop() > pop());
}
static void op_NZ() {
push(pop() != 0);
}
static void op_EZ() {
push(pop() == 0);
}
static void op_TR_TOG() {
int16_t a = pop();
// saturate and shift
if(a < 1) a = 1;
else if(a > 4) a = 4;
a--;
if(tele_arrays[0].v[a]) tele_arrays[0].v[a] = 0;
else tele_arrays[0].v[a] = 1;
update_tr(a,tele_arrays[0].v[a]);
}
static void op_N() {
int16_t a = pop();
if(a < 0) {
if(a < -127) a = -127;
a = -a;
push(-table_n[a]);
}
else {
if(a > 127) a = 127;
push(table_n[a]);
}
}
static void op_S_ALL() {
for(int16_t i = 0;i<tele_stack_top;i++)
process(&tele_stack[tele_stack_top-i-1]);
tele_stack_top = 0;
(*update_s)(0);
}
static void op_S_POP() {
if(tele_stack_top) {
tele_stack_top--;
process(&tele_stack[tele_stack_top]);
if(tele_stack_top == 0)
(*update_s)(0);
}
}
static void op_S_CLR() {
tele_stack_top = 0;
(*update_s)(0);
}
static void op_DEL_CLR() {
clear_delays();
}
static void op_M_RESET() {
(*update_metro)(tele_vars[V_M].v, tele_vars[V_M_ACT].v, 1);
}
static void op_V() {
int16_t a = pop();
if(a > 10) a = 10;
else if(a < -10) a = -10;
if(a < 0) {
a = -a;
push(-table_v[a]);
}
else
push(table_v[a]);
}
static void op_VV() {
uint8_t negative = 1;
int16_t a = pop();
if(a < 0) {
negative = -1;
a = -a;
}
if(a > 1000) a = 1000;
push(negative * (table_v[a/100] + table_vv[a%100]));
}
static void op_P() {
int16_t a, b;
a = pop();
if(a < 0) {
if(tele_patterns[pn].l == 0) a = 0;
else if(a < -tele_patterns[pn].l) a = 0;
else
a = tele_patterns[pn].l + a;
}
if(a > 63) a = 63;
if(left == 0 && top > 0) {
b = pop();
tele_patterns[pn].v[a] = b;
(*update_pi)();
}
else {
push(tele_patterns[pn].v[a]);
}
}
static void op_P_INS() {
int16_t a, b, i;
a = pop();
b = pop();
if(a < 0) {
if(tele_patterns[pn].l == 0) a = 0;
else if(a < -tele_patterns[pn].l) a = 0;
else
a = tele_patterns[pn].l + a;
}
if(a>63) a =63;
if(tele_patterns[pn].l >= a) {
for(i = tele_patterns[pn].l;i>a;i--)
tele_patterns[pn].v[i] = tele_patterns[pn].v[i-1];
if(tele_patterns[pn].l < 63)
tele_patterns[pn].l++;
}
tele_patterns[pn].v[a] = b;
(*update_pi)();
}
static void op_P_RM() {
int16_t a, i;
a = pop();
if(a < 0) {
if(tele_patterns[pn].l == 0) a = 0;
else if(a < -tele_patterns[pn].l) a = 0;
else
a = tele_patterns[pn].l + a;
}
else if(a > tele_patterns[pn].l) a = tele_patterns[pn].l;
if(tele_patterns[pn].l > 0) {
push(tele_patterns[pn].v[a]);
for(i = a;i<tele_patterns[pn].l;i++)
tele_patterns[pn].v[i] = tele_patterns[pn].v[i+1];
tele_patterns[pn].l--;
}
else push(0);
(*update_pi)();
}
static void op_P_PUSH() {
int16_t a;
a = pop();
if(tele_patterns[pn].l < 64) {
tele_patterns[pn].v[tele_patterns[pn].l] = a;
tele_patterns[pn].l++;
(*update_pi)();
}
}
static void op_P_POP() {
if(tele_patterns[pn].l > 0) {
tele_patterns[pn].l--;
push(tele_patterns[pn].v[tele_patterns[pn].l]);
(*update_pi)();
}
else push(0);
}
static void op_PN() {
int16_t a, b, c;
a = pop();
b = pop();
if(a < 0) a = 0;
else if(a > 3) a = 3;
if(b < 0) {
if(tele_patterns[a].l == 0) b = 0;
else if(b < -tele_patterns[a].l) b = 0;
else
b = tele_patterns[a].l + b;
}
if(b > 63) b = 63;
if(left == 0 && top > 0) {
c = pop();
tele_patterns[a].v[b] = c;
(*update_pi)();
}
else {
push(tele_patterns[a].v[b]);
}
}
static void op_TR_PULSE() {
int16_t a = pop();
// saturate and shift
if(a < 1) a = 1;
else if(a > 4) a = 4;
a--;
int16_t time = tele_arrays[4].v[a]; // pulse time
if (time <= 0) return; // if time <= 0 don't do anything
tele_arrays[0].v[a] = tele_arrays[5].v[a];
tr_pulse[a] = time; // set time
update_tr(a,tele_arrays[0].v[a]);
}
static void op_II() {
int16_t a = pop();
int16_t b = pop();
update_ii(a,b);
}
static void op_RSH() {
push(pop() >> pop());
}
static void op_LSH() {
push(pop() << pop());
}
static void op_S_L() {
push(tele_stack_top);
}
static void op_CV_SET() {
int16_t a = pop();
int16_t b = pop();
// saturate and shift
if(a < 1) a = 1;
else if(a > 4) a = 4;
a--;
if(b<0) b = 0;
else if(b > 16383) b = 16383;
tele_arrays[1].v[a] = b;
(*update_cv)(a, b, 0);
}
static void op_EXP() {
int16_t a = pop();
if(a > 16383) a = 16383;
else if(a < -16383) a = -16383;
a = a >> 6;
if(a < 0) {
a = -a;
push(-table_exp[a]);
}
else
push(table_exp[a]);
}
static void op_ABS() {
int16_t a = pop();
if(a < 0)
push(-a);
else
push(a);
}
static void op_AND() {
push(pop() & pop());
}
static void op_OR() {
push(pop() | pop());
}
static void op_XOR() {
push(pop() ^ pop());
}
static void op_JI() {
uint32_t ji = (((pop()<<8) / pop()) * 1684) >> 8;
while(ji > 1683)
ji >>= 1;
push(ji);
}
static void op_SCRIPT() {
uint16_t a = pop();
if(a > 0 && a < 9)
(*run_script)(a);
}
static void op_KILL() {
clear_delays();
(*update_kill)();
}
static void op_MUTE() {
int16_t a;
a = pop();
if(a > 0 && a < 9) {
(*update_mute)(a-1,0);
}
}
static void op_UNMUTE() {
int16_t a;
a = pop();
if(a > 0 && a < 9) {
(*update_mute)(a-1,1);
}
}
static void op_SCALE() {
int16_t a, b, x, y, i;
a = pop();
b = pop();
x = pop();
y = pop();
i = pop();
push((i-a) * (y-x) / (b-a) + x);
}
static void op_STATE() {
int16_t a = pop();
a--;
if(a<0) a=0;
else if(a>7) a=7;
(*update_input)(a);
push(input_states[a]);
}
static void op_ER() {
int16_t fill = pop();
int16_t len = pop();
int16_t step = pop();
push(euclidean(fill, len, step));
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
// PROCESS //////////////////////////////////////////////////////
error_t parse(char *cmd) {
char c[32];
strcpy(c,cmd);
const char *delim = " \n";
const char *s = strtok(c,delim);
uint8_t n = 0;
temp.l = n;
// sprintf(dbg,"\r\nparse: ");
while(s) {
// CHECK IF NUMBER
if(isdigit(s[0]) || s[0]=='-') {
temp.data[n].t = NUMBER;
temp.data[n].v = strtol(s, NULL, 0);
}
else if(s[0]==':')
temp.data[n].t = SEP;
else {
// CHECK AGAINST VARS
int16_t i = VARS - 1;
do {
// print_dbg("\r\nvar '");
// print_dbg(tele_vars[i].name);
// print_dbg("'");
if(!strcmp(s,tele_vars[i].name)) {
temp.data[n].t = VAR;
temp.data[n].v = i;
// sprintf(dbg,"v(%d) ", temp.data[n].v);
break;
}
} while(i--);
if(i == -1) {
// CHECK AGAINST ARRAYS
i = ARRAYS;
while(i--) {
// print_dbg("\r\narrays '");
// print_dbg(tele_arrays[i].name);
// print_dbg("'");
if(!strcmp(s,tele_arrays[i].name)) {
temp.data[n].t = ARRAY;
temp.data[n].v = i;
// sprintf(dbg,"a(%d) ", temp.data[n].v);
break;
}
}
}
if(i == -1) {
// CHECK AGAINST OPS
i = OPS;
while(i--) {
// print_dbg("\r\nops '");
// print_dbg(tele_ops[i].name);
// print_dbg("'");
if(!strcmp(s,tele_ops[i].name)) {
temp.data[n].t = OP;
temp.data[n].v = i;
// sprintf(dbg,"f(%d) ", temp.data[n].v);
break;
}
}
}
if(i == -1) {
// CHECK AGAINST MOD
i = MODS;
while(i--) {
// print_dbg("\r\nmods '");
// print_dbg(tele_mods[i].name);
// print_dbg("'");
if(!strcmp(s,tele_mods[i].name)) {
temp.data[n].t = MOD;
temp.data[n].v = i;
// sprintf(dbg,"f(%d) ", temp.data[n].v);
break;
}
}
}
if(i == -1) {
// CHECK AGAINST KEY
i = KEYS;
while(i--) {
// print_dbg("\r\nmods '");
// print_dbg(tele_mods[i].name);
// print_dbg("'");
if(!strcmp(s,tele_keys[i].name)) {
temp.data[n].t = KEY;
temp.data[n].v = i;
// sprintf(dbg,"f(%d) ", temp.data[n].v);
break;
}
}
}
if(i == -1) {
strcpy(error_detail, s);
return E_PARSE;
}
}
s = strtok(NULL,delim);
n++;
temp.l = n;
if(n == COMMAND_MAX_LENGTH)
return E_LENGTH;
}
// sprintf(dbg,"// length: %d", temp.l);
return E_OK;
}
/////////////////////////////////////////////////////////////////
// VALIDATE /////////////////////////////////////////////////////
error_t validate(tele_command_t *c) {
int16_t h = 0;
uint8_t n = c->l;
c->separator = -1;
while(n--) {
if(c->data[n].t == OP) {
if(tele_ops[c->data[n].v].returns == 0 && n) {
if(c->data[n-1].t != SEP) {
strcpy(error_detail, tele_ops[c->data[n].v].name);
return E_NOT_LEFT;
}
}
h -= tele_ops[c->data[n].v].params;
if(h < 0) {
strcpy(error_detail, tele_ops[c->data[n].v].name);
return E_NEED_PARAMS;
}
h += tele_ops[c->data[n].v].returns;
// hack for var-length params for P
if(c->data[n].v == 29 || c->data[n].v == 34) {
if(n==0)
h--;
else if(c->data[n-1].t == SEP)
h--;
}
}
else if(c->data[n].t == MOD) {
strcpy(error_detail, tele_mods[c->data[n].v].name);
if(n != 0)
return E_NO_MOD_HERE;
else if(c->separator == -1)
return E_NEED_SEP;
else if(h < tele_mods[c->data[n].v].params)
return E_NEED_PARAMS;
else if(h > tele_mods[c->data[n].v].params)
return E_EXTRA_PARAMS;
else h = 0;
}
else if(c->data[n].t == SEP) {
if(c->separator != -1)
return E_MANY_SEP;
else if(n==0)
return E_PLACE_SEP;
c->separator = n;
if(h > 1)
return E_EXTRA_PARAMS;
else h = 0;
}
// RIGHT (get)
else if(n && c->data[n-1].t != SEP) {
if(c->data[n].t == NUMBER || c->data[n].t == VAR || c->data[n].t == KEY) {
h++;
}
else if(c->data[n].t == ARRAY) {
if(h < 1) {
strcpy(error_detail, tele_arrays[c->data[n].v].name);
return E_NEED_PARAMS;
}
// h-- then h++
}
}
// LEFT (set)
else {
if(c->data[n].t == NUMBER || c->data[n].t == KEY) {
h++;
}
else if(c->data[n].t == VAR) {
if(h == 0) h++;
// else {
// h--;
// if(h > 0)
// return E_EXTRA_PARAMS;
// }
}
else if(c->data[n].t == ARRAY) {
if(h < 1) {
strcpy(error_detail, tele_arrays[c->data[n].v].name);
return E_NEED_PARAMS;
}
h--;
if(h == 0) h++;
// else if(h > 1)
// return E_EXTRA_PARAMS;
}
}
}
if(h > 1)
return E_EXTRA_PARAMS;
else
return E_OK;
}
/////////////////////////////////////////////////////////////////
// PROCESS //////////////////////////////////////////////////////
void process(tele_command_t *c) {
top = 0; left = 0;
int16_t i;
int16_t n;
if(c->separator == -1)
n = c->l;
else
n = c->separator;
// sprintf(dbg,"\r\r\nprocess (%d): %s", n, print_command(c));
// DBG;
while(n--) {
left = n;
if(c->data[n].t == NUMBER)
push(c->data[n].v);
else if(c->data[n].t == OP)
tele_ops[c->data[n].v].func();
else if(c->data[n].t == MOD)
tele_mods[c->data[n].v].func(c);
else if(c->data[n].t == VAR) {
if(tele_vars[c->data[n].v].func == NULL) {
if(n || top == 0 )
push(tele_vars[c->data[n].v].v);
else
tele_vars[c->data[n].v].v = pop();
}
else
tele_vars[c->data[n].v].func(0);
}
else if(c->data[n].t == ARRAY) {
i = pop();
// saturate for 1-4 indexing
if(i<1) i=1;
else if(i>3) i=4;
i--;
if(n || top == 0) {
// sprintf(dbg,"\r\nget array %s @ %d : %d", tele_arrays[c->data[n].v].name, i, tele_arrays[c->data[n].v].v[i]);
// DBG
push(tele_arrays[c->data[n].v].v[i]);
}
else {
// sprintf(dbg,"\r\nset array %s @ %d to %d", tele_arrays[c->data[n].v].name, i, tele_arrays[c->data[n].v].v[i]);
// DBG
if(tele_arrays[c->data[n].v].func)
tele_arrays[c->data[n].v].func(i);
else
tele_arrays[c->data[n].v].v[i] = pop();
}
}
else if(c->data[n].t == KEY) {
push(tele_keys[c->data[n].v].v);
}
}
// PRint16_t DEBUG OUTPUT IF VAL LEFT ON STACK
if(top) {
output = pop();
output_new++;
// sprintf(dbg,"\r\n>>> %d", output);
// DBG
// to_v(output);
}
}
char * print_command(const tele_command_t *c) {
int16_t n = 0;
char number[8];
char *p = pcmd;
*p = 0;
while(n < c->l) {
switch(c->data[n].t) {
case OP:
strcpy(p, tele_ops[c->data[n].v].name);
p += strlen(tele_ops[c->data[n].v].name) - 1;
break;
case ARRAY:
strcpy(p,tele_arrays[c->data[n].v].name);
p += strlen(tele_arrays[c->data[n].v].name) - 1;
break;
case NUMBER:
itoa(c->data[n].v,number,10);
strcpy(p, number);
p+=strlen(number) - 1;
break;
case VAR:
strcpy(p,tele_vars[c->data[n].v].name);
p += strlen(tele_vars[c->data[n].v].name) - 1;
break;
case MOD:
strcpy(p, tele_mods[c->data[n].v].name);
p += strlen(tele_mods[c->data[n].v].name) - 1;
break;
case SEP:
*p = ':';
break;
case KEY:
strcpy(p,tele_keys[c->data[n].v].name);
p += strlen(tele_keys[c->data[n].v].name) - 1;
break;
default:
break;
}
n++;
p++;
*p = ' ';
p++;
}
p--;
*p = 0;
return pcmd;
}
int16_t tele_get_array(uint8_t a, uint8_t i) {
return tele_arrays[a].v[i];
}
void tele_set_array(uint8_t a, uint8_t i, uint16_t v) {
tele_arrays[a].v[i] = v;
}
void tele_set_val(uint8_t i, uint16_t v) {
tele_vars[i].v = v;
}
void tele_tick(uint8_t i) {
process_delays(i);
// inc time
if(tele_vars[V_TIME_ACT].v)
tele_vars[V_TIME].v += i;
}
void tele_init() {
u8 i;
for(i=0;i<4;i++) {
tele_patterns[i].i = 0;
tele_patterns[i].l = 0;
tele_patterns[i].wrap = 1;
tele_patterns[i].start = 0;
tele_patterns[i].end = 63;
}
for(i=0;i<8;i++)
mutes[i] = 1;
}
const char * to_v(int16_t i) {
static char n[3], v[7];
int16_t a=0, b=0;
if(i > table_v[8]) {
i -= table_v[8];
a += 8;
}
if(i > table_v[4]) {
i -= table_v[4];
a += 4;
}
if(i > table_v[2]) {
i -= table_v[2];
a += 2;
}
if(i > table_v[1]) {
i -= table_v[1];
a += 1;
}
if(i > table_vv[64]) {
i -= table_vv[64];
b += 64;
}
if(i > table_vv[32]) {
i -= table_vv[32];
b += 32;
}
if(i > table_vv[16]) {
i -= table_vv[16];
b += 16;
}
if(i > table_vv[8]) {
i -= table_vv[8];
b += 8;
}
if(i > table_vv[4]) {
i -= table_vv[4];
b += 4;
}
if(i > table_vv[2]) {
i -= table_vv[2];
b++;
}
if(i > table_vv[1]) {
i -= table_vv[1];
b++;
}
b++;
itoa(a,n,10);
strcpy(v, n);
strcat(v,".");
itoa(b,n,10);
strcat(v, n);
strcat(v,"V");
return v;
// printf(" (VV %d %d)",a,b);
}