Commit 98babff7 authored by Jacob Vosmaer's avatar Jacob Vosmaer

Make list ADT

parent 5cdc03a4
PRG = crowbx
OBJ = crowbx.o midi.o dac.o voice.o uart.o gate.o poly.o mono.o queue.o
OBJ = crowbx.o midi.o dac.o voice.o uart.o gate.o poly.o mono.o queue.o list.o
MCU_TARGET = atmega328p
#MCU_TARGET = at90s2313
#MCU_TARGET = at90s2333
......
#include "list.h"
void
l_push(struct list *l, uint8_t x)
{
l->array[x] = l->head;
l->head = x;
}
void
l_delete(struct list *l, uint8_t x)
{
if (l->head == x) {
l->head = l->array[x];
return;
}
for (uint8_t i = l->head; l->array[i] != l->sup; i = l->array[i]) {
if (l->array[i] == x) {
l->array[i] = l->array[x];
return;
}
}
}
uint8_t
l_last(struct list *l)
{
uint8_t x = l->head;
if (x == l->sup) {
return x;
}
for (; l->array[x] != l->sup; x = l->array[x]) {
// walk the list
}
return x;
}
void
l_flush(struct list *l)
{
l->head = l->sup;
}
#ifndef _list_h
#define _list_h
#include <inttypes.h>
struct list {
uint8_t head;
uint8_t *array;
uint8_t sup;
};
void l_push(struct list *l, uint8_t x);
void l_delete(struct list *l, uint8_t x);
uint8_t l_last(struct list *l);
void l_flush(struct list *l);
#endif
......@@ -40,3 +40,10 @@ q_dequeue(struct queue *q)
q->head = q_advance(q, q->head);
return x;
}
void
q_flush(struct queue *q)
{
q->head = 0;
q->tail = 0;
}
......@@ -15,5 +15,6 @@ uint8_t q_full(struct queue *q);
void q_enqueue(struct queue *q, uint8_t x);
uint8_t q_empty(struct queue *q);
uint8_t q_dequeue(struct queue *q);
void q_flush(struct queue *q);
#endif
#include "voice.h"
#include "queue.h"
#include "list.h"
// The voice assigner moves voices between the 'avail' (available) queue
// and the 'playing' list. The 'avail' data structure is a queue to get a
......@@ -42,8 +43,6 @@
uint8_t avail_array[NUM_VOICES + 1];
struct queue avail = {
.head = 0,
.tail = 0,
.array = avail_array,
.size = NUM_VOICES,
};
......@@ -71,8 +70,12 @@ avail_dequeue(void)
// list aspect is used to be able to determine the oldest playing note,
// and to be able to remove voices from anywhere in the list. A voice may
// only occur once in the list.
uint8_t playing[NUM_VOICES];
uint8_t playing_head;
uint8_t playing_array[NUM_VOICES];
struct list playing = {
.array = playing_array,
.sup = NUM_VOICES,
};
// playing_head is a number between 0 and NUM_VOICES. if playing_head < NUM_VOICES it
// indicates the last voice that started playing. If playing_head == NUM_VOICES,
......@@ -90,34 +93,19 @@ uint8_t playing_head;
void
playing_play(uint8_t v)
{
playing[v] = playing_head;
playing_head = v;
l_push(&playing, v);
}
void
playing_release(uint8_t v)
{
if (playing_head == v) {
playing_head = playing[v];
return;
}
for (uint8_t i = playing_head; playing[i] != NUM_VOICES; i = playing[i]) {
if (playing[i] == v) {
playing[i] = playing[v];
return;
}
}
l_delete(&playing, v);
}
uint8_t
playing_oldest(void)
{
uint8_t i = playing_head;
for (; playing[i] != NUM_VOICES; i = playing[i]) {
// walk the list
}
return i;
return l_last(&playing);
}
// notes maps voices to the MIDI note they are currently playing, if they
......@@ -127,13 +115,12 @@ uint8_t notes[NUM_VOICES];
void
voice_init(void)
{
avail.head = 0;
avail.tail = 0;
q_flush(&avail);
for (uint8_t i = 0; i < NUM_VOICES; i++) {
avail_enqueue(i);
}
playing_head = NUM_VOICES;
l_flush(&playing);
}
// Release the oldest playing voice, regardless of what note it is playing.
......@@ -172,7 +159,7 @@ voice_release(uint8_t note)
{
// Find oldest voice playing this note
uint8_t v = NUM_VOICES;
for (uint8_t i = playing_head; i != NUM_VOICES; i = playing[i]) {
for (uint8_t i = playing.head; i != playing.sup; i = playing.array[i]) {
if (notes[i] == note) {
v = i;
}
......
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