From 1223947839e174210a73c9b4e9d2889a567b1b19 Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 23 Mar 2022 14:24:31 +0000 Subject: [PATCH 01/13] Finished P1S3, strating P1S4 --- src/main.cpp | 86 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 29 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 593349b..f27d24b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,8 +3,24 @@ #include #include +volatile int32_t currentStepSize; +volatile uint8_t keyArray[7]; +volatile uint8_t *keyArrayPtr = keyArray; + #pragma region Config Values -const uint32_t interval = 10; // Display update interval +const uint32_t interval = 10; // Display update interval +const uint8_t octave = 4; // Octave to start on +const uint32_t samplingRate = 44100; // Sampling rate +const int32_t stepSizes[] = {0, + 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, 12841175, 136047513, 144137319, 152708170, + 161788670, 171409125, 181601642, 192400238}; // Step sizes for each note #pragma endregion #pragma region Pin Definitions @@ -46,25 +62,6 @@ void setOutMuxBit(const uint8_t bitIdx, const bool value) { digitalWrite(REN_PIN, LOW); } -// Function to read keys from key matrix -uint32_t readKeys() { - uint32_t keys = 0; - for (uint8_t i = 0; i < 3; i++) { - digitalWrite(REN_PIN, LOW); - digitalWrite(RA0_PIN, i & 0x01); - digitalWrite(RA1_PIN, i & 0x02); - digitalWrite(RA2_PIN, i & 0x04); - digitalWrite(REN_PIN, HIGH); - delayMicroseconds(5); - keys |= !digitalRead(C0_PIN) << (i * 4); - keys |= !digitalRead(C1_PIN) << (i * 4 + 1); - keys |= !digitalRead(C2_PIN) << (i * 4 + 2); - keys |= !digitalRead(C3_PIN) << (i * 4 + 3); - } - digitalWrite(REN_PIN, LOW); - return keys; -} - // Read key values in currently set row uint8_t readCols() { uint8_t row = 0; @@ -84,6 +81,35 @@ void setRow(const uint8_t rowIdx) { digitalWrite(REN_PIN, HIGH); } +uint16_t getTopKey(volatile uint8_t array[]) { + uint16_t topKey = 0; + for (uint8_t i = 0; i < 3; i++) { + for (uint8_t j = 0; j < 4; j++) { + if (array[i] & (0x1 << j)) { + topKey = (octave - 2) * 12 + i * 4 + j + 1; + } + } + } + Serial.println(topKey); + return topKey; +} + +void sampleISR(){ + static int32_t phaseAcc = 0; + phaseAcc += currentStepSize; + int32_t Vout = phaseAcc >> 24; + analogWrite(OUTR_PIN, Vout + 128); +} + +void scanKeysTask(void * pvParameters){ + for (uint8_t i = 0; i < 3; i++) { + setRow(i); + delayMicroseconds(3); + keyArray[i] = readCols(); + } + __atomic_store_n(¤tStepSize, stepSizes[getTopKey(keyArray)], __ATOMIC_RELAXED); +} + void setup() { #pragma region Pin Setup pinMode(RA0_PIN, OUTPUT); @@ -112,16 +138,16 @@ void setup() { // Initialise UART Serial.begin(115200); Serial.println("Hello World"); + + TIM_TypeDef *Instance = TIM1; + HardwareTimer *sampleTimer = new HardwareTimer(Instance); + sampleTimer->setOverflow(samplingRate, HERTZ_FORMAT); + sampleTimer->attachInterrupt(sampleISR); + sampleTimer->resume(); } void loop() { static uint32_t next = millis(); - static uint8_t keyArray[7]; - for (uint8_t i = 0; i < 3; i++) { - setRow(i); - delayMicroseconds(3); - keyArray[i] = readCols(); - } for (uint8_t i = 3; i < 7; i++) { setRow(i); delayMicroseconds(3); @@ -130,9 +156,11 @@ void loop() { if (millis() > next) { next += interval; - u8g2.clearBuffer(); // clear the internal memory - u8g2.setFont(u8g2_font_profont12_mf); // choose a suitable font - u8g2.drawStr(2, 10, "Hello World!"); // write something to the internal memory + u8g2.clearBuffer(); // clear the internal memory + u8g2.setFont(u8g2_font_profont12_mf); // choose a suitable font + u8g2.setCursor(2, 10); // set the cursor position + scanKeysTask(NULL); + u8g2.print(currentStepSize); // Print the current frequency digitalToggle(LED_BUILTIN); u8g2.setCursor(2, 20); for (uint8_t i = 0; i < 7; i++) { From 65033439bdf4cdadf67db5ed4f6770e76ca9fc59 Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 23 Mar 2022 14:43:09 +0000 Subject: [PATCH 02/13] P1 complete --- platformio.ini | 3 +- src/main.cpp | 78 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 54 insertions(+), 27 deletions(-) diff --git a/platformio.ini b/platformio.ini index cd3edda..d545dc8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,5 +13,6 @@ platform = ststm32 board = nucleo_l432kc framework = arduino monitor_speed = 115200 -lib_deps = +lib_deps = olikraus/U8g2@^2.32.10 + stm32duino/STM32duino FreeRTOS@^10.3.1 diff --git a/src/main.cpp b/src/main.cpp index f27d24b..288472f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,7 @@ #include #include +#include volatile int32_t currentStepSize; volatile uint8_t keyArray[7]; @@ -90,7 +91,6 @@ uint16_t getTopKey(volatile uint8_t array[]) { } } } - Serial.println(topKey); return topKey; } @@ -102,12 +102,40 @@ void sampleISR(){ } void scanKeysTask(void * pvParameters){ - for (uint8_t i = 0; i < 3; i++) { + const TickType_t xFrequency = 50/portTICK_PERIOD_MS; + TickType_t xLastWakeTime = xTaskGetTickCount(); + while(1){ + vTaskDelayUntil(&xLastWakeTime, xFrequency); + for (uint8_t i = 0; i < 3; i++) { + setRow(i); + delayMicroseconds(3); + keyArray[i] = readCols(); + } + for (uint8_t i = 3; i < 7; i++) { setRow(i); delayMicroseconds(3); keyArray[i] = readCols(); } - __atomic_store_n(¤tStepSize, stepSizes[getTopKey(keyArray)], __ATOMIC_RELAXED); + __atomic_store_n(¤tStepSize, stepSizes[getTopKey(keyArray)], __ATOMIC_RELAXED); + } +} + +void displayUpdateTask(void * pvParameters){ + const TickType_t xFrequency = 100/portTICK_PERIOD_MS; + TickType_t xLastWakeTime = xTaskGetTickCount(); + while(1){ + vTaskDelayUntil(&xLastWakeTime, xFrequency); + u8g2.clearBuffer(); // clear the internal memory + u8g2.setFont(u8g2_font_profont12_mf); // choose a suitable font + u8g2.setCursor(2, 10); // set the cursor position + u8g2.print(currentStepSize); // Print the current frequency + digitalToggle(LED_BUILTIN); + u8g2.setCursor(2, 20); + for (uint8_t i = 0; i < 7; i++) { + u8g2.print(keyArray[i], HEX); + } + u8g2.sendBuffer(); // transfer internal memory to the display + } } void setup() { @@ -144,28 +172,26 @@ void setup() { sampleTimer->setOverflow(samplingRate, HERTZ_FORMAT); sampleTimer->attachInterrupt(sampleISR); sampleTimer->resume(); + + TaskHandle_t scanKeysHandle = NULL; + TaskHandle_t displayUpdateHandle = NULL; + xTaskCreate( + scanKeysTask, /* Function that implements the task */ + "scanKeys", /* Text name for the task */ + 64, /* Stack size in words, not bytes */ + NULL, /* Parameter passed into the task */ + 2, /* Task priority */ + &scanKeysHandle /* Pointer to store the task handle */ + ); + xTaskCreate( + displayUpdateTask, /* Function that implements the task */ + "displayUpdate", /* Text name for the task */ + 256, /* Stack size in words, not bytes */ + NULL, /* Parameter passed into the task */ + 1, /* Task priority */ + &displayUpdateHandle /* Pointer to store the task handle */ + ); + vTaskStartScheduler(); } -void loop() { - static uint32_t next = millis(); - for (uint8_t i = 3; i < 7; i++) { - setRow(i); - delayMicroseconds(3); - keyArray[i] = readCols(); - } - - if (millis() > next) { - next += interval; - u8g2.clearBuffer(); // clear the internal memory - u8g2.setFont(u8g2_font_profont12_mf); // choose a suitable font - u8g2.setCursor(2, 10); // set the cursor position - scanKeysTask(NULL); - u8g2.print(currentStepSize); // Print the current frequency - digitalToggle(LED_BUILTIN); - u8g2.setCursor(2, 20); - for (uint8_t i = 0; i < 7; i++) { - u8g2.print(keyArray[i], HEX); - } - u8g2.sendBuffer(); // transfer internal memory to the display - } -} \ No newline at end of file +void loop() {} \ No newline at end of file From 5b0661e77fa03e0e05017048727541d40449865e Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 23 Mar 2022 15:24:26 +0000 Subject: [PATCH 03/13] P2S5 done --- src/main.cpp | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 288472f..5e70a26 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ volatile int32_t currentStepSize; volatile uint8_t keyArray[7]; -volatile uint8_t *keyArrayPtr = keyArray; +SemaphoreHandle_t keyArrayMutex; #pragma region Config Values const uint32_t interval = 10; // Display update interval @@ -23,7 +23,6 @@ const int32_t stepSizes[] = {0, 107980982, 114401866, 121204555, 12841175, 136047513, 144137319, 152708170, 161788670, 171409125, 181601642, 192400238}; // Step sizes for each note #pragma endregion - #pragma region Pin Definitions // Row select and enable const int RA0_PIN = D3; @@ -102,21 +101,23 @@ void sampleISR(){ } void scanKeysTask(void * pvParameters){ + uint8_t keyArrayCopy[7]; const TickType_t xFrequency = 50/portTICK_PERIOD_MS; TickType_t xLastWakeTime = xTaskGetTickCount(); while(1){ vTaskDelayUntil(&xLastWakeTime, xFrequency); - for (uint8_t i = 0; i < 3; i++) { + xSemaphoreTake(keyArrayMutex, portMAX_DELAY); + memcpy(keyArrayCopy, (void*)keyArray, 7); + xSemaphoreGive(keyArrayMutex); + for (uint8_t i = 0; i < 7; i++) { setRow(i); delayMicroseconds(3); - keyArray[i] = readCols(); + keyArrayCopy[i] = readCols(); } - for (uint8_t i = 3; i < 7; i++) { - setRow(i); - delayMicroseconds(3); - keyArray[i] = readCols(); - } - __atomic_store_n(¤tStepSize, stepSizes[getTopKey(keyArray)], __ATOMIC_RELAXED); + xSemaphoreTake(keyArrayMutex, portMAX_DELAY); + memcpy((void*)keyArray, keyArrayCopy, 7); + xSemaphoreGive(keyArrayMutex); + __atomic_store_n(¤tStepSize, stepSizes[getTopKey(keyArrayCopy)], __ATOMIC_RELAXED); } } @@ -191,6 +192,9 @@ void setup() { 1, /* Task priority */ &displayUpdateHandle /* Pointer to store the task handle */ ); + + keyArrayMutex = xSemaphoreCreateMutex(); + vTaskStartScheduler(); } From 84e3b8f27f1f2eb70b0284fdada5b8cfa65a1f8e Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 23 Mar 2022 15:51:52 +0000 Subject: [PATCH 04/13] P2S5 complete --- src/main.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 5e70a26..ce92b58 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -122,10 +122,16 @@ void scanKeysTask(void * pvParameters){ } void displayUpdateTask(void * pvParameters){ + uint8_t keyArrayCopy[7]; const TickType_t xFrequency = 100/portTICK_PERIOD_MS; TickType_t xLastWakeTime = xTaskGetTickCount(); while(1){ vTaskDelayUntil(&xLastWakeTime, xFrequency); + + xSemaphoreTake(keyArrayMutex, portMAX_DELAY); + memcpy(keyArrayCopy, (void*)keyArray, 7); + xSemaphoreGive(keyArrayMutex); + u8g2.clearBuffer(); // clear the internal memory u8g2.setFont(u8g2_font_profont12_mf); // choose a suitable font u8g2.setCursor(2, 10); // set the cursor position @@ -133,8 +139,11 @@ void displayUpdateTask(void * pvParameters){ digitalToggle(LED_BUILTIN); u8g2.setCursor(2, 20); for (uint8_t i = 0; i < 7; i++) { - u8g2.print(keyArray[i], HEX); + u8g2.print(keyArrayCopy[6-i], HEX); } + u8g2.drawStr(120,30,"+"); + u8g2.drawStr(85,30,"-"); + //u8g2.drawStr(100,30,"hi"); u8g2.sendBuffer(); // transfer internal memory to the display } } From e2252d0b27eaac521986b6adc58b0965f7c32ac1 Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 23 Mar 2022 20:12:15 +0000 Subject: [PATCH 05/13] Added fun icons --- src/knob.cpp | 44 ++++++++++++++++++++++++++++++ src/knob.h | 19 +++++++++++++ src/main.cpp | 75 +++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 129 insertions(+), 9 deletions(-) create mode 100644 src/knob.cpp create mode 100644 src/knob.h diff --git a/src/knob.cpp b/src/knob.cpp new file mode 100644 index 0000000..a776891 --- /dev/null +++ b/src/knob.cpp @@ -0,0 +1,44 @@ +#include "knob.h" + +Knob::Knob(int minimum, int maximum) { + Knob::minimum = minimum; + Knob::maximum = maximum; + Knob::A = false; + Knob::B = false; + Knob::rotPlusOnePrev = false; + Knob::rotMinOnePrev = false; + Knob::rotation = 0; +} + +int Knob::getRotation() { + return Knob::rotation; +}; + +void Knob::updateRotation(bool ANew, bool BNew) { + bool rotPlusOneNew = (!B && !A && !BNew && ANew) || + (!B && A && BNew && ANew) || + (B && !A && !BNew && !ANew) || + (B && A && BNew && !ANew); + + bool rotMinOneNew = (!B && !A && BNew && !ANew) || + (!B && A && !BNew && !ANew) || + (B && !A && BNew && ANew) || + (B && A && !BNew && ANew); + + bool impossibleState = (!B && !A && BNew && ANew) || + (!B && A && BNew && !ANew) || + (B && !A && !BNew && ANew) || + (B && A && !BNew && !ANew); + + if (rotPlusOneNew || (impossibleState && rotPlusOnePrev)) rotation += 1; + if (rotMinOneNew || (impossibleState && rotMinOnePrev)) rotation -= 1; + if (rotation < minimum) rotation = minimum; + if (rotation > maximum) rotation = maximum; + + A = ANew; + B = BNew; + if (!impossibleState) { + rotPlusOnePrev = rotPlusOneNew; + rotMinOnePrev = rotMinOneNew; + } +} \ No newline at end of file diff --git a/src/knob.h b/src/knob.h new file mode 100644 index 0000000..054fadb --- /dev/null +++ b/src/knob.h @@ -0,0 +1,19 @@ +#ifndef KNOB_H +#define KNOB_H + +class Knob { +private: + int rotation; + int minimum, maximum; + bool A, B; + bool rotPlusOnePrev, rotMinOnePrev; + +public: + Knob(int minimum, int max); + + int getRotation(); + + void updateRotation(bool ANew, bool BNew); +}; + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index ce92b58..f50c0a7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,17 +3,22 @@ #include #include #include +#include "knob.h" volatile int32_t currentStepSize; volatile uint8_t keyArray[7]; SemaphoreHandle_t keyArrayMutex; +Knob K1(0,6); +Knob K3(0,10); +enum wave{SQR=0,SAW,TRI,SIN}; + #pragma region Config Values const uint32_t interval = 10; // Display update interval const uint8_t octave = 4; // Octave to start on const uint32_t samplingRate = 44100; // Sampling rate -const int32_t stepSizes[] = {0, - 6370029, 6748811, 7150116, 7575284, 8025734, 8502969, 9008582, +const int32_t stepSizes[] = { + 0, 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, @@ -22,6 +27,30 @@ const int32_t stepSizes[] = {0, 72068659, 76354085, 80894335, 85704562, 90800821, 96200119, 101920475, 107980982, 114401866, 121204555, 12841175, 136047513, 144137319, 152708170, 161788670, 171409125, 181601642, 192400238}; // Step sizes for each note +static unsigned char waveforms[4][18] = { + {0x7f, 0x10, 0x41, 0x10, 0x41, 0x10, 0x41, 0x10, 0x41, 0x10, 0x41, 0x10, + 0x41, 0x10, 0x41, 0x10, 0xc1, 0x1f}, //square wave + {0x70, 0x10, 0x58, 0x18, 0x48, 0x08, 0x4c, 0x0c, 0x44, 0x04, 0x46, 0x06, + 0x42, 0x02, 0x43, 0x03, 0xc1, 0x01}, //sawtooth wave + {0x08, 0x00, 0x1c, 0x00, 0x36, 0x00, 0x63, 0x00, 0xc1, 0x00, 0x80, 0x11, + 0x00, 0x1b, 0x00, 0x0e, 0x00, 0x04}, //triange wave + {0x1c, 0x00, 0x36, 0x00, 0x22, 0x00, 0x63, 0x00, 0x41, 0x10, 0xc0, 0x18, + 0x80, 0x08, 0x80, 0x0d, 0x00, 0x07} //sine wave +}; +static unsigned char volumes[6][18] = { + {0x10, 0x02, 0x98, 0x04, 0x1c, 0x05, 0x5f, 0x09, 0x5f, 0x09, 0x5f, 0x09, + 0x1c, 0x05, 0x98, 0x04, 0x10, 0x02 }, //volume max + {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, 0x00, 0x1f, 0x00, + 0x1c, 0x00, 0x18, 0x00, 0x10, 0x00 }, //volume lowest + {0x10, 0x00, 0x18, 0x00, 0x5c, 0x04, 0x9f, 0x02, 0x1f, 0x01, 0x9f, 0x02, + 0x5c, 0x04, 0x18, 0x00, 0x10, 0x00} //mute +}; #pragma endregion #pragma region Pin Definitions // Row select and enable @@ -106,9 +135,6 @@ void scanKeysTask(void * pvParameters){ TickType_t xLastWakeTime = xTaskGetTickCount(); while(1){ vTaskDelayUntil(&xLastWakeTime, xFrequency); - xSemaphoreTake(keyArrayMutex, portMAX_DELAY); - memcpy(keyArrayCopy, (void*)keyArray, 7); - xSemaphoreGive(keyArrayMutex); for (uint8_t i = 0; i < 7; i++) { setRow(i); delayMicroseconds(3); @@ -117,7 +143,10 @@ void scanKeysTask(void * pvParameters){ xSemaphoreTake(keyArrayMutex, portMAX_DELAY); memcpy((void*)keyArray, keyArrayCopy, 7); xSemaphoreGive(keyArrayMutex); + digitalToggle(LED_BUILTIN); __atomic_store_n(¤tStepSize, stepSizes[getTopKey(keyArrayCopy)], __ATOMIC_RELAXED); + K1.updateRotation(keyArrayCopy[4] & 0x1, keyArrayCopy[4] & 0x2); + K3.updateRotation(keyArrayCopy[3] & 0x1, keyArrayCopy[3] & 0x2); } } @@ -136,14 +165,42 @@ void displayUpdateTask(void * pvParameters){ u8g2.setFont(u8g2_font_profont12_mf); // choose a suitable font u8g2.setCursor(2, 10); // set the cursor position u8g2.print(currentStepSize); // Print the current frequency - digitalToggle(LED_BUILTIN); + //digitalToggle(LED_BUILTIN); u8g2.setCursor(2, 20); for (uint8_t i = 0; i < 7; i++) { u8g2.print(keyArrayCopy[6-i], HEX); } - u8g2.drawStr(120,30,"+"); - u8g2.drawStr(85,30,"-"); - //u8g2.drawStr(100,30,"hi"); + // Print waveform icon + int K1_rot = K1.getRotation(); + if(K1_rot<2){ + u8g2.drawXBM(38,22,13,9,waveforms[SQR]); + }else if(K1_rot<4){ + u8g2.drawXBM(38,22,13,9,waveforms[SAW]); + }else if(K1_rot<6){ + u8g2.drawXBM(38,22,13,9,waveforms[TRI]); + }else if(K1_rot==6){ + u8g2.drawXBM(38,22,13,9,waveforms[SIN]); + }; + u8g2.setCursor(2, 30); + u8g2.print("O:"); + u8g2.setCursor(14, 30); + u8g2.print(octave); + + // Print volume indicator and bar + int K3_rot = K3.getRotation(); + if(K3_rot==0){ + u8g2.drawXBM(116,22,13,9,volumes[5]); + }else if(K3_rot<3){ + u8g2.drawXBM(116,22,13,9,volumes[4]); + }else if(K3_rot<5){ + u8g2.drawXBM(116,22,13,9,volumes[3]); + }else if(K3_rot<7){ + u8g2.drawXBM(116,22,13,9,volumes[2]); + }else if(K3_rot<9){ + u8g2.drawXBM(116,22,13,9,volumes[1]); + }else if(K3_rot<11){ + u8g2.drawXBM(116,22,13,9,volumes[0]); + }; u8g2.sendBuffer(); // transfer internal memory to the display } } From 483b87e2164af5d42722421c3a5a177c9c911193 Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 23 Mar 2022 21:15:40 +0000 Subject: [PATCH 06/13] Added volume control --- src/main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index f50c0a7..f9e23a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -7,6 +7,7 @@ volatile int32_t currentStepSize; volatile uint8_t keyArray[7]; +volatile int8_t volume; SemaphoreHandle_t keyArrayMutex; Knob K1(0,6); Knob K3(0,10); @@ -17,6 +18,7 @@ enum wave{SQR=0,SAW,TRI,SIN}; const uint32_t interval = 10; // Display update interval const uint8_t octave = 4; // Octave to start on const uint32_t samplingRate = 44100; // Sampling rate +const int8_t volumeMax = 10; const int32_t stepSizes[] = { 0, 6370029, 6748811, 7150116, 7575284, 8025734, 8502969, 9008582, 9544260, 10111791, 10713070, 11350102, 12025014, 12740059, 13497622, @@ -125,7 +127,8 @@ uint16_t getTopKey(volatile uint8_t array[]) { void sampleISR(){ static int32_t phaseAcc = 0; phaseAcc += currentStepSize; - int32_t Vout = phaseAcc >> 24; + int32_t Vout = (phaseAcc >> 16)*25*volume; + Vout = Vout >> 16; analogWrite(OUTR_PIN, Vout + 128); } @@ -147,6 +150,7 @@ void scanKeysTask(void * pvParameters){ __atomic_store_n(¤tStepSize, stepSizes[getTopKey(keyArrayCopy)], __ATOMIC_RELAXED); K1.updateRotation(keyArrayCopy[4] & 0x1, keyArrayCopy[4] & 0x2); K3.updateRotation(keyArrayCopy[3] & 0x1, keyArrayCopy[3] & 0x2); + __atomic_store_n(&volume, K3.getRotation(), __ATOMIC_RELAXED); } } @@ -181,6 +185,8 @@ void displayUpdateTask(void * pvParameters){ }else if(K1_rot==6){ u8g2.drawXBM(38,22,13,9,waveforms[SIN]); }; + + // Print octave number u8g2.setCursor(2, 30); u8g2.print("O:"); u8g2.setCursor(14, 30); From 555579da53b58ab443c0907239ba47d861ab39a4 Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 23 Mar 2022 22:26:20 +0000 Subject: [PATCH 07/13] Added coarse and fine volume control --- src/knob.cpp | 12 +++++++++++- src/knob.h | 2 ++ src/main.cpp | 52 +++++++++++++++++++++++++++++++++++----------------- 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/src/knob.cpp b/src/knob.cpp index a776891..cd24604 100644 --- a/src/knob.cpp +++ b/src/knob.cpp @@ -41,4 +41,14 @@ void Knob::updateRotation(bool ANew, bool BNew) { rotPlusOnePrev = rotPlusOneNew; rotMinOnePrev = rotMinOneNew; } -} \ No newline at end of file +}; + +void Knob::changeLimitsVolume(int newMinimum, int newMaximum) { + if(newMaximum>maximum){ + rotation = rotation<<1; + }else if(newMaximum>1; + }else{} + minimum = newMinimum; + maximum = newMaximum; +}; \ No newline at end of file diff --git a/src/knob.h b/src/knob.h index 054fadb..be39ce9 100644 --- a/src/knob.h +++ b/src/knob.h @@ -14,6 +14,8 @@ public: int getRotation(); void updateRotation(bool ANew, bool BNew); + + void changeLimitsVolume(int newMinimum, int newMaximum); }; #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index f9e23a9..326546f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,6 +8,8 @@ volatile int32_t currentStepSize; volatile uint8_t keyArray[7]; volatile int8_t volume; +volatile bool volumeFiner; +int8_t volumeHistory = 0; SemaphoreHandle_t keyArrayMutex; Knob K1(0,6); Knob K3(0,10); @@ -18,7 +20,6 @@ enum wave{SQR=0,SAW,TRI,SIN}; const uint32_t interval = 10; // Display update interval const uint8_t octave = 4; // Octave to start on const uint32_t samplingRate = 44100; // Sampling rate -const int8_t volumeMax = 10; const int32_t stepSizes[] = { 0, 6370029, 6748811, 7150116, 7575284, 8025734, 8502969, 9008582, 9544260, 10111791, 10713070, 11350102, 12025014, 12740059, 13497622, @@ -127,13 +128,18 @@ uint16_t getTopKey(volatile uint8_t array[]) { void sampleISR(){ static int32_t phaseAcc = 0; phaseAcc += currentStepSize; - int32_t Vout = (phaseAcc >> 16)*25*volume; - Vout = Vout >> 16; + int32_t Vout = phaseAcc >> 16; + if(volumeFiner){ + Vout = (Vout*12*volume) >> 16; + }else{ // 25 = floor( (1/10) << 8 ) + Vout = (Vout*25*volume) >> 16; //scale by 2*8 cuz 16-bit*8-bit=24-bit -> scale by 16 to get to 8 + } analogWrite(OUTR_PIN, Vout + 128); } void scanKeysTask(void * pvParameters){ uint8_t keyArrayCopy[7]; + bool volumeFinerNext; const TickType_t xFrequency = 50/portTICK_PERIOD_MS; TickType_t xLastWakeTime = xTaskGetTickCount(); while(1){ @@ -149,8 +155,16 @@ void scanKeysTask(void * pvParameters){ digitalToggle(LED_BUILTIN); __atomic_store_n(¤tStepSize, stepSizes[getTopKey(keyArrayCopy)], __ATOMIC_RELAXED); K1.updateRotation(keyArrayCopy[4] & 0x1, keyArrayCopy[4] & 0x2); + if(volumeFiner){ + K3.changeLimitsVolume(0,20); + }else{ + K3.changeLimitsVolume(0,10); + } K3.updateRotation(keyArrayCopy[3] & 0x1, keyArrayCopy[3] & 0x2); __atomic_store_n(&volume, K3.getRotation(), __ATOMIC_RELAXED); + volumeHistory = (volumeHistory << 1) + ((keyArrayCopy[5]&0x2)>>1); + volumeFinerNext = ((!(volumeHistory==1))&volumeFiner) | ((volumeHistory==1)&!volumeFiner); + __atomic_store_n(&volumeFiner, volumeFinerNext, __ATOMIC_RELAXED); } } @@ -192,20 +206,24 @@ void displayUpdateTask(void * pvParameters){ u8g2.setCursor(14, 30); u8g2.print(octave); - // Print volume indicator and bar - int K3_rot = K3.getRotation(); - if(K3_rot==0){ - u8g2.drawXBM(116,22,13,9,volumes[5]); - }else if(K3_rot<3){ - u8g2.drawXBM(116,22,13,9,volumes[4]); - }else if(K3_rot<5){ - u8g2.drawXBM(116,22,13,9,volumes[3]); - }else if(K3_rot<7){ - u8g2.drawXBM(116,22,13,9,volumes[2]); - }else if(K3_rot<9){ - u8g2.drawXBM(116,22,13,9,volumes[1]); - }else if(K3_rot<11){ - u8g2.drawXBM(116,22,13,9,volumes[0]); + // Print volume indicator + if(!volumeFiner){ + if(volume==0){ + u8g2.drawXBM(116,22,13,9,volumes[5]); + }else if(volume<3){ + u8g2.drawXBM(116,22,13,9,volumes[4]); + }else if(volume<5){ + u8g2.drawXBM(116,22,13,9,volumes[3]); + }else if(volume<7){ + u8g2.drawXBM(116,22,13,9,volumes[2]); + }else if(volume<9){ + u8g2.drawXBM(116,22,13,9,volumes[1]); + }else if(volume<11){ + u8g2.drawXBM(116,22,13,9,volumes[0]); + }; + }else{ + u8g2.setCursor(122, 30); + u8g2.print(volume/2); }; u8g2.sendBuffer(); // transfer internal memory to the display } From d30170137b2afe9d436fdf40e76886f6a4c8cf4b Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 23 Mar 2022 22:32:48 +0000 Subject: [PATCH 08/13] Finished finer volume control --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 326546f..0c186a5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -222,7 +222,7 @@ void displayUpdateTask(void * pvParameters){ u8g2.drawXBM(116,22,13,9,volumes[0]); }; }else{ - u8g2.setCursor(122, 30); + u8g2.setCursor(117, 30); u8g2.print(volume/2); }; u8g2.sendBuffer(); // transfer internal memory to the display From a8f6e72473dcfa23133daa2a437006b4134c8f8a Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 23 Mar 2022 23:13:48 +0000 Subject: [PATCH 09/13] Added square wave --- src/main.cpp | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 0c186a5..37c078e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,11 +9,12 @@ volatile int32_t currentStepSize; volatile uint8_t keyArray[7]; volatile int8_t volume; volatile bool volumeFiner; +volatile int8_t wave; int8_t volumeHistory = 0; SemaphoreHandle_t keyArrayMutex; Knob K1(0,6); Knob K3(0,10); -enum wave{SQR=0,SAW,TRI,SIN}; +enum waves{SQUARE=0,SAWTOOTH,TRIANGLE,SINE}; #pragma region Config Values @@ -128,7 +129,16 @@ uint16_t getTopKey(volatile uint8_t array[]) { void sampleISR(){ static int32_t phaseAcc = 0; phaseAcc += currentStepSize; - int32_t Vout = phaseAcc >> 16; + int32_t Vout = 0; + if(wave==SAWTOOTH){ + Vout = phaseAcc >> 16; + }else if(wave==SQUARE){ + if(phaseAcc<0){ + Vout = 0x8000; + }else{ + Vout = 0; + } + } if(volumeFiner){ Vout = (Vout*12*volume) >> 16; }else{ // 25 = floor( (1/10) << 8 ) @@ -155,6 +165,7 @@ void scanKeysTask(void * pvParameters){ digitalToggle(LED_BUILTIN); __atomic_store_n(¤tStepSize, stepSizes[getTopKey(keyArrayCopy)], __ATOMIC_RELAXED); K1.updateRotation(keyArrayCopy[4] & 0x1, keyArrayCopy[4] & 0x2); + __atomic_store_n(&wave, K1.getRotation()/2, __ATOMIC_RELAXED); if(volumeFiner){ K3.changeLimitsVolume(0,20); }else{ @@ -191,13 +202,13 @@ void displayUpdateTask(void * pvParameters){ // Print waveform icon int K1_rot = K1.getRotation(); if(K1_rot<2){ - u8g2.drawXBM(38,22,13,9,waveforms[SQR]); + u8g2.drawXBM(38,22,13,9,waveforms[SQUARE]); }else if(K1_rot<4){ - u8g2.drawXBM(38,22,13,9,waveforms[SAW]); + u8g2.drawXBM(38,22,13,9,waveforms[SAWTOOTH]); }else if(K1_rot<6){ - u8g2.drawXBM(38,22,13,9,waveforms[TRI]); + u8g2.drawXBM(38,22,13,9,waveforms[TRIANGLE]); }else if(K1_rot==6){ - u8g2.drawXBM(38,22,13,9,waveforms[SIN]); + u8g2.drawXBM(38,22,13,9,waveforms[SINE]); }; // Print octave number From df0957a110c83f34d87edad9dda03a5b84dd5256 Mon Sep 17 00:00:00 2001 From: Kacper Date: Wed, 23 Mar 2022 23:54:47 +0000 Subject: [PATCH 10/13] Added more octaves --- src/knob.cpp | 10 ++++++++++ src/knob.h | 1 + src/main.cpp | 41 ++++++++++++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/knob.cpp b/src/knob.cpp index cd24604..f588024 100644 --- a/src/knob.cpp +++ b/src/knob.cpp @@ -10,6 +10,16 @@ Knob::Knob(int minimum, int maximum) { Knob::rotation = 0; } +Knob::Knob(int minimum, int maximum, int initialRotation) { + Knob::minimum = minimum; + Knob::maximum = maximum; + Knob::A = false; + Knob::B = false; + Knob::rotPlusOnePrev = false; + Knob::rotMinOnePrev = false; + Knob::rotation = initialRotation; +} + int Knob::getRotation() { return Knob::rotation; }; diff --git a/src/knob.h b/src/knob.h index be39ce9..5b53d82 100644 --- a/src/knob.h +++ b/src/knob.h @@ -10,6 +10,7 @@ private: public: Knob(int minimum, int max); + Knob(int minimum, int max, int initialRotation); int getRotation(); diff --git a/src/main.cpp b/src/main.cpp index 37c078e..0f42384 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,19 +10,22 @@ volatile uint8_t keyArray[7]; volatile int8_t volume; volatile bool volumeFiner; volatile int8_t wave; +volatile int8_t octave = 4; int8_t volumeHistory = 0; SemaphoreHandle_t keyArrayMutex; -Knob K1(0,6); -Knob K3(0,10); +Knob K0(2,14,8); //Octave encoder +Knob K1(0,6); //Waveform encoder +Knob K3(0,10); //Volume encoder enum waves{SQUARE=0,SAWTOOTH,TRIANGLE,SINE}; #pragma region Config Values const uint32_t interval = 10; // Display update interval -const uint8_t octave = 4; // Octave to start on const uint32_t samplingRate = 44100; // Sampling rate const int32_t stepSizes[] = { - 0, 6370029, 6748811, 7150116, 7575284, 8025734, 8502969, 9008582, + 0, 3374406, 3575058, 3787642, 4012867, 4251485, 4504291, 4772130, + 5055896, 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, @@ -30,7 +33,9 @@ const int32_t stepSizes[] = { 48100059, 50960237, 53990491, 57200933, 60602277, 64205876, 68023756, 72068659, 76354085, 80894335, 85704562, 90800821, 96200119, 101920475, 107980982, 114401866, 121204555, 12841175, 136047513, 144137319, 152708170, - 161788670, 171409125, 181601642, 192400238}; // Step sizes for each note + 161788670, 171409125, 181601642, 192400238, 203840952, 215961966, + 228803732, 242409110, 256823506, 272095026, 288274639, 305416341, 323577341, + 342818251, 363203285, 384800477, 407681904}; // Step sizes for each note static unsigned char waveforms[4][18] = { {0x7f, 0x10, 0x41, 0x10, 0x41, 0x10, 0x41, 0x10, 0x41, 0x10, 0x41, 0x10, 0x41, 0x10, 0x41, 0x10, 0xc1, 0x1f}, //square wave @@ -114,12 +119,24 @@ void setRow(const uint8_t rowIdx) { digitalWrite(REN_PIN, HIGH); } +uint32_t scaleVolume(uint32_t Vout){ + uint32_t newVout = 0; + if(volumeFiner){ + newVout = (Vout*12*volume) >> 16; + }else{ // 25 = floor( (1/10) << 8 ) + newVout = (Vout*25*volume) >> 16; //scale by 2*8 cuz 16-bit*8-bit=24-bit -> scale by 16 to get to 8 + } + return newVout; +} + +//uint32_t combineNotes(uint32_t lol){} + uint16_t getTopKey(volatile uint8_t array[]) { uint16_t topKey = 0; for (uint8_t i = 0; i < 3; i++) { for (uint8_t j = 0; j < 4; j++) { if (array[i] & (0x1 << j)) { - topKey = (octave - 2) * 12 + i * 4 + j + 1; + topKey = (octave-1) * 12 + i * 4 + j + 1; } } } @@ -138,12 +155,12 @@ void sampleISR(){ }else{ Vout = 0; } + }else if(wave==TRIANGLE){ + //TODO + }else if(wave==SINE){ + //TODO } - if(volumeFiner){ - Vout = (Vout*12*volume) >> 16; - }else{ // 25 = floor( (1/10) << 8 ) - Vout = (Vout*25*volume) >> 16; //scale by 2*8 cuz 16-bit*8-bit=24-bit -> scale by 16 to get to 8 - } + Vout = scaleVolume(Vout); analogWrite(OUTR_PIN, Vout + 128); } @@ -164,6 +181,8 @@ void scanKeysTask(void * pvParameters){ xSemaphoreGive(keyArrayMutex); digitalToggle(LED_BUILTIN); __atomic_store_n(¤tStepSize, stepSizes[getTopKey(keyArrayCopy)], __ATOMIC_RELAXED); + K0.updateRotation(keyArrayCopy[4] & 0x4, keyArrayCopy[4] & 0x8); + __atomic_store_n(&octave, K0.getRotation()/2, __ATOMIC_RELAXED); K1.updateRotation(keyArrayCopy[4] & 0x1, keyArrayCopy[4] & 0x2); __atomic_store_n(&wave, K1.getRotation()/2, __ATOMIC_RELAXED); if(volumeFiner){ From c425de4fa5887e2d6d1f6320bea482bc04b16788 Mon Sep 17 00:00:00 2001 From: Kacper Date: Thu, 24 Mar 2022 22:18:18 +0000 Subject: [PATCH 11/13] Completed merge --- lib/knob/knob | 2 ++ lib/knob/knob.cpp | 26 +++++++++++++++-- src/knob.cpp | 64 ----------------------------------------- src/knob.h | 22 -------------- src/main.cpp | 73 ++++++++++++++++++++++++----------------------- 5 files changed, 62 insertions(+), 125 deletions(-) delete mode 100644 src/knob.cpp delete mode 100644 src/knob.h diff --git a/lib/knob/knob b/lib/knob/knob index 9c035a1..48fd263 100644 --- a/lib/knob/knob +++ b/lib/knob/knob @@ -10,10 +10,12 @@ class Knob { public: Knob(int minimum, int max); + Knob(int minimum, int max, int initialRotation); int getRotation(); void updateRotation(bool ANew, bool BNew); + void changeLimitsVolume(int newMinimum, int newMaximum); }; #endif \ No newline at end of file diff --git a/lib/knob/knob.cpp b/lib/knob/knob.cpp index 25bf475..b15c03a 100644 --- a/lib/knob/knob.cpp +++ b/lib/knob/knob.cpp @@ -10,6 +10,16 @@ Knob::Knob(int minimum, int maximum) { Knob::rotation = 0; } +Knob::Knob(int minimum, int maximum, int initialRotation) { + Knob::minimum = minimum; + Knob::maximum = maximum; + Knob::A = false; + Knob::B = false; + Knob::rotPlusOnePrev = false; + Knob::rotMinOnePrev = false; + Knob::rotation = initialRotation; +} + int Knob::getRotation() { return Knob::rotation; }; @@ -31,9 +41,9 @@ void Knob::updateRotation(bool ANew, bool BNew) { (B && A && !BNew && !ANew); if (rotPlusOneNew || (impossibleState && rotPlusOnePrev)) - rotation += 2; + rotation += 1; if (rotMinOneNew || (impossibleState && rotMinOnePrev)) - rotation -= 2; + rotation -= 1; if (rotation < minimum) rotation = minimum; if (rotation > maximum) @@ -45,4 +55,14 @@ void Knob::updateRotation(bool ANew, bool BNew) { rotPlusOnePrev = rotPlusOneNew; rotMinOnePrev = rotMinOneNew; } -} \ No newline at end of file +} + +void Knob::changeLimitsVolume(int newMinimum, int newMaximum) { + if(newMaximum>maximum){ + rotation = rotation<<1; + }else if(newMaximum>1; + }else{} + minimum = newMinimum; + maximum = newMaximum; +}; \ No newline at end of file diff --git a/src/knob.cpp b/src/knob.cpp deleted file mode 100644 index f588024..0000000 --- a/src/knob.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "knob.h" - -Knob::Knob(int minimum, int maximum) { - Knob::minimum = minimum; - Knob::maximum = maximum; - Knob::A = false; - Knob::B = false; - Knob::rotPlusOnePrev = false; - Knob::rotMinOnePrev = false; - Knob::rotation = 0; -} - -Knob::Knob(int minimum, int maximum, int initialRotation) { - Knob::minimum = minimum; - Knob::maximum = maximum; - Knob::A = false; - Knob::B = false; - Knob::rotPlusOnePrev = false; - Knob::rotMinOnePrev = false; - Knob::rotation = initialRotation; -} - -int Knob::getRotation() { - return Knob::rotation; -}; - -void Knob::updateRotation(bool ANew, bool BNew) { - bool rotPlusOneNew = (!B && !A && !BNew && ANew) || - (!B && A && BNew && ANew) || - (B && !A && !BNew && !ANew) || - (B && A && BNew && !ANew); - - bool rotMinOneNew = (!B && !A && BNew && !ANew) || - (!B && A && !BNew && !ANew) || - (B && !A && BNew && ANew) || - (B && A && !BNew && ANew); - - bool impossibleState = (!B && !A && BNew && ANew) || - (!B && A && BNew && !ANew) || - (B && !A && !BNew && ANew) || - (B && A && !BNew && !ANew); - - if (rotPlusOneNew || (impossibleState && rotPlusOnePrev)) rotation += 1; - if (rotMinOneNew || (impossibleState && rotMinOnePrev)) rotation -= 1; - if (rotation < minimum) rotation = minimum; - if (rotation > maximum) rotation = maximum; - - A = ANew; - B = BNew; - if (!impossibleState) { - rotPlusOnePrev = rotPlusOneNew; - rotMinOnePrev = rotMinOneNew; - } -}; - -void Knob::changeLimitsVolume(int newMinimum, int newMaximum) { - if(newMaximum>maximum){ - rotation = rotation<<1; - }else if(newMaximum>1; - }else{} - minimum = newMinimum; - maximum = newMaximum; -}; \ No newline at end of file diff --git a/src/knob.h b/src/knob.h deleted file mode 100644 index 5b53d82..0000000 --- a/src/knob.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef KNOB_H -#define KNOB_H - -class Knob { -private: - int rotation; - int minimum, maximum; - bool A, B; - bool rotPlusOnePrev, rotMinOnePrev; - -public: - Knob(int minimum, int max); - Knob(int minimum, int max, int initialRotation); - - int getRotation(); - - void updateRotation(bool ANew, bool BNew); - - void changeLimitsVolume(int newMinimum, int newMaximum); -}; - -#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 673c9b0..bf0c762 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,7 +14,7 @@ const uint32_t canID = 0x123; // Variables std::atomic currentStepSize; std::atomic keyArray[7]; -std::atomic octave = 4; // Octave to start on +std::atomic octave; std::atomic volume; std::atomic volumeFiner; std::atomic wave; @@ -170,35 +170,35 @@ void sampleISR(){ analogWrite(OUTR_PIN, Vout + 128); } -void CAN_RX_ISR() { - uint8_t ISR_RX_Message[8]; - uint32_t ISR_rxID; - CAN_RX(ISR_rxID, ISR_RX_Message); - xQueueSendFromISR(msgInQ, ISR_RX_Message, nullptr); -} +// void CAN_RX_ISR() { +// uint8_t ISR_RX_Message[8]; +// uint32_t ISR_rxID; +// CAN_RX(ISR_rxID, ISR_RX_Message); +// xQueueSendFromISR(msgInQ, ISR_RX_Message, nullptr); +// } -void decodeTask(void *pvParameters) { - while (1) { - xQueueReceive(msgInQ, RX_Message, portMAX_DELAY); - if (RX_Message[0] == 0x50) { // Pressed - currentStepSize = notes[(RX_Message[1] - 1) * 12 + RX_Message[2]].stepSize; - } else { // Released - currentStepSize = 0; - } - } -} +// void decodeTask(void *pvParameters) { +// while (1) { +// xQueueReceive(msgInQ, RX_Message, portMAX_DELAY); +// if (RX_Message[0] == 0x50) { // Pressed +// currentStepSize = notes[(RX_Message[1] - 1) * 12 + RX_Message[2]].stepSize; +// } else { // Released +// currentStepSize = 0; +// } +// } +// } -void keyChangedSendTXMessage(uint8_t octave, uint8_t key, bool pressed) { - uint8_t TX_Message[8] = {0}; - if (pressed) { - TX_Message[0] = 0x50; // "P" - } else { - TX_Message[0] = 0x52; // "R" - } - TX_Message[1] = octave; - TX_Message[2] = key; - CAN_TX(canID, TX_Message); -} +// void keyChangedSendTXMessage(uint8_t octave, uint8_t key, bool pressed) { +// uint8_t TX_Message[8] = {0}; +// if (pressed) { +// TX_Message[0] = 0x50; // "P" +// } else { +// TX_Message[0] = 0x52; // "R" +// } +// TX_Message[1] = octave; +// TX_Message[2] = key; +// CAN_TX(canID, TX_Message); +// } // Task to update keyArray values at a higher priority void scanKeysTask(void *pvParameters) { @@ -217,7 +217,7 @@ void scanKeysTask(void *pvParameters) { keyArray[i] = newRow; for (uint8_t j = 0; j < 4; j++) { if ((oldRow & (0x1 << j)) ^ (newRow & (0x1 << j))) { - keyChangedSendTXMessage(octave, i * 4 + j + 1, newRow & (0x1 << j)); + //keyChangedSendTXMessage(octave, i * 4 + j + 1, newRow & (0x1 << j)); } } } @@ -303,6 +303,7 @@ void displayUpdateTask(void *pvParameters) { } void setup() { + octave = 4; #pragma region Pin Setup pinMode(RA0_PIN, OUTPUT); pinMode(RA1_PIN, OUTPUT); @@ -330,13 +331,13 @@ void setup() { Serial.begin(115200); Serial.println("Hello World"); #pragma endregion -#pragma region CAN Setup - msgInQ = xQueueCreate(36, 8); - CAN_Init(true); - setCANFilter(0x123, 0x7ff); - CAN_RegisterRX_ISR(CAN_RX_ISR); - CAN_Start(); -#pragma endregion +// #pragma region CAN Setup +// msgInQ = xQueueCreate(36, 8); +// CAN_Init(true); +// setCANFilter(0x123, 0x7ff); +// CAN_RegisterRX_ISR(CAN_RX_ISR); +// CAN_Start(); +// #pragma endregion #pragma region Task Scheduler Setup TIM_TypeDef *Instance = TIM1; HardwareTimer *sampleTimer = new HardwareTimer(Instance); From 86f5af554747a19dfaa044155000b1bb5277f41c Mon Sep 17 00:00:00 2001 From: Kacper Date: Fri, 25 Mar 2022 09:56:37 +0000 Subject: [PATCH 12/13] Trying to implement multiple notes --- src/main.cpp | 98 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 23 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bf0c762..900e2f5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,12 +12,13 @@ const uint32_t interval = 10; // Display update interval const uint32_t samplingRate = 44100; // Sampling rate const uint32_t canID = 0x123; // Variables -std::atomic currentStepSize; +std::atomic currentStepSize[12]; std::atomic keyArray[7]; std::atomic octave; std::atomic volume; std::atomic volumeFiner; std::atomic wave; +std::atomic pressedKeys; int8_t volumeHistory = 0; QueueHandle_t msgInQ; uint8_t RX_Message[8] = {0}; @@ -27,12 +28,16 @@ Knob K0(2,14,8); //Octave encoder Knob K1(0,6); //Waveform encoder Knob K3(0,10); //Volume encoder // Program Specific Structures -typedef struct{ - int32_t stepSize; - std::string note; -} Note; -const Note notes[] = { - {0, "None"}, {3185014, "C1"}, {3374405, "C1#"}, {3575058, "D1"}, {3787642, "D1#"}, {4012867, "E1"}, {4251484, "F1"}, {4504291, "F1#"}, {4772130, "G1"}, {5055895, "G1#"}, {5356535, "A1"}, {5675051, "A1#"}, {6012507, "B1"}, {6370029, "C2"}, {6748811, "C2#"}, {7150116, "D2"}, {7575284, "D2#"}, {8025734, "E2"}, {8502969, "F2"}, {9008582, "F2#"}, {9544260, "G2"}, {10111791, "G2#"}, {10713070, "A2"}, {11350102, "A2#"}, {12025014, "B2"}, {12740059, "C3"}, {13497622, "C3#"}, {14300233, "D3"}, {15150569, "D3#"}, {16051469, "E3"}, {17005939, "F3"}, {18017164, "F3#"}, {19088521, "G3"}, {20223583, "G3#"}, {21426140, "A3"}, {22700205, "A3#"}, {24050029, "B3"}, {25480118, "C4"}, {26995245, "C4#"}, {28600466, "D4"}, {30301138, "D4#"}, {32102938, "E4"}, {34011878, "F4"}, {36034329, "F4#"}, {38177042, "G4"}, {40447167, "G4#"}, {42852281, "A4"}, {45400410, "A4#"}, {48100059, "B4"}, {50960237, "C5"}, {53990491, "C5#"}, {57200933, "D5"}, {60602277, "D5#"}, {64205876, "E5"}, {68023756, "F5"}, {72068659, "F5#"}, {76354085, "G5"}, {80894335, "G5#"}, {85704562, "A5"}, {90800821, "A5#"}, {96200119, "B5"}, {101920475, "C6"}, {107980982, "C6#"}, {114401866, "D6"}, {121204555, "D6#"}, {128411753, "E6"}, {136047513, "F6"}, {144137319, "F6#"}, {152708170, "G6"}, {161788670, "G6#"}, {171409125, "A6"}, {181601642, "A6#"}, {192400238, "B6"}, {203840951, "C7"}, {215961965, "C7#"}, {228803732, "D7"}, {242409110, "D7#"}, {256823506, "E7"}, {272095026, "F7"}, {288274638, "F7#"}, {305416340, "G7"}, {323577341, "G7#"}, {342818251, "A7"}, {363203285, "A7#"}, {384800476, "B7"}}; +const int32_t notes[8][12] = { + {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} +}; enum waveform { SQUARE = 0, SAWTOOTH, @@ -141,31 +146,75 @@ uint16_t getTopKey() { for (uint8_t i = 0; i < 3; i++) { for (uint8_t j = 0; j < 4; j++) { if (keyArray[i] & (0x1 << j)) { - topKey = (octave - 1) * 12 + i * 4 + j + 1; + topKey = i * 4 + j; } } } return topKey; } +// Returns integer where each bit represents a separate key (1 = pressed, 0 = not pressed) +uint16_t getKeys() { + uint16_t keys = 0; + for (uint8_t i = 0; i < 3; i++) { + for (uint8_t j = 0; j < 4; j++) { + if (keyArray[i] & (0x1 << j)) { + keys += 0x1 << (j+i*4); + } + } + } + return keys; +} + +int8_t getKeyCount() { + uint8_t keyCount = 0; + for (uint8_t i = 0; i < 3; i++) { + for (uint8_t j = 0; j < 4; j++) { + if (keyArray[i] & (0x1 << j)) { + keyCount += 1; + } + } + } + return keyCount; +} + +int32_t mixInputs(int32_t *accs) { + int8_t keyCount = getKeyCount(); + int32_t output = 0; + if(keyCount!=0){ + for(int8_t i = 0; i<12; i++){ + if(wave==SAWTOOTH){ + output += (*(accs+i)/keyCount) >> 16; + }else if(wave==SQUARE){ + if(*(accs+i)<0){ + output += 0x8000/keyCount; + }else{ + output += 0; + } + }else if(wave==TRIANGLE){ + //TODO + }else if(wave==SINE){ + //TODO + } + } + } + return output; +} + // Interrupt driven routine to send waveform to DAC void sampleISR(){ - static int32_t phaseAcc = 0; - phaseAcc += currentStepSize; - int32_t Vout = 0; - if(wave==SAWTOOTH){ - Vout = phaseAcc >> 16; - }else if(wave==SQUARE){ - if(phaseAcc<0){ - Vout = 0x8000; + static int32_t phaseAcc[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; + int8_t keyCount = getKeyCount(); + uint16_t keys = getKeys(); + Serial.print(1); + for(int8_t i = 0; i<12; i++){ + if(keys & (0x1 << i)){ + phaseAcc[i] += notes[octave][i]; }else{ - Vout = 0; + phaseAcc[i] = 0; } - }else if(wave==TRIANGLE){ - //TODO - }else if(wave==SINE){ - //TODO } + int32_t Vout = mixInputs(phaseAcc); Vout = scaleVolume(Vout); analogWrite(OUTR_PIN, Vout + 128); } @@ -227,7 +276,7 @@ void scanKeysTask(void *pvParameters) { }else{ K3.changeLimitsVolume(0,10); }; - currentStepSize = notes[getTopKey()].stepSize; // Atomic Store + pressedKeys = getKeys(); K0.updateRotation(keyArray[4] & 0x4, keyArray[4] & 0x8); octave = K0.getRotation()/2; K1.updateRotation(keyArray[4] & 0x1, keyArray[4] & 0x2); @@ -250,7 +299,7 @@ void displayUpdateTask(void *pvParameters) { u8g2.clearBuffer(); // clear the internal memory u8g2.setFont(u8g2_font_profont12_mf); // choose a suitable font uint16_t key = getTopKey(); - u8g2.drawStr(2, 10, notes[key].note.c_str()); // Print the current key + //u8g2.drawStr(2, 10, notes[key].note.c_str()); // Print the current key digitalToggle(LED_BUILTIN); u8g2.setCursor(2, 20); for (uint8_t i = 0; i < 7; i++) { @@ -261,6 +310,9 @@ void displayUpdateTask(void *pvParameters) { u8g2.print(RX_Message[1]); u8g2.print(RX_Message[2], HEX); + u8g2.setCursor(70, 30); + u8g2.print(getKeys()); + // Print waveform icon int K1_rot = K1.getRotation(); if(K1_rot<2){ From c484ebba343b2d11c958141baf4aa24c1cb50117 Mon Sep 17 00:00:00 2001 From: Kacper Date: Fri, 25 Mar 2022 15:07:53 +0000 Subject: [PATCH 13/13] Added triangle and sine --- src/main.cpp | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index bf0c762..69617b1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -66,6 +66,24 @@ const unsigned char volumes[6][18] = { const unsigned char icon_bits[] = { 0x00, 0x00, 0x00, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x02, 0x01, 0xfe, 0x01, 0x00, 0x00}; +const int16_t sineLookUpTable[] = { + 128,131,134,137,140,143,146,149,152,156,159,162,165,168,171,174, + 176,179,182,185,188,191,193,196,199,201,204,206,209,211,213,216, + 218,220,222,224,226,228,230,232,234,236,237,239,240,242,243,245, + 246,247,248,249,250,251,252,252,253,254,254,255,255,255,255,255, + 255,255,255,255,255,255,254,254,253,252,252,251,250,249,248,247, + 246,245,243,242,240,239,237,236,234,232,230,228,226,224,222,220, + 218,216,213,211,209,206,204,201,199,196,193,191,188,185,182,179, + 176,174,171,168,165,162,159,156,152,149,146,143,140,137,134,131, + 128,124,121,118,115,112,109,106,103,99, 96, 93, 90, 87, 84, 81, + 79, 76, 73, 70, 67, 64, 62, 59, 56, 54, 51, 49, 46, 44, 42, 39, + 37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 18, 16, 15, 13, 12, 10, + 9, 8, 7, 6, 5, 4, 3, 3, 2, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 8, + 9, 10, 12, 13, 15, 16, 18, 19, 21, 23, 25, 27, 29, 31, 33, 35, + 37, 39, 42, 44, 46, 49, 51, 54, 56, 59, 62, 64, 67, 70, 73, 76, + 79, 81, 84, 87, 90, 93, 96, 99, 103,106,109,112,115,118,121,124 +}; #pragma endregion #pragma region Pin Definitions @@ -157,14 +175,14 @@ void sampleISR(){ Vout = phaseAcc >> 16; }else if(wave==SQUARE){ if(phaseAcc<0){ - Vout = 0x8000; + Vout = 0x00007FFF; }else{ - Vout = 0; + Vout = 0xFFFF8000; } }else if(wave==TRIANGLE){ - //TODO + Vout = (abs(phaseAcc)-1073741824) >> 15; }else if(wave==SINE){ - //TODO + Vout = (sineLookUpTable[(uint32_t)phaseAcc>>24]-128)<<8; } Vout = scaleVolume(Vout); analogWrite(OUTR_PIN, Vout + 128);