Commit bbaf5e5d authored by Jacob Vosmaer's avatar Jacob Vosmaer

Add JP-6 style poly assigner

parent a58d0354
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 = at90s2313
#MCU_TARGET = at90s2333
......
......@@ -6,10 +6,12 @@
#include "midi.h"
#include "voice.h"
#include "poly.h"
#include "poly2.h"
#include "mono.h"
enum _programs {
PGM_POLY,
PGM_POLY2,
PGM_MONO,
NUM_PGM,
};
......@@ -17,26 +19,31 @@ static uint8_t current_program = NUM_PGM;
void (*note_on[NUM_PGM])(uint8_t n) = {
poly_note_on,
poly2_note_on,
mono_note_on,
};
void (*note_off[NUM_PGM])(uint8_t n) = {
poly_note_off,
poly2_note_off,
mono_note_off,
};
void (*control_change[NUM_PGM])(uint8_t ctl, uint8_t val) = {
poly_control_change,
poly2_control_change,
mono_control_change,
};
void (*pitch_bend[NUM_PGM])(uint16_t bend) = {
poly_pitch_bend,
poly2_pitch_bend,
mono_pitch_bend,
};
void (*update_clock[NUM_PGM])(uint8_t delta) = {
poly_update_clock,
poly2_update_clock,
mono_update_clock,
};
......@@ -77,6 +84,9 @@ program_change(uint8_t pgm)
case PGM_POLY:
poly_init();
return;
case PGM_POLY2:
poly2_init();
return;
case PGM_MONO:
mono_init();
return;
......
......@@ -111,6 +111,60 @@ test_contains(void)
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
main(int argc, char** argv)
{
......@@ -118,5 +172,8 @@ main(int argc, char** argv)
test_empty();
test_push();
test_contains();
test_append();
test_index();
return 0;
}
#include "list.h"
uint8_t
succ(struct list *l, uint8_t x)
l_succ(struct list *l, uint8_t x)
{
return l->array[x];
}
......@@ -18,6 +18,30 @@ l_push(struct list *l, uint8_t 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
l_delete(struct list *l, uint8_t x)
{
......@@ -26,13 +50,13 @@ l_delete(struct list *l, uint8_t x)
}
if (l->head == x) {
l->head = succ(l, x);
l->head = l_succ(l, x);
return;
}
for (uint8_t i = l->head; i != l->sup; i = succ(l, i)) {
if (succ(l, i) == x) {
l->array[i] = succ(l, x);
for (uint8_t i = l->head; i != l->sup; i = l_succ(l, i)) {
if (l_succ(l, i) == x) {
l->array[i] = l_succ(l, x);
return;
}
}
......@@ -52,7 +76,7 @@ l_last(struct list *l)
}
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
}
return x;
......@@ -72,17 +96,24 @@ l_empty(struct list *l)
uint8_t
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) {
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) {
return 1;
return j;
}
j++;
}
return 0;
return l->sup;
}
......@@ -10,11 +10,14 @@ struct list {
};
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);
uint8_t l_first(struct list *l);
uint8_t l_last(struct list *l);
void l_flush(struct list *l);
uint8_t l_empty(struct list *l);
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
......@@ -5,10 +5,10 @@
#include "list.h"
#include "vibrato.h"
#include "midi.h"
#include "notes.h"
#include <util/delay.h>
#define NUM_NOTES 128
static uint8_t _notes_array[NUM_NOTES];
static struct list notes = {
.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