Commit bbaf5e5d authored by Jacob Vosmaer's avatar Jacob Vosmaer

Add JP-6 style poly assigner

parent a58d0354
PRG = crowbx PRG = crowbx
OBJ = crowbx.o midi.o dac.o voice.o uart.o gate.o poly.o mono.o list.o vibrato.o OBJ = crowbx.o midi.o dac.o voice.o uart.o gate.o poly.o mono.o list.o vibrato.o poly2.o
MCU_TARGET = atmega328p MCU_TARGET = atmega328p
#MCU_TARGET = at90s2313 #MCU_TARGET = at90s2313
#MCU_TARGET = at90s2333 #MCU_TARGET = at90s2333
......
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
#include "midi.h" #include "midi.h"
#include "voice.h" #include "voice.h"
#include "poly.h" #include "poly.h"
#include "poly2.h"
#include "mono.h" #include "mono.h"
enum _programs { enum _programs {
PGM_POLY, PGM_POLY,
PGM_POLY2,
PGM_MONO, PGM_MONO,
NUM_PGM, NUM_PGM,
}; };
...@@ -17,26 +19,31 @@ static uint8_t current_program = NUM_PGM; ...@@ -17,26 +19,31 @@ static uint8_t current_program = NUM_PGM;
void (*note_on[NUM_PGM])(uint8_t n) = { void (*note_on[NUM_PGM])(uint8_t n) = {
poly_note_on, poly_note_on,
poly2_note_on,
mono_note_on, mono_note_on,
}; };
void (*note_off[NUM_PGM])(uint8_t n) = { void (*note_off[NUM_PGM])(uint8_t n) = {
poly_note_off, poly_note_off,
poly2_note_off,
mono_note_off, mono_note_off,
}; };
void (*control_change[NUM_PGM])(uint8_t ctl, uint8_t val) = { void (*control_change[NUM_PGM])(uint8_t ctl, uint8_t val) = {
poly_control_change, poly_control_change,
poly2_control_change,
mono_control_change, mono_control_change,
}; };
void (*pitch_bend[NUM_PGM])(uint16_t bend) = { void (*pitch_bend[NUM_PGM])(uint16_t bend) = {
poly_pitch_bend, poly_pitch_bend,
poly2_pitch_bend,
mono_pitch_bend, mono_pitch_bend,
}; };
void (*update_clock[NUM_PGM])(uint8_t delta) = { void (*update_clock[NUM_PGM])(uint8_t delta) = {
poly_update_clock, poly_update_clock,
poly2_update_clock,
mono_update_clock, mono_update_clock,
}; };
...@@ -77,6 +84,9 @@ program_change(uint8_t pgm) ...@@ -77,6 +84,9 @@ program_change(uint8_t pgm)
case PGM_POLY: case PGM_POLY:
poly_init(); poly_init();
return; return;
case PGM_POLY2:
poly2_init();
return;
case PGM_MONO: case PGM_MONO:
mono_init(); mono_init();
return; return;
......
...@@ -111,6 +111,60 @@ test_contains(void) ...@@ -111,6 +111,60 @@ test_contains(void)
assert(l_contains(&l, 4)); assert(l_contains(&l, 4));
} }
void
test_append(void)
{
desc("test l_append()");
l_flush(&l);
l_push(&l, 3);
l_push(&l, 4);
l_push(&l, 9);
l_append(&l, 2);
assert(l.head == 9);
assert(l.array[9] == 4);
assert(l.array[4] == 3);
assert(l.array[3] == 2);
assert(l.array[2] == l.sup);
l_flush(&l);
l_append(&l, 5);
assert(l_last(&l) == 5);
assert(l_first(&l) == 5);
l_flush(&l);
l_push(&l, 2);
l_push(&l, 3);
l_push(&l, 4);
l_append(&l, 4);
assert(l_last(&l) == 4);
assert(l_first(&l) == 3);
}
void
test_index(void)
{
desc("test l_index()");
l_flush(&l);
l_push(&l, 3);
l_push(&l, 4);
l_push(&l, 9);
l_append(&l, 2);
assert(l_index(&l, 3) == 2);
assert(l_index(&l, 4) == 1);
assert(l_index(&l, 9) == 0);
assert(l_index(&l, 2) == 3);
assert(l_index(&l, 5) == l.sup);
assert(l_index(&l, l.sup) == l.sup);
assert(l_index(&l, l.sup + 1) == l.sup);
}
int int
main(int argc, char** argv) main(int argc, char** argv)
{ {
...@@ -118,5 +172,8 @@ main(int argc, char** argv) ...@@ -118,5 +172,8 @@ main(int argc, char** argv)
test_empty(); test_empty();
test_push(); test_push();
test_contains(); test_contains();
test_append();
test_index();
return 0; return 0;
} }
#include "list.h" #include "list.h"
uint8_t uint8_t
succ(struct list *l, uint8_t x) l_succ(struct list *l, uint8_t x)
{ {
return l->array[x]; return l->array[x];
} }
...@@ -18,6 +18,30 @@ l_push(struct list *l, uint8_t x) ...@@ -18,6 +18,30 @@ l_push(struct list *l, uint8_t x)
l->head = x; l->head = x;
} }
void
l_append(struct list *l, uint8_t x)
{
if (x >= l->sup) {
return;
}
if (l_empty(l)) {
l_push(l, x);
return;
}
l_delete(l, x);
uint8_t i = l->head;
for (; l_succ(l, i) != l->sup; i = l_succ(l, i)) {
// nop
}
l->array[i] = x;
l->array[x] = l->sup;
}
void void
l_delete(struct list *l, uint8_t x) l_delete(struct list *l, uint8_t x)
{ {
...@@ -26,13 +50,13 @@ l_delete(struct list *l, uint8_t x) ...@@ -26,13 +50,13 @@ l_delete(struct list *l, uint8_t x)
} }
if (l->head == x) { if (l->head == x) {
l->head = succ(l, x); l->head = l_succ(l, x);
return; return;
} }
for (uint8_t i = l->head; i != l->sup; i = succ(l, i)) { for (uint8_t i = l->head; i != l->sup; i = l_succ(l, i)) {
if (succ(l, i) == x) { if (l_succ(l, i) == x) {
l->array[i] = succ(l, x); l->array[i] = l_succ(l, x);
return; return;
} }
} }
...@@ -52,7 +76,7 @@ l_last(struct list *l) ...@@ -52,7 +76,7 @@ l_last(struct list *l)
} }
uint8_t x = l->head; uint8_t x = l->head;
for (; succ(l, x) != l->sup; x = succ(l, x)) { for (; l_succ(l, x) != l->sup; x = l_succ(l, x)) {
// walk the list // walk the list
} }
return x; return x;
...@@ -72,17 +96,24 @@ l_empty(struct list *l) ...@@ -72,17 +96,24 @@ l_empty(struct list *l)
uint8_t uint8_t
l_contains(struct list *l, uint8_t x) l_contains(struct list *l, uint8_t x)
{
return l_index(l, x) < l->sup;
}
uint8_t
l_index(struct list *l, uint8_t x)
{ {
if (x >= l->sup) { if (x >= l->sup) {
return 0; return l->sup;
} }
for (uint8_t i = l->head; i != l->sup; i = succ(l, i)) { uint8_t j = 0;
for (uint8_t i = l->head; i != l->sup; i = l_succ(l, i)) {
if (i == x) { if (i == x) {
return 1; return j;
} }
j++;
} }
return 0; return l->sup;
} }
...@@ -10,11 +10,14 @@ struct list { ...@@ -10,11 +10,14 @@ struct list {
}; };
void l_push(struct list *l, uint8_t x); void l_push(struct list *l, uint8_t x);
void l_append(struct list *l, uint8_t x);
void l_delete(struct list *l, uint8_t x); void l_delete(struct list *l, uint8_t x);
uint8_t l_first(struct list *l); uint8_t l_first(struct list *l);
uint8_t l_last(struct list *l); uint8_t l_last(struct list *l);
void l_flush(struct list *l); void l_flush(struct list *l);
uint8_t l_empty(struct list *l); uint8_t l_empty(struct list *l);
uint8_t l_contains(struct list *l, uint8_t x); uint8_t l_contains(struct list *l, uint8_t x);
uint8_t l_succ(struct list *l, uint8_t x);
uint8_t l_index(struct list *l, uint8_t x);
#endif #endif
...@@ -5,10 +5,10 @@ ...@@ -5,10 +5,10 @@
#include "list.h" #include "list.h"
#include "vibrato.h" #include "vibrato.h"
#include "midi.h" #include "midi.h"
#include "notes.h"
#include <util/delay.h> #include <util/delay.h>
#define NUM_NOTES 128
static uint8_t _notes_array[NUM_NOTES]; static uint8_t _notes_array[NUM_NOTES];
static struct list notes = { static struct list notes = {
.array = _notes_array, .array = _notes_array,
......
#ifndef _notes_h
#define _notes_h
#define NUM_NOTES 128
#endif
#include "dac.h"
#include "poly2.h"
#include "gate.h"
#include "voice.h"
#include "vibrato.h"
#include "midi.h"
#include "list.h"
#include "notes.h"
static uint8_t playing[NUM_VOICES];
static uint16_t current_bend;
static uint8_t want_play_array[NUM_NOTES];
static struct list want_play = {
.array = want_play_array,
.sup = NUM_NOTES,
};
static uint8_t avail_array[NUM_VOICES];
static struct list avail = {
.array = avail_array,
.sup = NUM_VOICES,
};
void poly2_update_playing(void);
void
poly2_init(void)
{
l_flush(&want_play);
l_flush(&avail);
for (uint8_t i = 0; i < NUM_VOICES; i++) {
playing[i] = NUM_NOTES;
l_push(&avail, i);
}
current_bend = BEND_CENTER;
}
void
poly2_set_pitch(uint8_t v, uint8_t note)
{
dac_set_note2(v, note, vibrato_detune(), current_bend);
}
void
poly2_note_on(uint8_t note)
{
if (note >= NUM_NOTES) {
return; // should never happen
}
l_append(&want_play, note);
poly2_update_playing();
}
static uint8_t
poly2_is_playing(uint8_t note)
{
for (uint8_t v = 0; v < NUM_VOICES; v++) {
if (playing[v] == note) {
return 1;
}
}
return 0;
}
void
poly2_update_playing(void)
{
for (uint8_t v = 0; v < NUM_VOICES; v++) {
if ((playing[v] < NUM_NOTES) && !(l_index(&want_play, playing[v]) < NUM_VOICES)) {
gate_off(v);
playing[v] = NUM_NOTES;
l_push(&avail, v);
}
}
uint8_t want_play_i = 0;
for (uint8_t j = want_play.head; (want_play_i < NUM_VOICES) && (j != want_play.sup); want_play_i++, (j = l_succ(&want_play, j))) {
if (poly2_is_playing(j)) {
continue;
}
uint8_t v = l_last(&avail);
if (v == NUM_VOICES) {
// no voices available
continue;
}
poly2_set_pitch(v, j);
gate_on(v);
playing[v] = j;
l_delete(&avail, v);
}
}
void
poly2_note_off(uint8_t note)
{
if (note >= NUM_NOTES) {
return; // should never happen
}
l_delete(&want_play, note);
poly2_update_playing();
}
void
poly2_control_change(uint8_t ctl, uint8_t val)
{
switch (ctl) {
case CC_MOD_WHEEL:
vibrato_set_depth(val);
break;
case CC_VIB_RATE:
vibrato_set_rate(val);
break;
}
}
void
poly2_pitch_bend(uint16_t bend)
{
current_bend = bend;
for (uint8_t v = 0; v < NUM_VOICES; v++) {
poly2_set_pitch(v, playing[v]);
}
}
void
poly2_update_clock(uint8_t delta)
{
vibrato_update(delta);
for (uint8_t v = 0; v < NUM_VOICES; v++) {
poly2_set_pitch(v, playing[v]);
}
}
#ifndef _poly2_h
#define _poly2_h
#include <stdint.h>
void poly2_init(void);
void poly2_note_on(uint8_t note);
void poly2_note_off(uint8_t note);
void poly2_control_change(uint8_t ctl, uint8_t val);
void poly2_pitch_bend(uint16_t bend);
void poly2_update_clock(uint8_t delta);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment