...
 
Commits (2)
......@@ -30,6 +30,11 @@ void (*control_change[NUM_PGM])(uint8_t ctl, uint8_t val) = {
mono_control_change,
};
void (*pitch_bend[NUM_PGM])(uint16_t bend) = {
poly_pitch_bend,
mono_pitch_bend,
};
void
io_init(void)
{
......@@ -99,6 +104,10 @@ main(void)
uint8_t ctl = data >> 8;
uint8_t val = data & 0xff;
(*control_change[current_program])(ctl, val);
} else if (midi_status() == MIDI_PITCH_BEND) {
uint8_t lsb = data >> 8;
uint8_t msb = data & 0xff;
(*pitch_bend[current_program])((msb << 7) | lsb);
}
}
......
......@@ -97,7 +97,7 @@ safe_add(uint16_t x, int16_t delta)
{
if (delta < 0) {
uint16_t sub = -delta;
if (x < -delta) {
if (x < sub) {
return 0;
}
return x - sub;
......@@ -111,7 +111,7 @@ safe_add(uint16_t x, int16_t delta)
}
void
dac_set_note_detune(uint8_t voice, uint8_t note, int16_t detune)
dac_set_note2(uint8_t voice, uint8_t note, int16_t detune, uint16_t bend)
{
if (voice >= NUM_VOICES) {
return;
......@@ -136,11 +136,15 @@ dac_set_note_detune(uint8_t voice, uint8_t note, int16_t detune)
);
data = safe_add(data, detune);
float bend_factor = ((int16_t) (bend & BEND_MAX) - BEND_CENTER) / ((float) BEND_MAX);
int16_t bend_data = dac_semitones[4] * bend_factor;
data = safe_add(data, bend_data);
send_dac(0b00110000 | dac_chan[voice], data);
}
void
dac_set_note(uint8_t voice, uint8_t note)
{
dac_set_note_detune(voice, note, 0);
dac_set_note2(voice, note, 0, BEND_CENTER);
}
......@@ -4,7 +4,10 @@
#include <stdint.h>
void dac_set_note(uint8_t voice, uint8_t note);
void dac_set_note_detune(uint8_t voice, uint8_t note, int16_t detune);
void dac_set_note2(uint8_t voice, uint8_t note, int16_t detune, uint16_t bend);
void dac_init(void);
#define BEND_CENTER 8192
#define BEND_MAX 16383
#endif
......@@ -142,6 +142,33 @@ test_control_change(void)
assert_status(MIDI_CONTROL_CHANGE, 1, 0x7162);
}
void
test_pitch_bend(void)
{
desc("test pitch bend messages");
status_init();
assert_status(MIDI_NUM_STATUSES, 0, 0);
midi_parse(0xe0);
midi_parse(0x34);
midi_parse(0x45);
assert_status(MIDI_PITCH_BEND, 1, 0x3445);
midi_parse(0x90);
midi_parse(0x60);
midi_parse(0x64);
assert_status(MIDI_NOTE_ON, 1, 0x6064);
midi_parse(0xe0);
midi_parse(0x55);
midi_parse(0x67);
assert_status(MIDI_PITCH_BEND, 1, 0x5567);
midi_parse(0x71);
midi_parse(0x62);
assert_status(MIDI_PITCH_BEND, 1, 0x7162);
}
int
main(int argc, char** argv)
{
......@@ -150,6 +177,7 @@ main(int argc, char** argv)
test_note_off();
test_program_change();
test_control_change();
test_pitch_bend();
return 0;
}
......@@ -26,6 +26,7 @@ const uint8_t statuses[MIDI_NUM_STATUSES] = {
0b1000, // note off
0b1100, // program change
0b1011, // control change
0b1110, // pitch bend
};
uint8_t
......
......@@ -8,6 +8,7 @@ enum _statuses {
MIDI_NOTE_OFF,
MIDI_PROGRAM_CHANGE,
MIDI_CONTROL_CHANGE,
MIDI_PITCH_BEND,
MIDI_NUM_STATUSES,
};
......
......@@ -13,6 +13,8 @@ static struct list notes = {
.sup = NUM_NOTES,
};
static uint16_t current_bend;
void set_pitch(uint8_t n);
const uint8_t detune_factor[NUM_VOICES] = {
......@@ -28,6 +30,7 @@ mono_init(void)
{
l_flush(&notes);
detune_amount = 0;
current_bend = BEND_CENTER;
}
void
......@@ -49,7 +52,7 @@ void
set_pitch(uint8_t n)
{
for (uint8_t v = 0; v < NUM_VOICES; v++) {
dac_set_note_detune(v, n, (detune_factor[v] * detune_amount)/128);
dac_set_note2(v, n, (detune_factor[v] * detune_amount)/128, current_bend);
}
}
......@@ -85,3 +88,13 @@ mono_control_change(uint8_t ctl, uint8_t val)
}
}
}
void
mono_pitch_bend(uint16_t bend)
{
current_bend = bend;
if (!l_empty(&notes)) {
set_pitch(l_first(&notes));
}
}
......@@ -7,5 +7,6 @@ void mono_init(void);
void mono_note_on(uint8_t note);
void mono_note_off(uint8_t note);
void mono_control_change(uint8_t ctl, uint8_t val);
void mono_pitch_bend(uint16_t bend);
#endif
......@@ -41,3 +41,9 @@ poly_control_change(uint8_t ctl, uint8_t val)
{
// do nothing
}
void
poly_pitch_bend(uint16_t bend)
{
// do nothing
}
......@@ -7,5 +7,6 @@ void poly_init(void);
void poly_note_on(uint8_t note);
void poly_note_off(uint8_t note);
void poly_control_change(uint8_t ctl, uint8_t val);
void poly_pitch_bend(uint16_t bend);
#endif