crowbx.c 2.83 KB
Newer Older
Jacob Vosmaer's avatar
Jacob Vosmaer committed
1 2 3
#include <avr/io.h>
#include <util/delay.h>

4
#include "dac.h"
Jacob Vosmaer's avatar
Jacob Vosmaer committed
5
#include "gate.h"
Jacob Vosmaer's avatar
Jacob Vosmaer committed
6
#include "midi.h"
Jacob Vosmaer's avatar
Jacob Vosmaer committed
7
#include "voice.h"
8
#include "poly.h"
9
#include "poly2.h"
Jacob Vosmaer's avatar
Jacob Vosmaer committed
10 11 12 13
#include "mono.h"

enum _programs {
	PGM_POLY,
14
	PGM_POLY2,
Jacob Vosmaer's avatar
Jacob Vosmaer committed
15 16 17
	PGM_MONO,
	NUM_PGM,
};
18
static uint8_t current_program = NUM_PGM;
Jacob Vosmaer's avatar
Jacob Vosmaer committed
19

20 21
void (*note_on[NUM_PGM])(uint8_t n) = {
	poly_note_on,
22
	poly2_note_on,
23 24 25 26 27
	mono_note_on,
};

void (*note_off[NUM_PGM])(uint8_t n) = {
	poly_note_off,
28
	poly2_note_off,
29 30 31
	mono_note_off,
};

32 33
void (*control_change[NUM_PGM])(uint8_t ctl, uint8_t val) = {
	poly_control_change,
34
	poly2_control_change,
35 36 37
	mono_control_change,
};

38 39
void (*pitch_bend[NUM_PGM])(uint16_t bend) = {
	poly_pitch_bend,
40
	poly2_pitch_bend,
41 42 43
	mono_pitch_bend,
};

44 45
void (*update_clock[NUM_PGM])(uint8_t delta) = {
	poly_update_clock,
46
	poly2_update_clock,
47 48 49
	mono_update_clock,
};

50 51 52 53 54 55 56 57 58 59 60 61
void
io_init(void)
{
	 // More outputs to save power; PORTB6/7 is XTAL
	DDRB = _BV(PORTB0) | _BV(PORTB1) | _BV(PORTB2) | _BV(PORTB3) | _BV(PORTB4) | _BV(PORTB5);

	// More outputs to save power; PORTC6 is reset,  "PORTC7" does not exist (?)
	DDRC = _BV(PORTC0) | _BV(PORTC1) | _BV(PORTC2) | _BV(PORTC3) | _BV(PORTC4) | _BV(PORTC5);

	// PORTD0 is UART RX. Set all other PORTD pins output, to save power.
	DDRD = _BV(PORTD1) | _BV(PORTD2) | _BV(PORTD3) | _BV(PORTD4) | _BV(PORTD5) | _BV(PORTD6) | _BV(PORTD7);
}
Jacob Vosmaer's avatar
Jacob Vosmaer committed
62

63 64 65
void
clock_init(void)
{
66
	// Run Timer0 (8-bit timer) at F_CPU/1024 -- faster incurs roll arounds. Use 16 bit timer?
67 68 69
	TCCR0B |= _BV(CS00) | _BV(CS02);
}

Jacob Vosmaer's avatar
Jacob Vosmaer committed
70 71 72 73 74 75 76 77 78
void
program_change(uint8_t pgm)
{
	if ((pgm >= NUM_PGM) || (pgm == current_program)) {
		return;
	}

	current_program = pgm;

Jacob Vosmaer's avatar
Jacob Vosmaer committed
79
	for_each_voice(v) {
Jacob Vosmaer's avatar
Jacob Vosmaer committed
80 81 82 83 84 85 86
		gate_off(v);
	}

	switch (pgm) {
	case PGM_POLY:
		poly_init();
		return;
87 88 89
	case PGM_POLY2:
		poly2_init();
		return;
Jacob Vosmaer's avatar
Jacob Vosmaer committed
90 91 92 93 94 95
	case PGM_MONO:
		mono_init();
		return;
	}
}

96 97 98
int
main(void)
{
99
	io_init();
100
	dac_init();
101
	midi_init();
102
	clock_init();
103
	program_change(PGM_POLY);
104

105 106
	uint8_t prev_clock = 0;

107
	for (;;) {
108 109 110 111
		uint8_t clock = TCNT0;
		(*update_clock[current_program])(clock - prev_clock);
		prev_clock = clock;

112 113
		if (!midi_read()) {
			continue;
114
		}
115

116
		uint16_t data = midi_data();
117

118
		if (midi_status() == MIDI_NOTE_ON) {
119 120
			uint8_t note = data >> 8;
			uint8_t velocity = data & 0xff;
Jacob Vosmaer's avatar
Jacob Vosmaer committed
121

122
			if (velocity > 0) {
123
				(*note_on[current_program])(note);
Jacob Vosmaer's avatar
Jacob Vosmaer committed
124
			} else {
125
				(*note_off[current_program])(note);
126
			}
Jacob Vosmaer's avatar
Jacob Vosmaer committed
127
		} else if (midi_status() == MIDI_NOTE_OFF) {
128
			uint8_t note = data >> 8;
129
			(*note_off[current_program])(note);
Jacob Vosmaer's avatar
Jacob Vosmaer committed
130
		} else if (midi_status() == MIDI_PROGRAM_CHANGE) {
131
			uint8_t pgm = data >> 8;
Jacob Vosmaer's avatar
Jacob Vosmaer committed
132
			program_change(pgm);
133
		} else if (midi_status() == MIDI_CONTROL_CHANGE) {
134 135
			uint8_t ctl = data >> 8;
			uint8_t val = data & 0xff;
Jacob Vosmaer's avatar
Jacob Vosmaer committed
136
			(*control_change[current_program])(ctl, val);
137 138 139 140
		} else if (midi_status() == MIDI_PITCH_BEND) {
			uint8_t lsb = data >> 8;
			uint8_t msb = data & 0xff;
			(*pitch_bend[current_program])((msb << 7) | lsb);
141
		}
Jacob Vosmaer's avatar
Jacob Vosmaer committed
142 143 144 145 146
	}

	return 0;
}