Commit 86bef6ee authored by Jacob Vosmaer's avatar Jacob Vosmaer

Add detune in mono mode

parent b7418b7b
......@@ -94,9 +94,12 @@ main(void)
uint8_t note = midi_data() >> 8;
(*note_off[current_program])(note);
} else if (midi_status() == MIDI_PROGRAM_CHANGE) {
program_change(midi_data() >> 8);
uint8_t pgm = midi_data() >> 8;
program_change(pgm);
} else if (midi_status() == MIDI_CONTROL_CHANGE) {
(*control_change[current_program])(midi_data() >> 8, midi_data() && 0xff);
uint8_t ctl = midi_data() >> 8;
uint8_t val = midi_data() & 0xff;
(*control_change[current_program])(ctl, val);
}
}
......
......@@ -22,7 +22,7 @@ const uint16_t dac_scale[NUM_VOICES] = {
};
// This tuning is chosen to be 'good enough' for the 8382-8384 scale range above
const uint16_t dac_semitones[12] = {
const int16_t dac_semitones[12] = {
0,
699,
1397,
......@@ -90,11 +90,28 @@ dac_init(void)
send_dac(0b01000000, 0b1111000000001111); // power down dacs 0, 1, 6, 7
}
#define DAC_MAX 65535
#define MIDI_LOWEST 24
uint16_t
safe_add(uint16_t x, int16_t delta)
{
if (delta < 0) {
uint16_t sub = -delta;
if (x < -delta) {
return 0;
}
return x - sub;
}
uint16_t add = delta;
if (UINT16_MAX - x < add) {
return UINT16_MAX;
}
return x + add;
}
void
dac_set_note(uint8_t voice, uint8_t note)
dac_set_note_detune(uint8_t voice, uint8_t note, int16_t detune)
{
if (voice >= NUM_VOICES) {
return;
......@@ -113,14 +130,17 @@ dac_set_note(uint8_t voice, uint8_t note)
return;
}
uint16_t data = dac_offset[voice] + octave * dac_scale[voice];
uint16_t semi_offset = dac_semitones[(note - MIDI_LOWEST) % 12];
if ((DAC_MAX - data) < semi_offset) {
data = DAC_MAX;
} else {
data += semi_offset;
}
uint16_t data = safe_add(
dac_offset[voice] + octave * dac_scale[voice],
dac_semitones[(note - MIDI_LOWEST) % 12]
);
data = safe_add(data, detune);
send_dac(0b00110000 | dac_chan[voice], data);
}
void
dac_set_note(uint8_t voice, uint8_t note)
{
dac_set_note_detune(voice, note, 0);
}
......@@ -4,6 +4,7 @@
#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_init(void);
#endif
......@@ -126,6 +126,20 @@ test_control_change(void)
midi_parse(0x34);
midi_parse(0x45);
assert_status(MIDI_CONTROL_CHANGE, 1, 0x3445);
midi_parse(0x90);
midi_parse(0x60);
midi_parse(0x64);
assert_status(MIDI_NOTE_ON, 1, 0x6064);
midi_parse(0xb0);
midi_parse(0x55);
midi_parse(0x67);
assert_status(MIDI_CONTROL_CHANGE, 1, 0x5567);
midi_parse(0x71);
midi_parse(0x62);
assert_status(MIDI_CONTROL_CHANGE, 1, 0x7162);
}
int
......
......@@ -4,6 +4,8 @@
#include "voice.h"
#include "list.h"
#include <util/delay.h>
#define NUM_NOTES 128
static uint8_t notes_array[NUM_NOTES];
static struct list notes = {
......@@ -13,10 +15,19 @@ static struct list notes = {
void set_pitch(uint8_t n);
const uint8_t detune_factor[NUM_VOICES] = {
1,
-1,
2,
-2,
};
static uint8_t detune_amount;
void
mono_init(void)
{
l_flush(&notes);
detune_amount = 0;
}
void
......@@ -38,7 +49,7 @@ void
set_pitch(uint8_t n)
{
for (uint8_t v = 0; v < NUM_VOICES; v++) {
dac_set_note(v, n);
dac_set_note_detune(v, n, (detune_factor[v] * detune_amount)/128);
}
}
......@@ -61,8 +72,16 @@ mono_note_off(uint8_t n)
set_pitch(l_first(&notes));
}
#define CC_DETUNE 14
void
mono_control_change(uint8_t ctl, uint8_t val)
{
// do nothing
if (ctl == CC_DETUNE) {
detune_amount = val;
if (!l_empty(&notes)) {
set_pitch(l_first(&notes));
}
}
}
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