#include "voice.h" #include // voicetab represents the physical hardware layout and parameters struct { struct gate gate; struct dac dac; } voicetab[] = { {.gate = {.port = &PORTC, .mask = _BV(0)}, .dac = {.channel = 2, .offset = 57, .scale = 8381}}, {.gate = {.port = &PORTC, .mask = _BV(1)}, .dac = {.channel = 3, .offset = 48, .scale = 8381}}, {.gate = {.port = &PORTC, .mask = _BV(2)}, .dac = {.channel = 4, .offset = 50, .scale = 8383}}, {.gate = {.port = &PORTC, .mask = _BV(3)}, .dac = {.channel = 5, .offset = 55, .scale = 8382}}, {.gate = {.port = &PORTD, .mask = _BV(3)}, .dac = {.channel = 0, .offset = 50, .scale = 8382}}, {.gate = {.port = &PORTD, .mask = _BV(4)}, .dac = {.channel = 1, .offset = 57, .scale = 8380}}, {.gate = {.port = &PORTD, .mask = _BV(5)}, .dac = {.channel = 7, .offset = 40, .scale = 8382}}, {.gate = {.port = &PORTD, .mask = _BV(6)}, .dac = {.channel = 6, .offset = 52, .scale = 8382}}, }; uint8_t voice_map[NUM_VOICES] = {1, 2, 3, 4, 5, 6, 7}; struct gate *gate(uint8_t v) { if (v >= NUM_VOICES) { return 0; } return &voicetab[voice_map[v]].gate; } struct dac *dac(uint8_t v) { if (v >= NUM_VOICES) { return 0; } return &voicetab[voice_map[v]].dac; } // This tuning is chosen to be 'good enough' for the 8380-8382 scale range above const int16_t dac_semitones[NUM_SEMITONES] = { 0, 698, 1397, 2095, 2794, 3492, 4191, 4889, 5587, 6286, 6984, 7683}; int16_t dac_semitone_offset(uint8_t semitone) { if (semitone >= NUM_SEMITONES) { return 0; } return dac_semitones[semitone]; }