Mostly Done

This commit is contained in:
Aadi Desai 2022-03-25 16:02:31 +00:00
parent f1ff21fb94
commit 61f5916730
No known key found for this signature in database
GPG key ID: CFFFE425830EF4D9

View file

@ -9,7 +9,7 @@
#pragma region Globals(Config values, Variables, Objects, Types, etc.) #pragma region Globals(Config values, Variables, Objects, Types, etc.)
// Config values // Config values
const uint32_t interval = 10; // Display update interval const uint32_t interval = 10; // Display update interval
const uint32_t samplingRate = 22000; // Sampling rate const uint32_t samplingRate = 44100; // Sampling rate
const uint32_t canID = 0x123; const uint32_t canID = 0x123;
// Variables // Variables
std::atomic<bool> isMainSynth; std::atomic<bool> isMainSynth;
@ -18,6 +18,9 @@ std::atomic<uint8_t> keyArray[7];
std::atomic<uint8_t> octave; std::atomic<uint8_t> octave;
std::atomic<uint8_t> selectedWaveform; std::atomic<uint8_t> selectedWaveform;
std::atomic<int> latestKey; std::atomic<int> latestKey;
std::atomic<int8_t> volume;
std::atomic<bool> volumeFiner;
int8_t volumeHistory = 0;
QueueHandle_t msgInQ; QueueHandle_t msgInQ;
uint8_t RX_Message[8] = {0}; uint8_t RX_Message[8] = {0};
std::atomic<bool> bufferAactive; std::atomic<bool> bufferAactive;
@ -25,12 +28,12 @@ int32_t bufferA[220];
int32_t bufferB[220]; int32_t bufferB[220];
// Objects // Objects
U8G2_SSD1305_128X32_NONAME_F_HW_I2C u8g2(U8G2_R0); // Display Driver Object U8G2_SSD1305_128X32_NONAME_F_HW_I2C u8g2(U8G2_R0); // Display Driver Object
Knob K0 = Knob(1, 7, 4); // Octave Knob Object Knob K0(1, 7, 4); // Octave Knob Object
Knob K1 = Knob(0, 3); // Waveform Knob Object Knob K1(0, 3, 1); // Waveform Knob Object
Knob K2 = Knob(0, 1); // Send / Receive Knob Object Knob K2(0, 1); // Send / Receive Knob Object
Knob K3 = Knob(0, 16); // Volume Knob Object Knob K3(0, 16); // Volume Knob Object
// Program Specific Structures // Program Specific Structures
const int32_t stepSizes[85] = {0, 6384507, 6764150, 7166367, 7592501, 8043975, 8522295, 9029057, 9565952, 10134773, 10737418, 11375898, 12052344, 12769014, 13528299, 14332734, 15185002, 16087950, 17044589, 18058113, 19131904, 20269547, 21474836, 22751797, 24104689, 25538028, 27056599, 28665468, 30370005, 32175899, 34089178, 36116226, 38263809, 40539093, 42949673, 45503593, 48209378, 51076057, 54113197, 57330935, 60740010, 64351799, 68178356, 72232452, 76527617, 81078186, 85899346, 91007187, 96418756, 102152113, 108226394, 114661870, 121480020, 128703598, 136356712, 144464904, 153055234, 162156372, 171798692, 182014374, 192837512, 204304227, 216452788, 229323741, 242960040, 257407196, 272713424, 288929808, 306110469, 324312744, 343597384, 364028747, 385675023, 408608453, 432905576, 458647482, 485920080, 514814392, 545426848, 577859616, 612220937, 648625489, 687194767, 728057495, 771350046}; const int32_t stepSizes[85] = {0, 3185014, 3374405, 3575058, 3787642, 4012867, 4251484, 4504291, 4772130, 5055895, 5356535, 5675051, 6012507, 6370029, 6748811, 7150116, 7575284, 8025734, 8502969, 9008582, 9544260, 10111791, 10713070, 11350102, 12025014, 12740059, 13497622, 14300233, 15150569, 16051469, 17005939, 18017164, 19088521, 20223583, 21426140, 22700205, 24050029, 25480118, 26995245, 28600466, 30301138, 32102938, 34011878, 36034329, 38177042, 40447167, 42852281, 45400410, 48100059, 50960237, 53990491, 57200933, 60602277, 64205876, 68023756, 72068659, 76354085, 80894335, 85704562, 90800821, 96200119, 101920475, 107980982, 114401866, 121204555, 128411753, 136047513, 144137319, 152708170, 161788670, 171409125, 181601642, 192400238, 203840951, 215961965, 228803732, 242409110, 256823506, 272095026, 288274638, 305416340, 323577341, 342818251, 363203285, 384800476};
const char *notes[85] = {"None", "C1", "C1#", "D1", "D1#", "E1", "F1", "F1#", "G1", "G1#", "A1", "A1#", "B1", "C2", "C2#", "D2", "D2#", "E2", "F2", "F2#", "G2", "G2#", "A2", "A2#", "B2", "C3", "C3#", "D3", "D3#", "E3", "F3", "F3#", "G3", "G3#", "A3", "A3#", "B3", "C4", "C4#", "D4", "D4#", "E4", "F4", "F4#", "G4", "G4#", "A4", "A4#", "B4", "C5", "C5#", "D5", "D5#", "E5", "F5", "F5#", "G5", "G5#", "A5", "A5#", "B5", "C6", "C6#", "D6", "D6#", "E6", "F6", "F6#", "G6", "G6#", "A6", "A6#", "B6", "C7", "C7#", "D7", "D7#", "E7", "F7", "F7#", "G7", "G7#", "A7", "A7#", "B7"}; const char *notes[85] = {"None", "C1", "C1#", "D1", "D1#", "E1", "F1", "F1#", "G1", "G1#", "A1", "A1#", "B1", "C2", "C2#", "D2", "D2#", "E2", "F2", "F2#", "G2", "G2#", "A2", "A2#", "B2", "C3", "C3#", "D3", "D3#", "E3", "F3", "F3#", "G3", "G3#", "A3", "A3#", "B3", "C4", "C4#", "D4", "D4#", "E4", "F4", "F4#", "G4", "G4#", "A4", "A4#", "B4", "C5", "C5#", "D5", "D5#", "E5", "F5", "F5#", "G5", "G5#", "A5", "A5#", "B5", "C6", "C6#", "D6", "D6#", "E6", "F6", "F6#", "G6", "G6#", "A6", "A6#", "B6", "C7", "C7#", "D7", "D7#", "E7", "F7", "F7#", "G7", "G7#", "A7", "A7#", "B7"};
std::atomic<bool> activeNotes[85] = {{0}}; std::atomic<bool> activeNotes[85] = {{0}};
enum waveform { enum waveform {
@ -50,22 +53,39 @@ const unsigned char waveforms[4][18] = {
0x10, 0xc0, 0x18, 0x80, 0x08, 0x80, 0x0d, 0x00, 0x07} // Sine Wave 0x10, 0xc0, 0x18, 0x80, 0x08, 0x80, 0x0d, 0x00, 0x07} // Sine Wave
}; };
const unsigned char volumes[6][18] = { const unsigned char volumes[6][18] = {
{0x10, 0x02, 0x98, 0x04, 0x1c, 0x05, 0x5f, 0x09, 0x5f, {0x10, 0x00, 0x18, 0x00, 0x5c, 0x04, 0x9f, 0x02, 0x1f,
0x09, 0x5f, 0x09, 0x1c, 0x05, 0x98, 0x04, 0x10, 0x02}, // volume max 0x01, 0x9f, 0x02, 0x5c, 0x04, 0x18, 0x00, 0x10, 0x00}, // mute
{0x10, 0x00, 0x98, 0x00, 0x1c, 0x01, 0x5f, 0x01, 0x5f,
0x01, 0x5f, 0x01, 0x1c, 0x01, 0x98, 0x00, 0x10, 0x00}, // volume mid higher
{0x10, 0x00, 0x18, 0x00, 0x1c, 0x01, 0x5f, 0x01, 0x5f,
0x01, 0x5f, 0x01, 0x1c, 0x01, 0x18, 0x00, 0x10, 0x00}, // volume mid lower
{0x10, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x5f, 0x00, 0x5f,
0x00, 0x5f, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x10, 0x00}, // volume low
{0x10, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x1f, 0x00, 0x5f, {0x10, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x1f, 0x00, 0x5f,
0x00, 0x1f, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x10, 0x00}, // volume lowest 0x00, 0x1f, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x10, 0x00}, // volume lowest
{0x10, 0x00, 0x18, 0x00, 0x5c, 0x04, 0x9f, 0x02, 0x1f, {0x10, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x5f, 0x00, 0x5f,
0x01, 0x9f, 0x02, 0x5c, 0x04, 0x18, 0x00, 0x10, 0x00} // mute 0x00, 0x5f, 0x00, 0x1c, 0x00, 0x18, 0x00, 0x10, 0x00}, // volume low
{0x10, 0x00, 0x18, 0x00, 0x1c, 0x01, 0x5f, 0x01, 0x5f,
0x01, 0x5f, 0x01, 0x1c, 0x01, 0x18, 0x00, 0x10, 0x00}, // volume mid lower
{0x10, 0x00, 0x98, 0x00, 0x1c, 0x01, 0x5f, 0x01, 0x5f,
0x01, 0x5f, 0x01, 0x1c, 0x01, 0x98, 0x00, 0x10, 0x00}, // volume mid higher
{0x10, 0x02, 0x98, 0x04, 0x1c, 0x05, 0x5f, 0x09, 0x5f,
0x09, 0x5f, 0x09, 0x1c, 0x05, 0x98, 0x04, 0x10, 0x02}, // volume max
}; };
const unsigned char icon_bits[] = { const unsigned char icon_bits[] = {
0x00, 0x00, 0x00, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x02, 0x01, 0x02, 0x01, 0xfe, 0x01, 0x00, 0x00}; 0x00, 0x00, 0x02, 0x01, 0x02, 0x01, 0xfe, 0x01, 0x00, 0x00};
const int8_t sinLUT[256] = {
0, 3, 6, 9, 12, 15, 18, 21, 24, 28, 31, 34, 37, 40, 43, 46,
48, 51, 54, 57, 60, 63, 65, 68, 71, 73, 76, 78, 81, 83, 85, 88,
90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 109, 111, 112, 114, 115, 117,
118, 119, 120, 121, 122, 123, 124, 124, 125, 126, 126, 127, 127, 127, 127, 127,
127, 127, 127, 127, 127, 127, 126, 126, 125, 124, 124, 123, 122, 121, 120, 119,
118, 117, 115, 114, 112, 111, 109, 108, 106, 104, 102, 100, 98, 96, 94, 92,
90, 88, 85, 83, 81, 78, 76, 73, 71, 68, 65, 63, 60, 57, 54, 51,
48, 46, 43, 40, 37, 34, 31, 28, 24, 21, 18, 15, 12, 9, 6, 3,
0, -4, -7, -10, -13, -16, -19, -22, -25, -29, -32, -35, -38, -41, -44, -47,
-49, -52, -55, -58, -61, -64, -66, -69, -72, -74, -77, -79, -82, -84, -86, -89,
-91, -93, -95, -97, -99, -101, -103, -105, -107, -109, -110, -112, -113, -115, -116, -118,
-119, -120, -121, -122, -123, -124, -125, -125, -126, -127, -127, -128, -128, -128, -128, -128,
-128, -128, -128, -128, -128, -128, -127, -127, -126, -125, -125, -124, -123, -122, -121, -120,
-119, -118, -116, -115, -113, -112, -110, -109, -107, -105, -103, -101, -99, -97, -95, -93,
-91, -89, -86, -84, -82, -79, -77, -74, -72, -69, -66, -64, -61, -58, -55, -52,
-49, -47, -44, -41, -38, -35, -32, -29, -25, -22, -19, -16, -13, -10, -7, -4};
#pragma endregion #pragma endregion
#pragma region Pin Definitions #pragma region Pin Definitions
@ -124,27 +144,40 @@ void setRow(const uint8_t rowIdx) {
digitalWrite(REN_PIN, HIGH); digitalWrite(REN_PIN, HIGH);
} }
// Returns key value (as stepSizes[] index) of highest currently pressed key // Scales output signal according to global volume value, to range 0-255
uint16_t getTopKey() { uint32_t scaleVolume(uint32_t Vout) {
uint16_t topKey = 0; uint32_t newVout = 0;
for (uint8_t i = 0; i < 3; i++) { if (volumeFiner) {
for (uint8_t j = 0; j < 4; j++) { newVout = (Vout * 12 * volume) >> 16;
if (keyArray[i] & (0x1 << j)) { } else { // 25 = floor( (1/10) << 8 )
topKey = (octave - 1) * 12 + i * 4 + j + 1; newVout = (Vout * 25 * volume) >> 16; // scale by 2*8 cuz 16-bit*8-bit=24-bit -> scale by 16 to get to 8
}
}
} }
return topKey; return newVout;
} }
// Interrupt driven routine to send waveform to DAC // Interrupt driven routine to send waveform to DAC
void sampleISR() { void sampleISR() {
static int32_t phaseAcc = 0; static int32_t phaseAcc = 0;
phaseAcc += currentStepSize; phaseAcc += currentStepSize;
int32_t Vout = phaseAcc >> (32 - K3.getRotation() / 2); // Volume range from (>> 32) to (>> 24), range of 8 int32_t Vout = 0;
if (selectedWaveform == SAWTOOTH) {
Vout = phaseAcc >> 16;
} else if (selectedWaveform == SQUARE) {
if (phaseAcc < 0) {
Vout = 0x00007FFF;
} else {
Vout = 0xFFFF8000;
}
} else if (selectedWaveform == TRIANGLE) {
Vout = (abs(phaseAcc) - 1073741824) >> 15;
} else if (selectedWaveform == SINE) {
Vout = (sinLUT[(uint32_t)phaseAcc >> 24]) << 8;
}
Vout = scaleVolume(Vout);
analogWrite(OUTR_PIN, Vout + 128); analogWrite(OUTR_PIN, Vout + 128);
} }
//
void CAN_RX_ISR() { void CAN_RX_ISR() {
uint8_t ISR_RX_Message[8]; uint8_t ISR_RX_Message[8];
uint32_t ISR_rxID; uint32_t ISR_rxID;
@ -152,26 +185,7 @@ void CAN_RX_ISR() {
xQueueSendFromISR(msgInQ, ISR_RX_Message, nullptr); xQueueSendFromISR(msgInQ, ISR_RX_Message, nullptr);
} }
void generateWaveformBufferTask(void *pvParameters) { // Task to update activeNotes[] and currentStepSize based on received CAN message
const TickType_t xFrequency = 50 / portTICK_PERIOD_MS;
TickType_t xLastWakeTime = xTaskGetTickCount();
static int32_t waveformBuffers[85][220] = {0};
while (1) {
vTaskDelayUntil(&xLastWakeTime, xFrequency);
// Generate waveforms and write to buffers
int32_t nextBuffer[220] = {0};
// Combine waveforms into nextBuffer waveform
// Write waveform to inactive buffer
for (uint8_t i = 0; i < 220; i++) {
if (bufferAactive) {
bufferB[i] = nextBuffer[i];
} else {
bufferA[i] = nextBuffer[i];
}
}
}
}
void decodeTask(void *pvParameters) { void decodeTask(void *pvParameters) {
while (1) { while (1) {
xQueueReceive(msgInQ, RX_Message, portMAX_DELAY); xQueueReceive(msgInQ, RX_Message, portMAX_DELAY);
@ -189,6 +203,7 @@ void decodeTask(void *pvParameters) {
} }
} }
//
void keyChangedSendTXMessage(uint8_t octave, uint8_t key, bool pressed) { void keyChangedSendTXMessage(uint8_t octave, uint8_t key, bool pressed) {
uint8_t TX_Message[8] = {0}; uint8_t TX_Message[8] = {0};
if (pressed) { if (pressed) {
@ -225,10 +240,21 @@ void scanKeysTask(void *pvParameters) {
} }
} }
} }
if (volumeFiner) {
K3.changeLimitsVolume(0, 10);
} else {
K3.changeLimitsVolume(0, 5);
}
K0.updateRotation(keyArray[4] & 0x4, keyArray[4] & 0x8); K0.updateRotation(keyArray[4] & 0x4, keyArray[4] & 0x8);
K1.updateRotation(keyArray[4] & 0x1, keyArray[4] & 0x2); K1.updateRotation(keyArray[4] & 0x1, keyArray[4] & 0x2);
K2.updateRotation(keyArray[3] & 0x4, keyArray[3] & 0x8); K2.updateRotation(keyArray[3] & 0x4, keyArray[3] & 0x8);
K3.updateRotation(keyArray[3] & 0x1, keyArray[3] & 0x2); K3.updateRotation(keyArray[3] & 0x1, keyArray[3] & 0x2);
octave = K0.getRotation();
selectedWaveform = K1.getRotation();
isMainSynth = !K2.getRotation();
volume = K3.getRotation();
volumeHistory = (volumeHistory << 1) + ((keyArray[5] & 0x2) >> 1);
volumeFiner = ((!(volumeHistory == 1)) & volumeFiner) | ((volumeHistory == 1) & !volumeFiner);
} }
} }
@ -238,25 +264,23 @@ void displayUpdateTask(void *pvParameters) {
TickType_t xLastWakeTime = xTaskGetTickCount(); TickType_t xLastWakeTime = xTaskGetTickCount();
while (1) { while (1) {
vTaskDelayUntil(&xLastWakeTime, xFrequency); vTaskDelayUntil(&xLastWakeTime, xFrequency);
uint32_t rxID; u8g2.clearBuffer(); // clear the internal memory
u8g2.clearBuffer(); // clear the internal memory u8g2.setFont(u8g2_font_profont12_mf); // choose a suitable font
u8g2.setFont(u8g2_font_profont12_mf); // choose a suitable font u8g2.drawStr(2, 10, notes[latestKey]); // Print the currently pressed keys
char currentKeys[64] = {0};
for (uint8_t i = 0; i < 85; i++) { // u8g2.setCursor(2, 20);
if (activeNotes[i]) { // for (uint8_t i = 0; i < 7; i++) {
strcat(currentKeys, notes[i]); // u8g2.print(keyArray[i], HEX);
strcat(currentKeys, " "); // };
} // u8g2.setCursor(100, 10); // Debug print of received CAN message
} // u8g2.print((char)RX_Message[0]);
u8g2.drawStr(2, 10, currentKeys); // Print the currently pressed keys // u8g2.print(RX_Message[1]);
u8g2.setCursor(2, 20); // u8g2.print(RX_Message[2], HEX);
for (uint8_t i = 0; i < 7; i++) {
u8g2.print(keyArray[i], HEX); // Print current octave number above knob 0
}; u8g2.drawStr(2, 30, "O:");
u8g2.setCursor(100, 10); // Debug print of received CAN message u8g2.setCursor(14, 30);
u8g2.print((char)RX_Message[0]); u8g2.print(octave);
u8g2.print(RX_Message[1]);
u8g2.print(RX_Message[2], HEX);
// Draw currently selected waveform above knob 1 // Draw currently selected waveform above knob 1
u8g2.drawXBM(38, 22, 13, 9, waveforms[K1.getRotation()]); u8g2.drawXBM(38, 22, 13, 9, waveforms[K1.getRotation()]);
@ -268,12 +292,16 @@ void displayUpdateTask(void *pvParameters) {
u8g2.drawStr(74, 30, "RECV"); u8g2.drawStr(74, 30, "RECV");
} }
// Print currently selected volume level above knob 3 // Print volume indicator above knob 3
u8g2.setCursor(116, 30); if (!volumeFiner) {
u8g2.print(K3.getRotation()); u8g2.drawXBM(116, 22, 13, 9, volumes[volume]);
} else {
u8g2.setCursor(117, 30);
u8g2.print(volume);
}
u8g2.sendBuffer(); // transfer internal memory to the display u8g2.sendBuffer(); // transfer internal memory to the display
digitalToggle(LED_BUILTIN); digitalToggle(LED_BUILTIN); // Toggle LED to show display update rate
} }
} }