From dedffefc7f1ac7ae5b055edb0b6584a8c853e6c6 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 26 May 2019 16:59:50 -0500 Subject: [PATCH] add dds synth --- midisynth/dds_01/dds_01.ino | 119 ++ midisynth/dds_01/setTimers.ino | 57 + midisynth/dds_02/dds_02.ino | 86 + midisynth/dds_02/setTimers.ino | 57 + midisynth/dds_02/tables.h | 267 +++ midisynth/dds_03/dds_03.ino | 120 ++ midisynth/dds_03/setTimers.ino | 57 + midisynth/dds_03/tables.h | 267 +++ midisynth/dds_04/dds_04.ino | 197 +++ midisynth/dds_04/logging.ino | 69 + midisynth/dds_04/setTimers.ino | 57 + midisynth/dds_04/tables.h | 1565 +++++++++++++++++ midisynth/dds_05/dds_05.ino | 214 +++ midisynth/dds_05/logging.ino | 69 + midisynth/dds_05/setTimers.ino | 57 + midisynth/dds_05/tables.h | 1565 +++++++++++++++++ midisynth/dds_06/dds_06.ino | 307 ++++ midisynth/dds_06/logging.ino | 69 + midisynth/dds_06/setTimers.ino | 57 + midisynth/dds_06/tables.h | 1565 +++++++++++++++++ .../M0_Simple_Synth_09/M0_Simple_Synth_09.ino | 5 +- .../M0_Simple_Synth_09/images/circuit.svg | 774 -------- .../M0_Simple_Synth_10/M0_Simple_Synth_10.ino | 507 ++++++ nandsynth/M0_Simple_Synth_10/README.md | 23 + nandsynth/M0_Simple_Synth_10/colorSet.ino | 18 + nandsynth/M0_Simple_Synth_10/initSequnce.ino | 20 + nandsynth/M0_Simple_Synth_10/logging.ino | 69 + nandsynth/M0_Simple_Synth_10/setTimers.ino | 61 + 28 files changed, 7522 insertions(+), 776 deletions(-) create mode 100644 midisynth/dds_01/dds_01.ino create mode 100644 midisynth/dds_01/setTimers.ino create mode 100644 midisynth/dds_02/dds_02.ino create mode 100644 midisynth/dds_02/setTimers.ino create mode 100644 midisynth/dds_02/tables.h create mode 100644 midisynth/dds_03/dds_03.ino create mode 100644 midisynth/dds_03/setTimers.ino create mode 100644 midisynth/dds_03/tables.h create mode 100644 midisynth/dds_04/dds_04.ino create mode 100644 midisynth/dds_04/logging.ino create mode 100644 midisynth/dds_04/setTimers.ino create mode 100644 midisynth/dds_04/tables.h create mode 100644 midisynth/dds_05/dds_05.ino create mode 100644 midisynth/dds_05/logging.ino create mode 100644 midisynth/dds_05/setTimers.ino create mode 100644 midisynth/dds_05/tables.h create mode 100644 midisynth/dds_06/dds_06.ino create mode 100644 midisynth/dds_06/logging.ino create mode 100644 midisynth/dds_06/setTimers.ino create mode 100644 midisynth/dds_06/tables.h delete mode 100644 nandsynth/M0_Simple_Synth_09/images/circuit.svg create mode 100644 nandsynth/M0_Simple_Synth_10/M0_Simple_Synth_10.ino create mode 100644 nandsynth/M0_Simple_Synth_10/README.md create mode 100644 nandsynth/M0_Simple_Synth_10/colorSet.ino create mode 100644 nandsynth/M0_Simple_Synth_10/initSequnce.ino create mode 100644 nandsynth/M0_Simple_Synth_10/logging.ino create mode 100644 nandsynth/M0_Simple_Synth_10/setTimers.ino diff --git a/midisynth/dds_01/dds_01.ino b/midisynth/dds_01/dds_01.ino new file mode 100644 index 0000000..92d82e6 --- /dev/null +++ b/midisynth/dds_01/dds_01.ino @@ -0,0 +1,119 @@ + + + +#include "avr/pgmspace.h" + + +PROGMEM prog_uchar tri256[] = {0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xe, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, 0x80, 0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9d, 0x9f, 0xa1, 0xa3, 0xa5, 0xa7, 0xa9, 0xab, 0xad, 0xaf, 0xb1, 0xb3, 0xb5, 0xb7, 0xb9, 0xbb, 0xbd, 0xbf, 0xc1, 0xc3, 0xc5, 0xc7, 0xc9, 0xcb, 0xcd, 0xcf, 0xd1, 0xd3, 0xd5, 0xd7, 0xd9, 0xdb, 0xdd, 0xdf, 0xe1, 0xe3, 0xe5, 0xe7, 0xe9, 0xeb, 0xed, 0xef, 0xf1, 0xf3, 0xf5, 0xf7, 0xf9, 0xfb, 0xfd, 0xff, 0xfd, 0xfb, 0xf9, 0xf7, 0xf5, 0xf3, 0xf1, 0xef, 0xed, 0xeb, 0xe9, 0xe7, 0xe5, 0xe3, 0xe1, 0xdf, 0xdd, 0xdb, 0xd9, 0xd7, 0xd5, 0xd3, 0xd1, 0xcf, 0xcd, 0xcb, 0xc9, 0xc7, 0xc5, 0xc3, 0xc1, 0xbf, 0xbd, 0xbb, 0xb9, 0xb7, 0xb5, 0xb3, 0xb1, 0xaf, 0xad, 0xab, 0xa9, 0xa7, 0xa5, 0xa3, 0xa1, 0x9f, 0x9d, 0x9b, 0x99, 0x97, 0x95, 0x93, 0x91, 0x8f, 0x8d, 0x8b, 0x89, 0x87, 0x85, 0x83, 0x81, 0x80, 0x7e, 0x7c, 0x7a, 0x78, 0x76, 0x74, 0x72, 0x70, 0x6e, 0x6c, 0x6a, 0x68, 0x66, 0x64, 0x62, 0x60, 0x5e, 0x5c, 0x5a, 0x58, 0x56, 0x54, 0x52, 0x50, 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x42, 0x40, 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x34, 0x32, 0x30, 0x2e, 0x2c, 0x2a, 0x28, 0x26, 0x24, 0x22, 0x20, 0x1e, 0x1c, 0x1a, 0x18, 0x16, 0x14, 0x12, 0x10, 0xe, 0xc, 0xa, 0x8, 0x6, 0x4, 0x2, 0x0}; + + +PROGMEM prog_uchar sine256[] = { + 127, 130, 133, 136, 139, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, + 176, 178, 181, 184, 187, 190, 192, 195, 198, 200, 203, 205, 208, 210, 212, 215, + 217, 219, 221, 223, 225, 227, 229, 231, 233, 234, 236, 238, 239, 240, 242, 243, + 244, 245, 247, 248, 249, 249, 250, 251, 252, 252, 253, 253, 253, 254, 254, 254, + + 254, 254, 254, 254, 253, 253, 253, 252, 252, 251, 250, 249, 249, 248, 247, 245, + 244, 243, 242, 240, 239, 238, 236, 234, 233, 231, 229, 227, 225, 223, 221, 219, + 217, 215, 212, 210, 208, 205, 203, 200, 198, 195, 192, 190, 187, 184, 181, 178, + 176, 173, 170, 167, 164, 161, 158, 155, 152, 149, 146, 143, 139, 136, 133, 130, + + 127, 124, 121, 118, 115, 111, 108, 105, 102, 99, 96, 93, 90, 87, 84, 81, + 78, 76, 73, 70, 67, 64, 62, 59, 56, 54, 51, 49, 46, 44, 42, 39, + 37, 35, 33, 31, 29, 27, 25, 23, 21, 20, 18, 16, 15, 14, 12, 11, + 10, 9, 7, 6, 5, 5, 4, 3, 2, 2, 1, 1, 1, 0, 0, 0, + + 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 4, 5, 5, 6, 7, 9, + 10, 11, 12, 14, 15, 16, 18, 20, 21, 23, 25, 27, 29, 31, 33, 35, + 37, 39, 42, 44, 46, 49, 51, 54, 56, 59, 62, 64, 67, 70, 73, 76, + 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 115, 118, 121, 124 + +}; + +// Fix Serial for SAMD +#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) +// Required for Serial on Zero based boards +#define Serial SERIAL_PORT_USBVIRTUAL +#endif + + +double dfreq; +const double refclk = 35780; // tweak this number to get a good reference. BAsically, test that you are getting 440 hz + +volatile uint32_t phaccu; // phase accumulator +volatile uint32_t tword_m; // dds tuning word m +volatile byte counter; // + + + + +void TC4_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC4->COUNT16.INTFLAG.bit.OVF && TC4->COUNT16.INTENSET.bit.OVF) + { + // Put your timer overflow (OVF) code here.... + + + TC4->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + } +} + +/* + High Frequency Interrupt + This is the interrupt that controls the actual signal + + +*/ + +void TC5_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC5->COUNT16.INTFLAG.bit.OVF && TC5->COUNT16.INTENSET.bit.OVF) + { + + phaccu = phaccu + tword_m; // soft DDS, phase accu with 32 bits + uint32_t icnt = phaccu >> 24; // use upper 8 bits for phase accu as frequency information + // read value fron ROM sine table and send to PWM DAC + + uint32_t value = pgm_read_byte_near(sine256 + icnt); + + // value = value << 1; + + + analogWrite(A0, value); + + + counter++; + if (counter % 2 == 0) { + digitalWrite(A2, true); + } else { + digitalWrite(A2, false); + } + + + + TC5->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + + } +} + +void setup() { + + Serial.begin(115200); + Serial.println("Setting up"); + analogWriteResolution(10); + dfreq = 440.0; // initial output frequency = 440 Hz + tword_m = pow(2, 32) * dfreq / refclk; // calulate DDS new tuning word + + counter = 0; + + setupTimer4_5(); + +} + +void loop() { + + Serial.println("Enter Loop:"); + while (true) { } +} diff --git a/midisynth/dds_01/setTimers.ino b/midisynth/dds_01/setTimers.ino new file mode 100644 index 0000000..78c8034 --- /dev/null +++ b/midisynth/dds_01/setTimers.ino @@ -0,0 +1,57 @@ + +// Set timer TC4 and TC5 + +// TC4 is set up with a prescaler of 1024 : 48MHz/1024 = 46.875kHz +// The CC0 is set to 100 so ultimately this timer is happening every 469 HZ + +// TC5 is much faster at +// 48MHz/64 = 750kHz +// 750kHz/20 = 37,500 + + +// http://forum.arduino.cc/index.php?topic=599151.0 +void setupTimer4_5() { + // Feed GCLK0 to TC4 and TC5 + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK0 to TC4 and TC5 + GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0 + GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK0 to TC4 and TC5 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CC[0].reg = 100; // Set the TC4 CC0 register as the TOP value in match frequency mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest) + NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC4->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC4->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC4 interrupts + + TC4->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024, 48MHz/1024 = 46.875kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC4 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC4 + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + + + TC5->COUNT16.CC[0].reg = 20; // Set the TC5 CC0 register as the TOP value in match frequency mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC5_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC5 to 0 (highest) + NVIC_EnableIRQ(TC5_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC5->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC5->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC5 interrupts + + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV64 | // Set prescaler to 64, 48MHz/64 = 750 kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC5 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC5->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC5 + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization +} diff --git a/midisynth/dds_02/dds_02.ino b/midisynth/dds_02/dds_02.ino new file mode 100644 index 0000000..86a30a3 --- /dev/null +++ b/midisynth/dds_02/dds_02.ino @@ -0,0 +1,86 @@ + +#include "avr/pgmspace.h" +#include "tables.h" + + +// Plays random sine wave notes + +// Fix Serial for SAMD +#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) +// Required for Serial on Zero based boards +#define Serial SERIAL_PORT_USBVIRTUAL +#endif + + + const double refclk = 35780; +volatile uint32_t phaccu; // pahse accumulator +volatile uint32_t tword_m; // dds tuning word m +volatile byte counter; // + +volatile int lf_counter; // +volatile int lf_counter_compare; // + + +void TC4_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC4->COUNT16.INTFLAG.bit.OVF && TC4->COUNT16.INTENSET.bit.OVF) + { + // Put your timer overflow (OVF) code here.... + + if ( lf_counter > lf_counter_compare) { + lf_counter = 0; + + double dfreq = random(200, 1000); // initial output frequency = 440 Hz + tword_m = pow(2, 32) * dfreq / refclk; // calulate DDS new tuning word + + } + lf_counter++; + + + TC4->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + } +} + +/* + High Frequency Interrupt + This is the interrupt that controls the actual signal +*/ + +void TC5_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC5->COUNT16.INTFLAG.bit.OVF && TC5->COUNT16.INTENSET.bit.OVF) + { + + phaccu = phaccu + tword_m; // soft DDS, phase accu with 32 bits + uint32_t icnt = phaccu >> 24; // use upper 8 bits for phase accu as frequency information + // read value fron ROM sine table and send to PWM DAC + + uint32_t value = (signed char)pgm_read_byte_near(SinTable + icnt)*4 + 512; + + analogWrite(A0, value); + + TC5->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + + } +} + +void setup() { + + Serial.begin(115200); + Serial.println("Setting up"); + //By setting the write resolution to 10, you can use analogWrite() + // with values between 0 and 1023 to exploit the full DAC resolution + analogWriteResolution(10); + lf_counter_compare = 200; // increase for longer notes + double dfreq = 440.0; // initial output frequency = 440 Hz + tword_m = pow(2, 32) * dfreq / refclk; // calulate DDS new tuning word + setupTimer4_5(); +} + +void loop() { + + Serial.println("Enter Loop:"); + while (true) { } +} diff --git a/midisynth/dds_02/setTimers.ino b/midisynth/dds_02/setTimers.ino new file mode 100644 index 0000000..78c8034 --- /dev/null +++ b/midisynth/dds_02/setTimers.ino @@ -0,0 +1,57 @@ + +// Set timer TC4 and TC5 + +// TC4 is set up with a prescaler of 1024 : 48MHz/1024 = 46.875kHz +// The CC0 is set to 100 so ultimately this timer is happening every 469 HZ + +// TC5 is much faster at +// 48MHz/64 = 750kHz +// 750kHz/20 = 37,500 + + +// http://forum.arduino.cc/index.php?topic=599151.0 +void setupTimer4_5() { + // Feed GCLK0 to TC4 and TC5 + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK0 to TC4 and TC5 + GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0 + GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK0 to TC4 and TC5 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CC[0].reg = 100; // Set the TC4 CC0 register as the TOP value in match frequency mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest) + NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC4->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC4->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC4 interrupts + + TC4->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024, 48MHz/1024 = 46.875kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC4 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC4 + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + + + TC5->COUNT16.CC[0].reg = 20; // Set the TC5 CC0 register as the TOP value in match frequency mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC5_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC5 to 0 (highest) + NVIC_EnableIRQ(TC5_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC5->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC5->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC5 interrupts + + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV64 | // Set prescaler to 64, 48MHz/64 = 750 kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC5 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC5->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC5 + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization +} diff --git a/midisynth/dds_02/tables.h b/midisynth/dds_02/tables.h new file mode 100644 index 0000000..4808969 --- /dev/null +++ b/midisynth/dds_02/tables.h @@ -0,0 +1,267 @@ + +// Tables + +#ifndef _TABLES +#define _TABLES + +const PROGMEM char SinTable[]= +{ + 0, //0 + 3, //1 + 6, //2 + 9, //3 + 12, //4 + 15, //5 + 18, //6 + 21, //7 + 24, //8 + 27, //9 + 30, //10 + 33, //11 + 36, //12 + 39, //13 + 42, //14 + 45, //15 + 48, //16 + 51, //17 + 54, //18 + 57, //19 + 59, //20 + 62, //21 + 65, //22 + 67, //23 + 70, //24 + 73, //25 + 75, //26 + 78, //27 + 80, //28 + 82, //29 + 85, //30 + 87, //31 + 89, //32 + 91, //33 + 94, //34 + 96, //35 + 98, //36 + 100, //37 + 102, //38 + 103, //39 + 105, //40 + 107, //41 + 108, //42 + 110, //43 + 112, //44 + 113, //45 + 114, //46 + 116, //47 + 117, //48 + 118, //49 + 119, //50 + 120, //51 + 121, //52 + 122, //53 + 123, //54 + 123, //55 + 124, //56 + 125, //57 + 125, //58 + 126, //59 + 126, //60 + 126, //61 + 126, //62 + 126, //63 + 127, //64 + 126, //65 + 126, //66 + 126, //67 + 126, //68 + 126, //69 + 125, //70 + 125, //71 + 124, //72 + 123, //73 + 123, //74 + 122, //75 + 121, //76 + 120, //77 + 119, //78 + 118, //79 + 117, //80 + 116, //81 + 114, //82 + 113, //83 + 112, //84 + 110, //85 + 108, //86 + 107, //87 + 105, //88 + 103, //89 + 102, //90 + 100, //91 + 98, //92 + 96, //93 + 94, //94 + 91, //95 + 89, //96 + 87, //97 + 85, //98 + 82, //99 + 80, //100 + 78, //101 + 75, //102 + 73, //103 + 70, //104 + 67, //105 + 65, //106 + 62, //107 + 59, //108 + 57, //109 + 54, //110 + 51, //111 + 48, //112 + 45, //113 + 42, //114 + 39, //115 + 36, //116 + 33, //117 + 30, //118 + 27, //119 + 24, //120 + 21, //121 + 18, //122 + 15, //123 + 12, //124 + 9, //125 + 6, //126 + 3, //127 + 0, //128 + -3, //129 + -6, //130 + -9, //131 + -12, //132 + -15, //133 + -18, //134 + -21, //135 + -24, //136 + -27, //137 + -30, //138 + -33, //139 + -36, //140 + -39, //141 + -42, //142 + -45, //143 + -48, //144 + -51, //145 + -54, //146 + -57, //147 + -59, //148 + -62, //149 + -65, //150 + -67, //151 + -70, //152 + -73, //153 + -75, //154 + -78, //155 + -80, //156 + -82, //157 + -85, //158 + -87, //159 + -89, //160 + -91, //161 + -94, //162 + -96, //163 + -98, //164 + -100, //165 + -102, //166 + -103, //167 + -105, //168 + -107, //169 + -108, //170 + -110, //171 + -112, //172 + -113, //173 + -114, //174 + -116, //175 + -117, //176 + -118, //177 + -119, //178 + -120, //179 + -121, //180 + -122, //181 + -123, //182 + -123, //183 + -124, //184 + -125, //185 + -125, //186 + -126, //187 + -126, //188 + -126, //189 + -126, //190 + -126, //191 + -127, //192 + -126, //193 + -126, //194 + -126, //195 + -126, //196 + -126, //197 + -125, //198 + -125, //199 + -124, //200 + -123, //201 + -123, //202 + -122, //203 + -121, //204 + -120, //205 + -119, //206 + -118, //207 + -117, //208 + -116, //209 + -114, //210 + -113, //211 + -112, //212 + -110, //213 + -108, //214 + -107, //215 + -105, //216 + -103, //217 + -102, //218 + -100, //219 + -98, //220 + -96, //221 + -94, //222 + -91, //223 + -89, //224 + -87, //225 + -85, //226 + -82, //227 + -80, //228 + -78, //229 + -75, //230 + -73, //231 + -70, //232 + -67, //233 + -65, //234 + -62, //235 + -59, //236 + -57, //237 + -54, //238 + -51, //239 + -48, //240 + -45, //241 + -42, //242 + -39, //243 + -36, //244 + -33, //245 + -30, //246 + -27, //247 + -24, //248 + -21, //249 + -18, //250 + -15, //251 + -12, //252 + -9, //253 + -6, //254 + -4, //255 +}; + +#endif diff --git a/midisynth/dds_03/dds_03.ino b/midisynth/dds_03/dds_03.ino new file mode 100644 index 0000000..a6cb667 --- /dev/null +++ b/midisynth/dds_03/dds_03.ino @@ -0,0 +1,120 @@ + +#include "avr/pgmspace.h" +#include "tables.h" + + +// Plays random notes +// Sums two waves and does a little envelope thing + + +// Fix Serial for SAMD +#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) +// Required for Serial on Zero based boards +#define Serial SERIAL_PORT_USBVIRTUAL +#endif + + +const double refclk = 35780; +volatile uint32_t phaccu1; // pahse accumulator +volatile uint32_t tword_m1; // dds tuning word m + +volatile uint32_t phaccu2; // pahse accumulator +volatile uint32_t tword_m2; // dds tuning word m + + +volatile int lf_counter; // +volatile int lf_counter_compare; // + + +void TC4_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC4->COUNT16.INTFLAG.bit.OVF && TC4->COUNT16.INTENSET.bit.OVF) + { + // Put your timer overflow (OVF) code here.... + + if ( lf_counter > lf_counter_compare) { + lf_counter = 0; + + double dfreq = random(200, 1000); // initial output frequency = 440 Hz + tword_m1 = pow(2, 32) * dfreq / refclk; // calulate DDS new tuning word + + dfreq = random(200, 1000); // initial output frequency = 440 Hz + tword_m2 = pow(2, 32) * dfreq / refclk; // calulate DDS new tuning word + + } + lf_counter++; + + + TC4->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + } +} + +/* + High Frequency Interrupt + This is the interrupt that controls the actual signal + + +*/ + +void TC5_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC5->COUNT16.INTFLAG.bit.OVF && TC5->COUNT16.INTENSET.bit.OVF) + { + + double amp = (lf_counter_compare - lf_counter) / lf_counter_compare; // + + phaccu1 = phaccu1 + tword_m1; // soft DDS, phase accu with 32 bits + phaccu2 = phaccu2 + tword_m2; // soft DDS, phase accu with 32 bits + + uint32_t icnt1 = phaccu1 >> 24; // use upper 8 bits for phase accu as frequency information + // read value fron ROM sine table and send to PWM DAC + + uint32_t icnt2 = phaccu2 >> 24; // use upper 8 bits for phase accu as frequency information + // read value fron ROM sine table and send to PWM DAC + + + signed int v1 = (signed char)pgm_read_byte_near(SinTable + icnt1) * + (lf_counter_compare - lf_counter) / lf_counter_compare; + signed int v2 = (signed char)pgm_read_byte_near(SinTable + icnt2) * + (lf_counter) / lf_counter_compare; + + + // This is where we are summing the signals. With M0, we get to play with a value from 0 to 1023. + // The most we will see adding two signals is 255 or -255. That gives us some room to amp up the + // signal be for adding the offset ( 2*127) + int value = ((v1 + v2) * 2) + 255; + // we now should have a signal between 0 and 1023 + + analogWrite(A0, value); + + + + TC5->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + + } +} + +void setup() { + + Serial.begin(115200); + Serial.println("Setting up"); + //By setting the write resolution to 10, you can use analogWrite() with values between 0 and 1023 to exploit the full DAC resolution + analogWriteResolution(10); + lf_counter_compare = 100; + double dfreq = 440.0; // initial output frequency = 440 Hz + tword_m1 = pow(2, 32) * dfreq / refclk; // calulate DDS new tuning word + + dfreq = 340.0; // initial output frequency = 440 Hz + tword_m2 = pow(2, 32) * dfreq / refclk; // calulate DDS new tuning word + + setupTimer4_5(); + +} + +void loop() { + + Serial.println("Enter Loop:"); + while (true) { } +} diff --git a/midisynth/dds_03/setTimers.ino b/midisynth/dds_03/setTimers.ino new file mode 100644 index 0000000..78c8034 --- /dev/null +++ b/midisynth/dds_03/setTimers.ino @@ -0,0 +1,57 @@ + +// Set timer TC4 and TC5 + +// TC4 is set up with a prescaler of 1024 : 48MHz/1024 = 46.875kHz +// The CC0 is set to 100 so ultimately this timer is happening every 469 HZ + +// TC5 is much faster at +// 48MHz/64 = 750kHz +// 750kHz/20 = 37,500 + + +// http://forum.arduino.cc/index.php?topic=599151.0 +void setupTimer4_5() { + // Feed GCLK0 to TC4 and TC5 + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK0 to TC4 and TC5 + GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0 + GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK0 to TC4 and TC5 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CC[0].reg = 100; // Set the TC4 CC0 register as the TOP value in match frequency mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest) + NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC4->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC4->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC4 interrupts + + TC4->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024, 48MHz/1024 = 46.875kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC4 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC4 + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + + + TC5->COUNT16.CC[0].reg = 20; // Set the TC5 CC0 register as the TOP value in match frequency mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC5_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC5 to 0 (highest) + NVIC_EnableIRQ(TC5_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC5->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC5->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC5 interrupts + + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV64 | // Set prescaler to 64, 48MHz/64 = 750 kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC5 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC5->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC5 + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization +} diff --git a/midisynth/dds_03/tables.h b/midisynth/dds_03/tables.h new file mode 100644 index 0000000..4808969 --- /dev/null +++ b/midisynth/dds_03/tables.h @@ -0,0 +1,267 @@ + +// Tables + +#ifndef _TABLES +#define _TABLES + +const PROGMEM char SinTable[]= +{ + 0, //0 + 3, //1 + 6, //2 + 9, //3 + 12, //4 + 15, //5 + 18, //6 + 21, //7 + 24, //8 + 27, //9 + 30, //10 + 33, //11 + 36, //12 + 39, //13 + 42, //14 + 45, //15 + 48, //16 + 51, //17 + 54, //18 + 57, //19 + 59, //20 + 62, //21 + 65, //22 + 67, //23 + 70, //24 + 73, //25 + 75, //26 + 78, //27 + 80, //28 + 82, //29 + 85, //30 + 87, //31 + 89, //32 + 91, //33 + 94, //34 + 96, //35 + 98, //36 + 100, //37 + 102, //38 + 103, //39 + 105, //40 + 107, //41 + 108, //42 + 110, //43 + 112, //44 + 113, //45 + 114, //46 + 116, //47 + 117, //48 + 118, //49 + 119, //50 + 120, //51 + 121, //52 + 122, //53 + 123, //54 + 123, //55 + 124, //56 + 125, //57 + 125, //58 + 126, //59 + 126, //60 + 126, //61 + 126, //62 + 126, //63 + 127, //64 + 126, //65 + 126, //66 + 126, //67 + 126, //68 + 126, //69 + 125, //70 + 125, //71 + 124, //72 + 123, //73 + 123, //74 + 122, //75 + 121, //76 + 120, //77 + 119, //78 + 118, //79 + 117, //80 + 116, //81 + 114, //82 + 113, //83 + 112, //84 + 110, //85 + 108, //86 + 107, //87 + 105, //88 + 103, //89 + 102, //90 + 100, //91 + 98, //92 + 96, //93 + 94, //94 + 91, //95 + 89, //96 + 87, //97 + 85, //98 + 82, //99 + 80, //100 + 78, //101 + 75, //102 + 73, //103 + 70, //104 + 67, //105 + 65, //106 + 62, //107 + 59, //108 + 57, //109 + 54, //110 + 51, //111 + 48, //112 + 45, //113 + 42, //114 + 39, //115 + 36, //116 + 33, //117 + 30, //118 + 27, //119 + 24, //120 + 21, //121 + 18, //122 + 15, //123 + 12, //124 + 9, //125 + 6, //126 + 3, //127 + 0, //128 + -3, //129 + -6, //130 + -9, //131 + -12, //132 + -15, //133 + -18, //134 + -21, //135 + -24, //136 + -27, //137 + -30, //138 + -33, //139 + -36, //140 + -39, //141 + -42, //142 + -45, //143 + -48, //144 + -51, //145 + -54, //146 + -57, //147 + -59, //148 + -62, //149 + -65, //150 + -67, //151 + -70, //152 + -73, //153 + -75, //154 + -78, //155 + -80, //156 + -82, //157 + -85, //158 + -87, //159 + -89, //160 + -91, //161 + -94, //162 + -96, //163 + -98, //164 + -100, //165 + -102, //166 + -103, //167 + -105, //168 + -107, //169 + -108, //170 + -110, //171 + -112, //172 + -113, //173 + -114, //174 + -116, //175 + -117, //176 + -118, //177 + -119, //178 + -120, //179 + -121, //180 + -122, //181 + -123, //182 + -123, //183 + -124, //184 + -125, //185 + -125, //186 + -126, //187 + -126, //188 + -126, //189 + -126, //190 + -126, //191 + -127, //192 + -126, //193 + -126, //194 + -126, //195 + -126, //196 + -126, //197 + -125, //198 + -125, //199 + -124, //200 + -123, //201 + -123, //202 + -122, //203 + -121, //204 + -120, //205 + -119, //206 + -118, //207 + -117, //208 + -116, //209 + -114, //210 + -113, //211 + -112, //212 + -110, //213 + -108, //214 + -107, //215 + -105, //216 + -103, //217 + -102, //218 + -100, //219 + -98, //220 + -96, //221 + -94, //222 + -91, //223 + -89, //224 + -87, //225 + -85, //226 + -82, //227 + -80, //228 + -78, //229 + -75, //230 + -73, //231 + -70, //232 + -67, //233 + -65, //234 + -62, //235 + -59, //236 + -57, //237 + -54, //238 + -51, //239 + -48, //240 + -45, //241 + -42, //242 + -39, //243 + -36, //244 + -33, //245 + -30, //246 + -27, //247 + -24, //248 + -21, //249 + -18, //250 + -15, //251 + -12, //252 + -9, //253 + -6, //254 + -4, //255 +}; + +#endif diff --git a/midisynth/dds_04/dds_04.ino b/midisynth/dds_04/dds_04.ino new file mode 100644 index 0000000..e09ba88 --- /dev/null +++ b/midisynth/dds_04/dds_04.ino @@ -0,0 +1,197 @@ + +#include "avr/pgmspace.h" +#include "tables.h" +#include "MIDIUSB.h" + +#include "pitchToFrequency.h" + +// added midi notes and logs for cc + +// Fix Serial for SAMD +#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) +// Required for Serial on Zero based boards +#define Serial SERIAL_PORT_USBVIRTUAL +#endif + + +const double refclk = 35780; +volatile uint32_t phaccu1; // pahse accumulator +volatile uint32_t tword_m1; // dds tuning word m + +volatile uint32_t phaccu2; // pahse accumulator +volatile uint32_t tword_m2; // dds tuning word m + +volatile double volumeOsc1 = 1.0; // Will define now, but adjust later +volatile double volumeOsc2 = 1.0; // +volatile double detuneOSc2 = 1.07; // + + + + +void TC4_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC4->COUNT16.INTFLAG.bit.OVF && TC4->COUNT16.INTENSET.bit.OVF) + { + // Put your timer overflow (OVF) code here.... + // Will use in a bit + + TC4->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + } +} + +/* + High Frequency Interrupt + This is the interrupt that controls the actual signal + + +*/ + +void TC5_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC5->COUNT16.INTFLAG.bit.OVF && TC5->COUNT16.INTENSET.bit.OVF) + { + + + phaccu1 = phaccu1 + tword_m1; // soft DDS, phase accu with 32 bits + phaccu2 = phaccu2 + tword_m2; // soft DDS, phase accu with 32 bits + + uint32_t icnt1 = phaccu1 >> 24; // use upper 8 bits for phase accu as frequency information + // read value fron ROM sine table and send to PWM DAC + + uint32_t icnt2 = phaccu2 >> 24; // use upper 8 bits for phase accu as frequency information + // read value fron ROM sine table and send to PWM DAC + + + signed int v1 = ((signed char)pgm_read_byte_near(SinTable + icnt1))* volumeOsc1 ; + signed int v2 = ((signed char)pgm_read_byte_near(SawTable + icnt2) )* volumeOsc2; + + + int value = ((v1 + v2) ) + 255; + // should be between 0 and 1023 + + analogWrite(A0, value); + + + + TC5->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + + } +} + +void setup() { + + Serial.begin(115200); + Serial.println("Setting up"); + analogWriteResolution(10); + tword_m1 = 0; + tword_m2 = 0; + setupTimer4_5(); +} + + + +// 0xB +void controlChange(byte channel, byte control, byte value) { + + logData(0xB, channel, control, value) ; // optional + + + //if (control == coreArray[CORE2].lfoCC) { + // coreArray[CORE2].lfoCounterCompare = mapMidiLowBudget(value, minLFO, maxLFO); + // return; + //} + + + +} + +// 0x9 +void noteOn(byte channel, byte pitch, byte velocity) { + + // Channel 0 check is optional. Im not sure why Im getting stray notes on initialization + if (channel == 0) { + Serial.print("Note on 1:"); + Serial.println(pitchFrequency[pitch]); + + double dfreq = pitchFrequency[pitch] ; // initial output frequency = 440 Hz + tword_m1 = pow(2, 32) * dfreq / refclk; // calulate DDS new tuning word + + // Add second voice as octave below + tword_m2 = tword_m1 >> 1; + + + } +} + +// 0x8 +void noteOff(byte channel, byte pitch, byte velocity) { + if (channel == 0) { + Serial.print("Note off 1:"); + Serial.println(pitch); + + tword_m2 = tword_m1 = 0; + + } +} + + +void loop() { + + Serial.println("Enter Loop:"); + while (true) { + + // Midi packet taken from + // midiEventPacket_t rx = MidiUSB.read(); + // + // First parameter is the event type (0x09 = note on, 0x08 = note off). + // Second parameter is note-on/note-off, combined with the channel. + // Channel can be anything between 0-15. Typically reported to the user as 1-16. + // Third parameter is the note number (48 = middle C). + // Fourth parameter is the velocity (64 = normal, 127 = fastest). + + midiEventPacket_t rx = MidiUSB.read(); + switch (rx.header) { + case 0: + break; //No pending events + + case 0xB: + controlChange( + rx.byte1 & 0xF, //channel + rx.byte2, //control + rx.byte3 //value + ); + break; + + case 0x9: + noteOn( + rx.byte1 & 0xF, //channel + rx.byte2, //pitch + rx.byte3 //velocity + ); + + break; + + case 0x8: + noteOff( + rx.byte1 & 0xF, //channel + rx.byte2, //pitch + rx.byte3 //velocity + ); + + break; + + default: + // If your curious + //logData(rx.header, rx.byte1, rx.byte2, rx.byte3) ; + + break; + } + + + + + + } +} diff --git a/midisynth/dds_04/logging.ino b/midisynth/dds_04/logging.ino new file mode 100644 index 0000000..426d1f6 --- /dev/null +++ b/midisynth/dds_04/logging.ino @@ -0,0 +1,69 @@ +// Utils to show the key name and Midi logging in the serial port +// +// +const char* pitch_name(byte pitch) { + static const char* names[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; + return names[pitch % 12]; +} + +int pitch_octave(byte pitch) { + return (pitch / 12) - 1; +} + + +void logData(byte header, byte channel, byte byte2, byte byte3) { + + switch (header) { + case 0: + return; + + + case 0x9: + + Serial.print("Note On: "); + Serial.println(byte2); + Serial.print(pitch_name(byte2)); + Serial.print(pitch_octave(byte2)); + Serial.print(", channel="); + Serial.print(channel); + Serial.print(", velocity="); + Serial.println(byte3); + break; + + case 0x8: + Serial.print("Note Off: "); + Serial.println(byte2); + Serial.print(pitch_name(byte2)); + Serial.print(pitch_octave(byte2)); + Serial.print(", channel="); + Serial.print(channel); + Serial.print(", velocity="); + Serial.println(byte3); + + break; + + case 0xB: + Serial.print("Control change: control="); + Serial.print(byte2); + Serial.print(", value="); + Serial.print(byte3); + Serial.print(", channel="); + Serial.println(channel); + break; + + default: + Serial.print("Unhandled MIDI message: "); + Serial.print(header, HEX); + Serial.print("-"); + Serial.print(channel, HEX); + Serial.print("-"); + Serial.print(byte2, HEX); + Serial.print("-"); + Serial.println(byte3, HEX); + + break; + + } +} + + diff --git a/midisynth/dds_04/setTimers.ino b/midisynth/dds_04/setTimers.ino new file mode 100644 index 0000000..78c8034 --- /dev/null +++ b/midisynth/dds_04/setTimers.ino @@ -0,0 +1,57 @@ + +// Set timer TC4 and TC5 + +// TC4 is set up with a prescaler of 1024 : 48MHz/1024 = 46.875kHz +// The CC0 is set to 100 so ultimately this timer is happening every 469 HZ + +// TC5 is much faster at +// 48MHz/64 = 750kHz +// 750kHz/20 = 37,500 + + +// http://forum.arduino.cc/index.php?topic=599151.0 +void setupTimer4_5() { + // Feed GCLK0 to TC4 and TC5 + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK0 to TC4 and TC5 + GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0 + GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK0 to TC4 and TC5 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CC[0].reg = 100; // Set the TC4 CC0 register as the TOP value in match frequency mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest) + NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC4->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC4->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC4 interrupts + + TC4->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024, 48MHz/1024 = 46.875kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC4 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC4 + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + + + TC5->COUNT16.CC[0].reg = 20; // Set the TC5 CC0 register as the TOP value in match frequency mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC5_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC5 to 0 (highest) + NVIC_EnableIRQ(TC5_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC5->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC5->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC5 interrupts + + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV64 | // Set prescaler to 64, 48MHz/64 = 750 kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC5 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC5->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC5 + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization +} diff --git a/midisynth/dds_04/tables.h b/midisynth/dds_04/tables.h new file mode 100644 index 0000000..1ee775c --- /dev/null +++ b/midisynth/dds_04/tables.h @@ -0,0 +1,1565 @@ + +// Tables + +#ifndef _TABLES +#define _TABLES + +const PROGMEM char SinTable[] = +{ + 0, //0 + 3, //1 + 6, //2 + 9, //3 + 12, //4 + 15, //5 + 18, //6 + 21, //7 + 24, //8 + 27, //9 + 30, //10 + 33, //11 + 36, //12 + 39, //13 + 42, //14 + 45, //15 + 48, //16 + 51, //17 + 54, //18 + 57, //19 + 59, //20 + 62, //21 + 65, //22 + 67, //23 + 70, //24 + 73, //25 + 75, //26 + 78, //27 + 80, //28 + 82, //29 + 85, //30 + 87, //31 + 89, //32 + 91, //33 + 94, //34 + 96, //35 + 98, //36 + 100, //37 + 102, //38 + 103, //39 + 105, //40 + 107, //41 + 108, //42 + 110, //43 + 112, //44 + 113, //45 + 114, //46 + 116, //47 + 117, //48 + 118, //49 + 119, //50 + 120, //51 + 121, //52 + 122, //53 + 123, //54 + 123, //55 + 124, //56 + 125, //57 + 125, //58 + 126, //59 + 126, //60 + 126, //61 + 126, //62 + 126, //63 + 127, //64 + 126, //65 + 126, //66 + 126, //67 + 126, //68 + 126, //69 + 125, //70 + 125, //71 + 124, //72 + 123, //73 + 123, //74 + 122, //75 + 121, //76 + 120, //77 + 119, //78 + 118, //79 + 117, //80 + 116, //81 + 114, //82 + 113, //83 + 112, //84 + 110, //85 + 108, //86 + 107, //87 + 105, //88 + 103, //89 + 102, //90 + 100, //91 + 98, //92 + 96, //93 + 94, //94 + 91, //95 + 89, //96 + 87, //97 + 85, //98 + 82, //99 + 80, //100 + 78, //101 + 75, //102 + 73, //103 + 70, //104 + 67, //105 + 65, //106 + 62, //107 + 59, //108 + 57, //109 + 54, //110 + 51, //111 + 48, //112 + 45, //113 + 42, //114 + 39, //115 + 36, //116 + 33, //117 + 30, //118 + 27, //119 + 24, //120 + 21, //121 + 18, //122 + 15, //123 + 12, //124 + 9, //125 + 6, //126 + 3, //127 + 0, //128 + -3, //129 + -6, //130 + -9, //131 + -12, //132 + -15, //133 + -18, //134 + -21, //135 + -24, //136 + -27, //137 + -30, //138 + -33, //139 + -36, //140 + -39, //141 + -42, //142 + -45, //143 + -48, //144 + -51, //145 + -54, //146 + -57, //147 + -59, //148 + -62, //149 + -65, //150 + -67, //151 + -70, //152 + -73, //153 + -75, //154 + -78, //155 + -80, //156 + -82, //157 + -85, //158 + -87, //159 + -89, //160 + -91, //161 + -94, //162 + -96, //163 + -98, //164 + -100, //165 + -102, //166 + -103, //167 + -105, //168 + -107, //169 + -108, //170 + -110, //171 + -112, //172 + -113, //173 + -114, //174 + -116, //175 + -117, //176 + -118, //177 + -119, //178 + -120, //179 + -121, //180 + -122, //181 + -123, //182 + -123, //183 + -124, //184 + -125, //185 + -125, //186 + -126, //187 + -126, //188 + -126, //189 + -126, //190 + -126, //191 + -127, //192 + -126, //193 + -126, //194 + -126, //195 + -126, //196 + -126, //197 + -125, //198 + -125, //199 + -124, //200 + -123, //201 + -123, //202 + -122, //203 + -121, //204 + -120, //205 + -119, //206 + -118, //207 + -117, //208 + -116, //209 + -114, //210 + -113, //211 + -112, //212 + -110, //213 + -108, //214 + -107, //215 + -105, //216 + -103, //217 + -102, //218 + -100, //219 + -98, //220 + -96, //221 + -94, //222 + -91, //223 + -89, //224 + -87, //225 + -85, //226 + -82, //227 + -80, //228 + -78, //229 + -75, //230 + -73, //231 + -70, //232 + -67, //233 + -65, //234 + -62, //235 + -59, //236 + -57, //237 + -54, //238 + -51, //239 + -48, //240 + -45, //241 + -42, //242 + -39, //243 + -36, //244 + -33, //245 + -30, //246 + -27, //247 + -24, //248 + -21, //249 + -18, //250 + -15, //251 + -12, //252 + -9, //253 + -6, //254 + -4, //255 +}; + + + +const PROGMEM char TriangleTable[] = +{ + 0, //0 + 1, //1 + 3, //2 + 5, //3 + 7, //4 + 9, //5 + 11, //6 + 13, //7 + 15, //8 + 17, //9 + 19, //10 + 21, //11 + 23, //12 + 25, //13 + 27, //14 + 29, //15 + 31, //16 + 33, //17 + 35, //18 + 37, //19 + 39, //20 + 41, //21 + 43, //22 + 45, //23 + 47, //24 + 49, //25 + 51, //26 + 53, //27 + 55, //28 + 57, //29 + 59, //30 + 61, //31 + 63, //32 + 65, //33 + 67, //34 + 69, //35 + 71, //36 + 73, //37 + 75, //38 + 77, //39 + 79, //40 + 81, //41 + 83, //42 + 85, //43 + 87, //44 + 89, //45 + 91, //46 + 93, //47 + 95, //48 + 97, //49 + 99, //50 + 101, //51 + 103, //52 + 105, //53 + 107, //54 + 109, //55 + 111, //56 + 113, //57 + 115, //58 + 117, //59 + 119, //60 + 121, //61 + 123, //62 + 125, //63 + 127, //64 + 125, //65 + 123, //66 + 121, //67 + 119, //68 + 117, //69 + 115, //70 + 113, //71 + 111, //72 + 109, //73 + 107, //74 + 105, //75 + 103, //76 + 101, //77 + 99, //78 + 97, //79 + 95, //80 + 93, //81 + 91, //82 + 89, //83 + 87, //84 + 85, //85 + 83, //86 + 81, //87 + 79, //88 + 77, //89 + 75, //90 + 73, //91 + 71, //92 + 69, //93 + 67, //94 + 65, //95 + 63, //96 + 61, //97 + 59, //98 + 57, //99 + 55, //100 + 53, //101 + 51, //102 + 49, //103 + 47, //104 + 45, //105 + 43, //106 + 41, //107 + 39, //108 + 37, //109 + 35, //110 + 33, //111 + 31, //112 + 29, //113 + 27, //114 + 25, //115 + 23, //116 + 21, //117 + 19, //118 + 17, //119 + 15, //120 + 13, //121 + 11, //122 + 9, //123 + 7, //124 + 5, //125 + 3, //126 + 1, //127 + 0, //128 + -1, //129 + -3, //130 + -5, //131 + -7, //132 + -9, //133 + -11, //134 + -13, //135 + -15, //136 + -17, //137 + -19, //138 + -21, //139 + -23, //140 + -25, //141 + -27, //142 + -29, //143 + -31, //144 + -33, //145 + -35, //146 + -37, //147 + -39, //148 + -41, //149 + -43, //150 + -45, //151 + -47, //152 + -49, //153 + -51, //154 + -53, //155 + -55, //156 + -57, //157 + -59, //158 + -61, //159 + -63, //160 + -65, //161 + -67, //162 + -69, //163 + -71, //164 + -73, //165 + -75, //166 + -77, //167 + -79, //168 + -81, //169 + -83, //170 + -85, //171 + -87, //172 + -89, //173 + -91, //174 + -93, //175 + -95, //176 + -97, //177 + -99, //178 + -101, //179 + -103, //180 + -105, //181 + -107, //182 + -109, //183 + -111, //184 + -113, //185 + -115, //186 + -117, //187 + -119, //188 + -121, //189 + -123, //190 + -125, //191 + -127, //192 + -125, //193 + -123, //194 + -121, //195 + -119, //196 + -117, //197 + -115, //198 + -113, //199 + -111, //200 + -109, //201 + -107, //202 + -105, //203 + -103, //204 + -101, //205 + -99, //206 + -97, //207 + -95, //208 + -93, //209 + -91, //210 + -89, //211 + -87, //212 + -85, //213 + -83, //214 + -81, //215 + -79, //216 + -77, //217 + -75, //218 + -73, //219 + -71, //220 + -69, //221 + -67, //222 + -65, //223 + -63, //224 + -61, //225 + -59, //226 + -57, //227 + -55, //228 + -53, //229 + -51, //230 + -49, //231 + -47, //232 + -45, //233 + -43, //234 + -41, //235 + -39, //236 + -37, //237 + -35, //238 + -33, //239 + -31, //240 + -29, //241 + -27, //242 + -25, //243 + -23, //244 + -21, //245 + -19, //246 + -17, //247 + -15, //248 + -13, //249 + -11, //250 + -9, //251 + -7, //252 + -5, //253 + -3, //254 + -2, //255 +}; + +const PROGMEM char SquareTable[] = +{ + 127, //0 + 127, //1 + 127, //2 + 127, //3 + 127, //4 + 127, //5 + 127, //6 + 127, //7 + 127, //8 + 127, //9 + 127, //10 + 127, //11 + 127, //12 + 127, //13 + 127, //14 + 127, //15 + 127, //16 + 127, //17 + 127, //18 + 127, //19 + 127, //20 + 127, //21 + 127, //22 + 127, //23 + 127, //24 + 127, //25 + 127, //26 + 127, //27 + 127, //28 + 127, //29 + 127, //30 + 127, //31 + 127, //32 + 127, //33 + 127, //34 + 127, //35 + 127, //36 + 127, //37 + 127, //38 + 127, //39 + 127, //40 + 127, //41 + 127, //42 + 127, //43 + 127, //44 + 127, //45 + 127, //46 + 127, //47 + 127, //48 + 127, //49 + 127, //50 + 127, //51 + 127, //52 + 127, //53 + 127, //54 + 127, //55 + 127, //56 + 127, //57 + 127, //58 + 127, //59 + 127, //60 + 127, //61 + 127, //62 + 127, //63 + 127, //64 + 127, //65 + 127, //66 + 127, //67 + 127, //68 + 127, //69 + 127, //70 + 127, //71 + 127, //72 + 127, //73 + 127, //74 + 127, //75 + 127, //76 + 127, //77 + 127, //78 + 127, //79 + 127, //80 + 127, //81 + 127, //82 + 127, //83 + 127, //84 + 127, //85 + 127, //86 + 127, //87 + 127, //88 + 127, //89 + 127, //90 + 127, //91 + 127, //92 + 127, //93 + 127, //94 + 127, //95 + 127, //96 + 127, //97 + 127, //98 + 127, //99 + 127, //100 + 127, //101 + 127, //102 + 127, //103 + 127, //104 + 127, //105 + 127, //106 + 127, //107 + 127, //108 + 127, //109 + 127, //110 + 127, //111 + 127, //112 + 127, //113 + 127, //114 + 127, //115 + 127, //116 + 127, //117 + 127, //118 + 127, //119 + 127, //120 + 127, //121 + 127, //122 + 127, //123 + 127, //124 + 127, //125 + 127, //126 + 127, //127 + -125, //128 + -125, //129 + -125, //130 + -125, //131 + -125, //132 + -125, //133 + -125, //134 + -125, //135 + -125, //136 + -125, //137 + -125, //138 + -125, //139 + -125, //140 + -125, //141 + -125, //142 + -125, //143 + -125, //144 + -125, //145 + -125, //146 + -125, //147 + -125, //148 + -125, //149 + -125, //150 + -125, //151 + -125, //152 + -125, //153 + -125, //154 + -125, //155 + -125, //156 + -125, //157 + -125, //158 + -125, //159 + -125, //160 + -125, //161 + -125, //162 + -125, //163 + -125, //164 + -125, //165 + -125, //166 + -125, //167 + -125, //168 + -125, //169 + -125, //170 + -125, //171 + -125, //172 + -125, //173 + -125, //174 + -125, //175 + -125, //176 + -125, //177 + -125, //178 + -125, //179 + -125, //180 + -125, //181 + -125, //182 + -125, //183 + -125, //184 + -125, //185 + -125, //186 + -125, //187 + -125, //188 + -125, //189 + -125, //190 + -125, //191 + -125, //192 + -125, //193 + -125, //194 + -125, //195 + -125, //196 + -125, //197 + -125, //198 + -125, //199 + -125, //200 + -125, //201 + -125, //202 + -125, //203 + -125, //204 + -125, //205 + -125, //206 + -125, //207 + -125, //208 + -125, //209 + -125, //210 + -125, //211 + -125, //212 + -125, //213 + -125, //214 + -125, //215 + -125, //216 + -125, //217 + -125, //218 + -125, //219 + -125, //220 + -125, //221 + -125, //222 + -125, //223 + -125, //224 + -125, //225 + -125, //226 + -125, //227 + -125, //228 + -125, //229 + -125, //230 + -125, //231 + -125, //232 + -125, //233 + -125, //234 + -125, //235 + -125, //236 + -125, //237 + -125, //238 + -125, //239 + -125, //240 + -125, //241 + -125, //242 + -125, //243 + -125, //244 + -125, //245 + -125, //246 + -125, //247 + -125, //248 + -125, //249 + -125, //250 + -125, //251 + -125, //252 + -125, //253 + -125, //254 + -1, //255 +}; +const PROGMEM char SawTable[] = +{ + 127, //0 + 127, //1 + 126, //2 + 125, //3 + 124, //4 + 123, //5 + 122, //6 + 121, //7 + 120, //8 + 119, //9 + 118, //10 + 117, //11 + 116, //12 + 115, //13 + 114, //14 + 113, //15 + 112, //16 + 111, //17 + 110, //18 + 109, //19 + 108, //20 + 107, //21 + 106, //22 + 105, //23 + 104, //24 + 103, //25 + 102, //26 + 101, //27 + 100, //28 + 99, //29 + 98, //30 + 97, //31 + 96, //32 + 95, //33 + 94, //34 + 93, //35 + 92, //36 + 91, //37 + 90, //38 + 89, //39 + 88, //40 + 87, //41 + 86, //42 + 85, //43 + 84, //44 + 83, //45 + 82, //46 + 81, //47 + 80, //48 + 79, //49 + 78, //50 + 77, //51 + 76, //52 + 75, //53 + 74, //54 + 73, //55 + 72, //56 + 71, //57 + 70, //58 + 69, //59 + 68, //60 + 67, //61 + 66, //62 + 65, //63 + 64, //64 + 63, //65 + 62, //66 + 61, //67 + 60, //68 + 59, //69 + 58, //70 + 57, //71 + 56, //72 + 55, //73 + 54, //74 + 53, //75 + 52, //76 + 51, //77 + 50, //78 + 49, //79 + 48, //80 + 47, //81 + 46, //82 + 45, //83 + 44, //84 + 43, //85 + 42, //86 + 41, //87 + 40, //88 + 39, //89 + 38, //90 + 37, //91 + 36, //92 + 35, //93 + 34, //94 + 33, //95 + 32, //96 + 31, //97 + 30, //98 + 29, //99 + 28, //100 + 27, //101 + 26, //102 + 25, //103 + 24, //104 + 23, //105 + 22, //106 + 21, //107 + 20, //108 + 19, //109 + 18, //110 + 17, //111 + 16, //112 + 15, //113 + 14, //114 + 13, //115 + 12, //116 + 11, //117 + 10, //118 + 9, //119 + 8, //120 + 7, //121 + 6, //122 + 5, //123 + 4, //124 + 3, //125 + 2, //126 + 1, //127 + 0, //128 + 0, //129 + -1, //130 + -2, //131 + -3, //132 + -4, //133 + -5, //134 + -6, //135 + -7, //136 + -8, //137 + -9, //138 + -10, //139 + -11, //140 + -12, //141 + -13, //142 + -14, //143 + -15, //144 + -16, //145 + -17, //146 + -18, //147 + -19, //148 + -20, //149 + -21, //150 + -22, //151 + -23, //152 + -24, //153 + -25, //154 + -26, //155 + -27, //156 + -28, //157 + -29, //158 + -30, //159 + -31, //160 + -32, //161 + -33, //162 + -34, //163 + -35, //164 + -36, //165 + -37, //166 + -38, //167 + -39, //168 + -40, //169 + -41, //170 + -42, //171 + -43, //172 + -44, //173 + -45, //174 + -46, //175 + -47, //176 + -48, //177 + -49, //178 + -50, //179 + -51, //180 + -52, //181 + -53, //182 + -54, //183 + -55, //184 + -56, //185 + -57, //186 + -58, //187 + -59, //188 + -60, //189 + -61, //190 + -62, //191 + -63, //192 + -64, //193 + -65, //194 + -66, //195 + -67, //196 + -68, //197 + -69, //198 + -70, //199 + -71, //200 + -72, //201 + -73, //202 + -74, //203 + -75, //204 + -76, //205 + -77, //206 + -78, //207 + -79, //208 + -80, //209 + -81, //210 + -82, //211 + -83, //212 + -84, //213 + -85, //214 + -86, //215 + -87, //216 + -88, //217 + -89, //218 + -90, //219 + -91, //220 + -92, //221 + -93, //222 + -94, //223 + -95, //224 + -96, //225 + -97, //226 + -98, //227 + -99, //228 + -100, //229 + -101, //230 + -102, //231 + -103, //232 + -104, //233 + -105, //234 + -106, //235 + -107, //236 + -108, //237 + -109, //238 + -110, //239 + -111, //240 + -112, //241 + -113, //242 + -114, //243 + -115, //244 + -116, //245 + -117, //246 + -118, //247 + -119, //248 + -120, //249 + -121, //250 + -122, //251 + -123, //252 + -124, //253 + -125, //254 + -127, //255 +}; +const PROGMEM char RampTable[] = +{ + -127, //0 + -126, //1 + -125, //2 + -124, //3 + -123, //4 + -122, //5 + -121, //6 + -120, //7 + -119, //8 + -118, //9 + -117, //10 + -116, //11 + -115, //12 + -114, //13 + -113, //14 + -112, //15 + -111, //16 + -110, //17 + -109, //18 + -108, //19 + -107, //20 + -106, //21 + -105, //22 + -104, //23 + -103, //24 + -102, //25 + -101, //26 + -100, //27 + -99, //28 + -98, //29 + -97, //30 + -96, //31 + -95, //32 + -94, //33 + -93, //34 + -92, //35 + -91, //36 + -90, //37 + -89, //38 + -88, //39 + -87, //40 + -86, //41 + -85, //42 + -84, //43 + -83, //44 + -82, //45 + -81, //46 + -80, //47 + -79, //48 + -78, //49 + -77, //50 + -76, //51 + -75, //52 + -74, //53 + -73, //54 + -72, //55 + -71, //56 + -70, //57 + -69, //58 + -68, //59 + -67, //60 + -66, //61 + -65, //62 + -64, //63 + -63, //64 + -62, //65 + -61, //66 + -60, //67 + -59, //68 + -58, //69 + -57, //70 + -56, //71 + -55, //72 + -54, //73 + -53, //74 + -52, //75 + -51, //76 + -50, //77 + -49, //78 + -48, //79 + -47, //80 + -46, //81 + -45, //82 + -44, //83 + -43, //84 + -42, //85 + -41, //86 + -40, //87 + -39, //88 + -38, //89 + -37, //90 + -36, //91 + -35, //92 + -34, //93 + -33, //94 + -32, //95 + -31, //96 + -30, //97 + -29, //98 + -28, //99 + -27, //100 + -26, //101 + -25, //102 + -24, //103 + -23, //104 + -22, //105 + -21, //106 + -20, //107 + -19, //108 + -18, //109 + -17, //110 + -16, //111 + -15, //112 + -14, //113 + -13, //114 + -12, //115 + -11, //116 + -10, //117 + -9, //118 + -8, //119 + -7, //120 + -6, //121 + -5, //122 + -4, //123 + -3, //124 + -2, //125 + -1, //126 + 0, //127 + 0, //128 + 1, //129 + 2, //130 + 3, //131 + 4, //132 + 5, //133 + 6, //134 + 7, //135 + 8, //136 + 9, //137 + 10, //138 + 11, //139 + 12, //140 + 13, //141 + 14, //142 + 15, //143 + 16, //144 + 17, //145 + 18, //146 + 19, //147 + 20, //148 + 21, //149 + 22, //150 + 23, //151 + 24, //152 + 25, //153 + 26, //154 + 27, //155 + 28, //156 + 29, //157 + 30, //158 + 31, //159 + 32, //160 + 33, //161 + 34, //162 + 35, //163 + 36, //164 + 37, //165 + 38, //166 + 39, //167 + 40, //168 + 41, //169 + 42, //170 + 43, //171 + 44, //172 + 45, //173 + 46, //174 + 47, //175 + 48, //176 + 49, //177 + 50, //178 + 51, //179 + 52, //180 + 53, //181 + 54, //182 + 55, //183 + 56, //184 + 57, //185 + 58, //186 + 59, //187 + 60, //188 + 61, //189 + 62, //190 + 63, //191 + 64, //192 + 65, //193 + 66, //194 + 67, //195 + 68, //196 + 69, //197 + 70, //198 + 71, //199 + 72, //200 + 73, //201 + 74, //202 + 75, //203 + 76, //204 + 77, //205 + 78, //206 + 79, //207 + 80, //208 + 81, //209 + 82, //210 + 83, //211 + 84, //212 + 85, //213 + 86, //214 + 87, //215 + 88, //216 + 89, //217 + 90, //218 + 91, //219 + 92, //220 + 93, //221 + 94, //222 + 95, //223 + 96, //224 + 97, //225 + 98, //226 + 99, //227 + 100, //228 + 101, //229 + 102, //230 + 103, //231 + 104, //232 + 105, //233 + 106, //234 + 107, //235 + 108, //236 + 109, //237 + 110, //238 + 111, //239 + 112, //240 + 113, //241 + 114, //242 + 115, //243 + 116, //244 + 117, //245 + 118, //246 + 119, //247 + 120, //248 + 121, //249 + 122, //250 + 123, //251 + 124, //252 + 125, //253 + 126, //254 + 127, //255 +}; +const PROGMEM char NoiseTable[] = +{ + -62, //0 + -72, //1 + -92, //2 + -98, //3 + 98, //4 + -103, //5 + 96, //6 + -89, //7 + -29, //8 + -55, //9 + 98, //10 + -8, //11 + -118, //12 + 13, //13 + 11, //14 + -1, //15 + 76, //16 + -8, //17 + -116, //18 + 51, //19 + 33, //20 + -85, //21 + -43, //22 + -16, //23 + -114, //24 + -47, //25 + -63, //26 + -113, //27 + 109, //28 + -39, //29 + -127, //30 + -59, //31 + 0, //32 + 118, //33 + 70, //34 + 62, //35 + 54, //36 + 85, //37 + 51, //38 + 122, //39 + 60, //40 + 30, //41 + -126, //42 + -25, //43 + 71, //44 + -82, //45 + -11, //46 + 64, //47 + -95, //48 + -110, //49 + 127, //50 + 37, //51 + -14, //52 + -57, //53 + 51, //54 + -4, //55 + -47, //56 + -80, //57 + 110, //58 + 7, //59 + -117, //60 + 89, //61 + 65, //62 + -58, //63 + 50, //64 + -21, //65 + 33, //66 + -113, //67 + -22, //68 + 111, //69 + -46, //70 + 108, //71 + 112, //72 + -57, //73 + -111, //74 + 53, //75 + -21, //76 + -22, //77 + -127, //78 + -18, //79 + -9, //80 + 95, //81 + 88, //82 + 99, //83 + -17, //84 + -3, //85 + 74, //86 + 2, //87 + 123, //88 + -31, //89 + 53, //90 + -7, //91 + 91, //92 + -80, //93 + 15, //94 + -112, //95 + 114, //96 + 14, //97 + -115, //98 + -55, //99 + 22, //100 + 95, //101 + 21, //102 + 53, //103 + -105, //104 + -67, //105 + -25, //106 + 25, //107 + 13, //108 + 58, //109 + -121, //110 + -62, //111 + 103, //112 + 87, //113 + 109, //114 + 38, //115 + -79, //116 + -60, //117 + -16, //118 + -68, //119 + -91, //120 + 90, //121 + 112, //122 + -99, //123 + 118, //124 + 87, //125 + -61, //126 + -36, //127 + -40, //128 + -39, //129 + -30, //130 + 34, //131 + 83, //132 + -100, //133 + -43, //134 + -114, //135 + -54, //136 + -8, //137 + -36, //138 + -52, //139 + 71, //140 + 22, //141 + -33, //142 + 116, //143 + 9, //144 + 114, //145 + 24, //146 + -91, //147 + -48, //148 + -106, //149 + -2, //150 + -31, //151 + 103, //152 + 21, //153 + 117, //154 + 44, //155 + 115, //156 + -59, //157 + 53, //158 + 97, //159 + 124, //160 + 66, //161 + 120, //162 + -44, //163 + 57, //164 + -96, //165 + -24, //166 + 46, //167 + 32, //168 + 111, //169 + -56, //170 + -123, //171 + 46, //172 + -11, //173 + 97, //174 + -70, //175 + -12, //176 + -89, //177 + -81, //178 + 24, //179 + -29, //180 + -23, //181 + 77, //182 + 42, //183 + -40, //184 + 8, //185 + -98, //186 + -35, //187 + -21, //188 + 116, //189 + 61, //190 + -41, //191 + 116, //192 + 66, //193 + -88, //194 + 22, //195 + 95, //196 + -31, //197 + 40, //198 + -51, //199 + -78, //200 + 28, //201 + 3, //202 + 124, //203 + 92, //204 + 81, //205 + -27, //206 + 78, //207 + 65, //208 + -16, //209 + -116, //210 + -73, //211 + -126, //212 + 55, //213 + -76, //214 + 78, //215 + 17, //216 + 43, //217 + 66, //218 + -24, //219 + 117, //220 + -38, //221 + -76, //222 + -10, //223 + -37, //224 + -47, //225 + -56, //226 + 33, //227 + 94, //228 + -40, //229 + 107, //230 + 36, //231 + -104, //232 + -11, //233 + -27, //234 + -23, //235 + 105, //236 + -96, //237 + 68, //238 + -25, //239 + 7, //240 + 67, //241 + 6, //242 + -69, //243 + 70, //244 + -10, //245 + 10, //246 + 5, //247 + 42, //248 + 120, //249 + -71, //250 + -122, //251 + -86, //252 + 113, //253 + 112, //254 + 119, //255 +}; +#endif diff --git a/midisynth/dds_05/dds_05.ino b/midisynth/dds_05/dds_05.ino new file mode 100644 index 0000000..bff61a4 --- /dev/null +++ b/midisynth/dds_05/dds_05.ino @@ -0,0 +1,214 @@ + +#include "avr/pgmspace.h" +#include "tables.h" +#include "MIDIUSB.h" + +#include "pitchToFrequency.h" + +// cc for vol osc1 and vol osc 2 and detune + + +// Fix Serial for SAMD +#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) +// Required for Serial on Zero based boards +#define Serial SERIAL_PORT_USBVIRTUAL +#endif + + +const double refclk = 35780; +volatile uint32_t phaccu1; // pahse accumulator +volatile uint32_t tword_m1; // dds tuning word m + +volatile uint32_t phaccu2; // pahse accumulator +volatile uint32_t tword_m2; // dds tuning word m + +volatile double volumeOsc1 = 1.0; // Will define now, but adjust later +volatile double volumeOsc2 = 1.0; // +volatile double detuneOsc2 = 1.0; // + + + + +void TC4_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC4->COUNT16.INTFLAG.bit.OVF && TC4->COUNT16.INTENSET.bit.OVF) + { + // Put your timer overflow (OVF) code here.... + // Will use in a bit + + TC4->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + } +} + +/* + High Frequency Interrupt + This is the interrupt that controls the actual signal + + +*/ + +void TC5_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC5->COUNT16.INTFLAG.bit.OVF && TC5->COUNT16.INTENSET.bit.OVF) + { + + + phaccu1 = phaccu1 + tword_m1; // soft DDS, phase accu with 32 bits + phaccu2 = phaccu2 + tword_m2; // soft DDS, phase accu with 32 bits + + uint32_t icnt1 = phaccu1 >> 24; // use upper 8 bits for phase accu as frequency information + // read value fron ROM sine table and send to PWM DAC + + uint32_t icnt2 = phaccu2 >> 24; // use upper 8 bits for phase accu as frequency information + // read value fron ROM sine table and send to PWM DAC + + + signed int v1 = ((signed char)pgm_read_byte_near(SinTable + icnt1) )* volumeOsc1 ; + signed int v2 = ((signed char)pgm_read_byte_near(SinTable + icnt2) )* volumeOsc2; + + + int value = ((v1 + v2) * 2) + 512; + + + analogWrite(A0, value); + + + + TC5->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + + } +} + +void setup() { + + Serial.begin(115200); + Serial.println("Setting up"); + analogWriteResolution(10); + + tword_m1 = 0; + + tword_m2 = 0; + + setupTimer4_5(); + +} + + + +// 0xB +void controlChange(byte channel, byte control, byte value) { + + logData(0xB, channel, control, value) ; // optional + + if (control == 10) { + volumeOsc1 = value / 128.0; + Serial.print("OSC1 volume:"); + Serial.println(volumeOsc1); + return; + } + + if (control == 114) { + volumeOsc2 = value / 128.0; + Serial.print("OSC2 volume:"); + Serial.println(volumeOsc2); + return; + } + + + if (control == 16) { + detuneOsc2 = (value + 64)/ 128.0; + Serial.print("detune:"); + Serial.println(detuneOsc2); + return; + } + + +} + +// 0x9 +void noteOn(byte channel, byte pitch, byte velocity) { + + // Channel 0 check is optional. Im not sure why Im getting stray notes on initialization + if (channel == 0) { + Serial.print("Note on 1:"); + Serial.println(pitchFrequency[pitch]); + + double dfreq = pitchFrequency[pitch] ; // initial output frequency = 440 Hz + tword_m1 = pow(2, 32) * dfreq / refclk; // calulate DDS new tuning word + + tword_m2 = (uint32_t)(tword_m1 * detuneOsc2); + + + } +} + +// 0x8 +void noteOff(byte channel, byte pitch, byte velocity) { + if (channel == 0) { + Serial.print("Note off 1:"); + Serial.println(pitch); + tword_m2 = tword_m1 = 0; + } +} + + +void loop() { + + Serial.println("Enter Loop:"); + while (true) { + + // Midi packet taken from + // midiEventPacket_t rx = MidiUSB.read(); + // + // First parameter is the event type (0x09 = note on, 0x08 = note off). + // Second parameter is note-on/note-off, combined with the channel. + // Channel can be anything between 0-15. Typically reported to the user as 1-16. + // Third parameter is the note number (48 = middle C). + // Fourth parameter is the velocity (64 = normal, 127 = fastest). + + midiEventPacket_t rx = MidiUSB.read(); + switch (rx.header) { + case 0: + break; //No pending events + + case 0xB: + controlChange( + rx.byte1 & 0xF, //channel + rx.byte2, //control + rx.byte3 //value + ); + break; + + case 0x9: + noteOn( + rx.byte1 & 0xF, //channel + rx.byte2, //pitch + rx.byte3 //velocity + ); + + break; + + case 0x8: + noteOff( + rx.byte1 & 0xF, //channel + rx.byte2, //pitch + rx.byte3 //velocity + ); + + break; + + default: + // If your curious + //logData(rx.header, rx.byte1, rx.byte2, rx.byte3) ; + + break; + } + + + + + + } +} diff --git a/midisynth/dds_05/logging.ino b/midisynth/dds_05/logging.ino new file mode 100644 index 0000000..426d1f6 --- /dev/null +++ b/midisynth/dds_05/logging.ino @@ -0,0 +1,69 @@ +// Utils to show the key name and Midi logging in the serial port +// +// +const char* pitch_name(byte pitch) { + static const char* names[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; + return names[pitch % 12]; +} + +int pitch_octave(byte pitch) { + return (pitch / 12) - 1; +} + + +void logData(byte header, byte channel, byte byte2, byte byte3) { + + switch (header) { + case 0: + return; + + + case 0x9: + + Serial.print("Note On: "); + Serial.println(byte2); + Serial.print(pitch_name(byte2)); + Serial.print(pitch_octave(byte2)); + Serial.print(", channel="); + Serial.print(channel); + Serial.print(", velocity="); + Serial.println(byte3); + break; + + case 0x8: + Serial.print("Note Off: "); + Serial.println(byte2); + Serial.print(pitch_name(byte2)); + Serial.print(pitch_octave(byte2)); + Serial.print(", channel="); + Serial.print(channel); + Serial.print(", velocity="); + Serial.println(byte3); + + break; + + case 0xB: + Serial.print("Control change: control="); + Serial.print(byte2); + Serial.print(", value="); + Serial.print(byte3); + Serial.print(", channel="); + Serial.println(channel); + break; + + default: + Serial.print("Unhandled MIDI message: "); + Serial.print(header, HEX); + Serial.print("-"); + Serial.print(channel, HEX); + Serial.print("-"); + Serial.print(byte2, HEX); + Serial.print("-"); + Serial.println(byte3, HEX); + + break; + + } +} + + diff --git a/midisynth/dds_05/setTimers.ino b/midisynth/dds_05/setTimers.ino new file mode 100644 index 0000000..78c8034 --- /dev/null +++ b/midisynth/dds_05/setTimers.ino @@ -0,0 +1,57 @@ + +// Set timer TC4 and TC5 + +// TC4 is set up with a prescaler of 1024 : 48MHz/1024 = 46.875kHz +// The CC0 is set to 100 so ultimately this timer is happening every 469 HZ + +// TC5 is much faster at +// 48MHz/64 = 750kHz +// 750kHz/20 = 37,500 + + +// http://forum.arduino.cc/index.php?topic=599151.0 +void setupTimer4_5() { + // Feed GCLK0 to TC4 and TC5 + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK0 to TC4 and TC5 + GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0 + GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK0 to TC4 and TC5 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CC[0].reg = 100; // Set the TC4 CC0 register as the TOP value in match frequency mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest) + NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC4->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC4->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC4 interrupts + + TC4->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024, 48MHz/1024 = 46.875kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC4 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC4 + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + + + TC5->COUNT16.CC[0].reg = 20; // Set the TC5 CC0 register as the TOP value in match frequency mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC5_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC5 to 0 (highest) + NVIC_EnableIRQ(TC5_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC5->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC5->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC5 interrupts + + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV64 | // Set prescaler to 64, 48MHz/64 = 750 kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC5 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC5->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC5 + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization +} diff --git a/midisynth/dds_05/tables.h b/midisynth/dds_05/tables.h new file mode 100644 index 0000000..1ee775c --- /dev/null +++ b/midisynth/dds_05/tables.h @@ -0,0 +1,1565 @@ + +// Tables + +#ifndef _TABLES +#define _TABLES + +const PROGMEM char SinTable[] = +{ + 0, //0 + 3, //1 + 6, //2 + 9, //3 + 12, //4 + 15, //5 + 18, //6 + 21, //7 + 24, //8 + 27, //9 + 30, //10 + 33, //11 + 36, //12 + 39, //13 + 42, //14 + 45, //15 + 48, //16 + 51, //17 + 54, //18 + 57, //19 + 59, //20 + 62, //21 + 65, //22 + 67, //23 + 70, //24 + 73, //25 + 75, //26 + 78, //27 + 80, //28 + 82, //29 + 85, //30 + 87, //31 + 89, //32 + 91, //33 + 94, //34 + 96, //35 + 98, //36 + 100, //37 + 102, //38 + 103, //39 + 105, //40 + 107, //41 + 108, //42 + 110, //43 + 112, //44 + 113, //45 + 114, //46 + 116, //47 + 117, //48 + 118, //49 + 119, //50 + 120, //51 + 121, //52 + 122, //53 + 123, //54 + 123, //55 + 124, //56 + 125, //57 + 125, //58 + 126, //59 + 126, //60 + 126, //61 + 126, //62 + 126, //63 + 127, //64 + 126, //65 + 126, //66 + 126, //67 + 126, //68 + 126, //69 + 125, //70 + 125, //71 + 124, //72 + 123, //73 + 123, //74 + 122, //75 + 121, //76 + 120, //77 + 119, //78 + 118, //79 + 117, //80 + 116, //81 + 114, //82 + 113, //83 + 112, //84 + 110, //85 + 108, //86 + 107, //87 + 105, //88 + 103, //89 + 102, //90 + 100, //91 + 98, //92 + 96, //93 + 94, //94 + 91, //95 + 89, //96 + 87, //97 + 85, //98 + 82, //99 + 80, //100 + 78, //101 + 75, //102 + 73, //103 + 70, //104 + 67, //105 + 65, //106 + 62, //107 + 59, //108 + 57, //109 + 54, //110 + 51, //111 + 48, //112 + 45, //113 + 42, //114 + 39, //115 + 36, //116 + 33, //117 + 30, //118 + 27, //119 + 24, //120 + 21, //121 + 18, //122 + 15, //123 + 12, //124 + 9, //125 + 6, //126 + 3, //127 + 0, //128 + -3, //129 + -6, //130 + -9, //131 + -12, //132 + -15, //133 + -18, //134 + -21, //135 + -24, //136 + -27, //137 + -30, //138 + -33, //139 + -36, //140 + -39, //141 + -42, //142 + -45, //143 + -48, //144 + -51, //145 + -54, //146 + -57, //147 + -59, //148 + -62, //149 + -65, //150 + -67, //151 + -70, //152 + -73, //153 + -75, //154 + -78, //155 + -80, //156 + -82, //157 + -85, //158 + -87, //159 + -89, //160 + -91, //161 + -94, //162 + -96, //163 + -98, //164 + -100, //165 + -102, //166 + -103, //167 + -105, //168 + -107, //169 + -108, //170 + -110, //171 + -112, //172 + -113, //173 + -114, //174 + -116, //175 + -117, //176 + -118, //177 + -119, //178 + -120, //179 + -121, //180 + -122, //181 + -123, //182 + -123, //183 + -124, //184 + -125, //185 + -125, //186 + -126, //187 + -126, //188 + -126, //189 + -126, //190 + -126, //191 + -127, //192 + -126, //193 + -126, //194 + -126, //195 + -126, //196 + -126, //197 + -125, //198 + -125, //199 + -124, //200 + -123, //201 + -123, //202 + -122, //203 + -121, //204 + -120, //205 + -119, //206 + -118, //207 + -117, //208 + -116, //209 + -114, //210 + -113, //211 + -112, //212 + -110, //213 + -108, //214 + -107, //215 + -105, //216 + -103, //217 + -102, //218 + -100, //219 + -98, //220 + -96, //221 + -94, //222 + -91, //223 + -89, //224 + -87, //225 + -85, //226 + -82, //227 + -80, //228 + -78, //229 + -75, //230 + -73, //231 + -70, //232 + -67, //233 + -65, //234 + -62, //235 + -59, //236 + -57, //237 + -54, //238 + -51, //239 + -48, //240 + -45, //241 + -42, //242 + -39, //243 + -36, //244 + -33, //245 + -30, //246 + -27, //247 + -24, //248 + -21, //249 + -18, //250 + -15, //251 + -12, //252 + -9, //253 + -6, //254 + -4, //255 +}; + + + +const PROGMEM char TriangleTable[] = +{ + 0, //0 + 1, //1 + 3, //2 + 5, //3 + 7, //4 + 9, //5 + 11, //6 + 13, //7 + 15, //8 + 17, //9 + 19, //10 + 21, //11 + 23, //12 + 25, //13 + 27, //14 + 29, //15 + 31, //16 + 33, //17 + 35, //18 + 37, //19 + 39, //20 + 41, //21 + 43, //22 + 45, //23 + 47, //24 + 49, //25 + 51, //26 + 53, //27 + 55, //28 + 57, //29 + 59, //30 + 61, //31 + 63, //32 + 65, //33 + 67, //34 + 69, //35 + 71, //36 + 73, //37 + 75, //38 + 77, //39 + 79, //40 + 81, //41 + 83, //42 + 85, //43 + 87, //44 + 89, //45 + 91, //46 + 93, //47 + 95, //48 + 97, //49 + 99, //50 + 101, //51 + 103, //52 + 105, //53 + 107, //54 + 109, //55 + 111, //56 + 113, //57 + 115, //58 + 117, //59 + 119, //60 + 121, //61 + 123, //62 + 125, //63 + 127, //64 + 125, //65 + 123, //66 + 121, //67 + 119, //68 + 117, //69 + 115, //70 + 113, //71 + 111, //72 + 109, //73 + 107, //74 + 105, //75 + 103, //76 + 101, //77 + 99, //78 + 97, //79 + 95, //80 + 93, //81 + 91, //82 + 89, //83 + 87, //84 + 85, //85 + 83, //86 + 81, //87 + 79, //88 + 77, //89 + 75, //90 + 73, //91 + 71, //92 + 69, //93 + 67, //94 + 65, //95 + 63, //96 + 61, //97 + 59, //98 + 57, //99 + 55, //100 + 53, //101 + 51, //102 + 49, //103 + 47, //104 + 45, //105 + 43, //106 + 41, //107 + 39, //108 + 37, //109 + 35, //110 + 33, //111 + 31, //112 + 29, //113 + 27, //114 + 25, //115 + 23, //116 + 21, //117 + 19, //118 + 17, //119 + 15, //120 + 13, //121 + 11, //122 + 9, //123 + 7, //124 + 5, //125 + 3, //126 + 1, //127 + 0, //128 + -1, //129 + -3, //130 + -5, //131 + -7, //132 + -9, //133 + -11, //134 + -13, //135 + -15, //136 + -17, //137 + -19, //138 + -21, //139 + -23, //140 + -25, //141 + -27, //142 + -29, //143 + -31, //144 + -33, //145 + -35, //146 + -37, //147 + -39, //148 + -41, //149 + -43, //150 + -45, //151 + -47, //152 + -49, //153 + -51, //154 + -53, //155 + -55, //156 + -57, //157 + -59, //158 + -61, //159 + -63, //160 + -65, //161 + -67, //162 + -69, //163 + -71, //164 + -73, //165 + -75, //166 + -77, //167 + -79, //168 + -81, //169 + -83, //170 + -85, //171 + -87, //172 + -89, //173 + -91, //174 + -93, //175 + -95, //176 + -97, //177 + -99, //178 + -101, //179 + -103, //180 + -105, //181 + -107, //182 + -109, //183 + -111, //184 + -113, //185 + -115, //186 + -117, //187 + -119, //188 + -121, //189 + -123, //190 + -125, //191 + -127, //192 + -125, //193 + -123, //194 + -121, //195 + -119, //196 + -117, //197 + -115, //198 + -113, //199 + -111, //200 + -109, //201 + -107, //202 + -105, //203 + -103, //204 + -101, //205 + -99, //206 + -97, //207 + -95, //208 + -93, //209 + -91, //210 + -89, //211 + -87, //212 + -85, //213 + -83, //214 + -81, //215 + -79, //216 + -77, //217 + -75, //218 + -73, //219 + -71, //220 + -69, //221 + -67, //222 + -65, //223 + -63, //224 + -61, //225 + -59, //226 + -57, //227 + -55, //228 + -53, //229 + -51, //230 + -49, //231 + -47, //232 + -45, //233 + -43, //234 + -41, //235 + -39, //236 + -37, //237 + -35, //238 + -33, //239 + -31, //240 + -29, //241 + -27, //242 + -25, //243 + -23, //244 + -21, //245 + -19, //246 + -17, //247 + -15, //248 + -13, //249 + -11, //250 + -9, //251 + -7, //252 + -5, //253 + -3, //254 + -2, //255 +}; + +const PROGMEM char SquareTable[] = +{ + 127, //0 + 127, //1 + 127, //2 + 127, //3 + 127, //4 + 127, //5 + 127, //6 + 127, //7 + 127, //8 + 127, //9 + 127, //10 + 127, //11 + 127, //12 + 127, //13 + 127, //14 + 127, //15 + 127, //16 + 127, //17 + 127, //18 + 127, //19 + 127, //20 + 127, //21 + 127, //22 + 127, //23 + 127, //24 + 127, //25 + 127, //26 + 127, //27 + 127, //28 + 127, //29 + 127, //30 + 127, //31 + 127, //32 + 127, //33 + 127, //34 + 127, //35 + 127, //36 + 127, //37 + 127, //38 + 127, //39 + 127, //40 + 127, //41 + 127, //42 + 127, //43 + 127, //44 + 127, //45 + 127, //46 + 127, //47 + 127, //48 + 127, //49 + 127, //50 + 127, //51 + 127, //52 + 127, //53 + 127, //54 + 127, //55 + 127, //56 + 127, //57 + 127, //58 + 127, //59 + 127, //60 + 127, //61 + 127, //62 + 127, //63 + 127, //64 + 127, //65 + 127, //66 + 127, //67 + 127, //68 + 127, //69 + 127, //70 + 127, //71 + 127, //72 + 127, //73 + 127, //74 + 127, //75 + 127, //76 + 127, //77 + 127, //78 + 127, //79 + 127, //80 + 127, //81 + 127, //82 + 127, //83 + 127, //84 + 127, //85 + 127, //86 + 127, //87 + 127, //88 + 127, //89 + 127, //90 + 127, //91 + 127, //92 + 127, //93 + 127, //94 + 127, //95 + 127, //96 + 127, //97 + 127, //98 + 127, //99 + 127, //100 + 127, //101 + 127, //102 + 127, //103 + 127, //104 + 127, //105 + 127, //106 + 127, //107 + 127, //108 + 127, //109 + 127, //110 + 127, //111 + 127, //112 + 127, //113 + 127, //114 + 127, //115 + 127, //116 + 127, //117 + 127, //118 + 127, //119 + 127, //120 + 127, //121 + 127, //122 + 127, //123 + 127, //124 + 127, //125 + 127, //126 + 127, //127 + -125, //128 + -125, //129 + -125, //130 + -125, //131 + -125, //132 + -125, //133 + -125, //134 + -125, //135 + -125, //136 + -125, //137 + -125, //138 + -125, //139 + -125, //140 + -125, //141 + -125, //142 + -125, //143 + -125, //144 + -125, //145 + -125, //146 + -125, //147 + -125, //148 + -125, //149 + -125, //150 + -125, //151 + -125, //152 + -125, //153 + -125, //154 + -125, //155 + -125, //156 + -125, //157 + -125, //158 + -125, //159 + -125, //160 + -125, //161 + -125, //162 + -125, //163 + -125, //164 + -125, //165 + -125, //166 + -125, //167 + -125, //168 + -125, //169 + -125, //170 + -125, //171 + -125, //172 + -125, //173 + -125, //174 + -125, //175 + -125, //176 + -125, //177 + -125, //178 + -125, //179 + -125, //180 + -125, //181 + -125, //182 + -125, //183 + -125, //184 + -125, //185 + -125, //186 + -125, //187 + -125, //188 + -125, //189 + -125, //190 + -125, //191 + -125, //192 + -125, //193 + -125, //194 + -125, //195 + -125, //196 + -125, //197 + -125, //198 + -125, //199 + -125, //200 + -125, //201 + -125, //202 + -125, //203 + -125, //204 + -125, //205 + -125, //206 + -125, //207 + -125, //208 + -125, //209 + -125, //210 + -125, //211 + -125, //212 + -125, //213 + -125, //214 + -125, //215 + -125, //216 + -125, //217 + -125, //218 + -125, //219 + -125, //220 + -125, //221 + -125, //222 + -125, //223 + -125, //224 + -125, //225 + -125, //226 + -125, //227 + -125, //228 + -125, //229 + -125, //230 + -125, //231 + -125, //232 + -125, //233 + -125, //234 + -125, //235 + -125, //236 + -125, //237 + -125, //238 + -125, //239 + -125, //240 + -125, //241 + -125, //242 + -125, //243 + -125, //244 + -125, //245 + -125, //246 + -125, //247 + -125, //248 + -125, //249 + -125, //250 + -125, //251 + -125, //252 + -125, //253 + -125, //254 + -1, //255 +}; +const PROGMEM char SawTable[] = +{ + 127, //0 + 127, //1 + 126, //2 + 125, //3 + 124, //4 + 123, //5 + 122, //6 + 121, //7 + 120, //8 + 119, //9 + 118, //10 + 117, //11 + 116, //12 + 115, //13 + 114, //14 + 113, //15 + 112, //16 + 111, //17 + 110, //18 + 109, //19 + 108, //20 + 107, //21 + 106, //22 + 105, //23 + 104, //24 + 103, //25 + 102, //26 + 101, //27 + 100, //28 + 99, //29 + 98, //30 + 97, //31 + 96, //32 + 95, //33 + 94, //34 + 93, //35 + 92, //36 + 91, //37 + 90, //38 + 89, //39 + 88, //40 + 87, //41 + 86, //42 + 85, //43 + 84, //44 + 83, //45 + 82, //46 + 81, //47 + 80, //48 + 79, //49 + 78, //50 + 77, //51 + 76, //52 + 75, //53 + 74, //54 + 73, //55 + 72, //56 + 71, //57 + 70, //58 + 69, //59 + 68, //60 + 67, //61 + 66, //62 + 65, //63 + 64, //64 + 63, //65 + 62, //66 + 61, //67 + 60, //68 + 59, //69 + 58, //70 + 57, //71 + 56, //72 + 55, //73 + 54, //74 + 53, //75 + 52, //76 + 51, //77 + 50, //78 + 49, //79 + 48, //80 + 47, //81 + 46, //82 + 45, //83 + 44, //84 + 43, //85 + 42, //86 + 41, //87 + 40, //88 + 39, //89 + 38, //90 + 37, //91 + 36, //92 + 35, //93 + 34, //94 + 33, //95 + 32, //96 + 31, //97 + 30, //98 + 29, //99 + 28, //100 + 27, //101 + 26, //102 + 25, //103 + 24, //104 + 23, //105 + 22, //106 + 21, //107 + 20, //108 + 19, //109 + 18, //110 + 17, //111 + 16, //112 + 15, //113 + 14, //114 + 13, //115 + 12, //116 + 11, //117 + 10, //118 + 9, //119 + 8, //120 + 7, //121 + 6, //122 + 5, //123 + 4, //124 + 3, //125 + 2, //126 + 1, //127 + 0, //128 + 0, //129 + -1, //130 + -2, //131 + -3, //132 + -4, //133 + -5, //134 + -6, //135 + -7, //136 + -8, //137 + -9, //138 + -10, //139 + -11, //140 + -12, //141 + -13, //142 + -14, //143 + -15, //144 + -16, //145 + -17, //146 + -18, //147 + -19, //148 + -20, //149 + -21, //150 + -22, //151 + -23, //152 + -24, //153 + -25, //154 + -26, //155 + -27, //156 + -28, //157 + -29, //158 + -30, //159 + -31, //160 + -32, //161 + -33, //162 + -34, //163 + -35, //164 + -36, //165 + -37, //166 + -38, //167 + -39, //168 + -40, //169 + -41, //170 + -42, //171 + -43, //172 + -44, //173 + -45, //174 + -46, //175 + -47, //176 + -48, //177 + -49, //178 + -50, //179 + -51, //180 + -52, //181 + -53, //182 + -54, //183 + -55, //184 + -56, //185 + -57, //186 + -58, //187 + -59, //188 + -60, //189 + -61, //190 + -62, //191 + -63, //192 + -64, //193 + -65, //194 + -66, //195 + -67, //196 + -68, //197 + -69, //198 + -70, //199 + -71, //200 + -72, //201 + -73, //202 + -74, //203 + -75, //204 + -76, //205 + -77, //206 + -78, //207 + -79, //208 + -80, //209 + -81, //210 + -82, //211 + -83, //212 + -84, //213 + -85, //214 + -86, //215 + -87, //216 + -88, //217 + -89, //218 + -90, //219 + -91, //220 + -92, //221 + -93, //222 + -94, //223 + -95, //224 + -96, //225 + -97, //226 + -98, //227 + -99, //228 + -100, //229 + -101, //230 + -102, //231 + -103, //232 + -104, //233 + -105, //234 + -106, //235 + -107, //236 + -108, //237 + -109, //238 + -110, //239 + -111, //240 + -112, //241 + -113, //242 + -114, //243 + -115, //244 + -116, //245 + -117, //246 + -118, //247 + -119, //248 + -120, //249 + -121, //250 + -122, //251 + -123, //252 + -124, //253 + -125, //254 + -127, //255 +}; +const PROGMEM char RampTable[] = +{ + -127, //0 + -126, //1 + -125, //2 + -124, //3 + -123, //4 + -122, //5 + -121, //6 + -120, //7 + -119, //8 + -118, //9 + -117, //10 + -116, //11 + -115, //12 + -114, //13 + -113, //14 + -112, //15 + -111, //16 + -110, //17 + -109, //18 + -108, //19 + -107, //20 + -106, //21 + -105, //22 + -104, //23 + -103, //24 + -102, //25 + -101, //26 + -100, //27 + -99, //28 + -98, //29 + -97, //30 + -96, //31 + -95, //32 + -94, //33 + -93, //34 + -92, //35 + -91, //36 + -90, //37 + -89, //38 + -88, //39 + -87, //40 + -86, //41 + -85, //42 + -84, //43 + -83, //44 + -82, //45 + -81, //46 + -80, //47 + -79, //48 + -78, //49 + -77, //50 + -76, //51 + -75, //52 + -74, //53 + -73, //54 + -72, //55 + -71, //56 + -70, //57 + -69, //58 + -68, //59 + -67, //60 + -66, //61 + -65, //62 + -64, //63 + -63, //64 + -62, //65 + -61, //66 + -60, //67 + -59, //68 + -58, //69 + -57, //70 + -56, //71 + -55, //72 + -54, //73 + -53, //74 + -52, //75 + -51, //76 + -50, //77 + -49, //78 + -48, //79 + -47, //80 + -46, //81 + -45, //82 + -44, //83 + -43, //84 + -42, //85 + -41, //86 + -40, //87 + -39, //88 + -38, //89 + -37, //90 + -36, //91 + -35, //92 + -34, //93 + -33, //94 + -32, //95 + -31, //96 + -30, //97 + -29, //98 + -28, //99 + -27, //100 + -26, //101 + -25, //102 + -24, //103 + -23, //104 + -22, //105 + -21, //106 + -20, //107 + -19, //108 + -18, //109 + -17, //110 + -16, //111 + -15, //112 + -14, //113 + -13, //114 + -12, //115 + -11, //116 + -10, //117 + -9, //118 + -8, //119 + -7, //120 + -6, //121 + -5, //122 + -4, //123 + -3, //124 + -2, //125 + -1, //126 + 0, //127 + 0, //128 + 1, //129 + 2, //130 + 3, //131 + 4, //132 + 5, //133 + 6, //134 + 7, //135 + 8, //136 + 9, //137 + 10, //138 + 11, //139 + 12, //140 + 13, //141 + 14, //142 + 15, //143 + 16, //144 + 17, //145 + 18, //146 + 19, //147 + 20, //148 + 21, //149 + 22, //150 + 23, //151 + 24, //152 + 25, //153 + 26, //154 + 27, //155 + 28, //156 + 29, //157 + 30, //158 + 31, //159 + 32, //160 + 33, //161 + 34, //162 + 35, //163 + 36, //164 + 37, //165 + 38, //166 + 39, //167 + 40, //168 + 41, //169 + 42, //170 + 43, //171 + 44, //172 + 45, //173 + 46, //174 + 47, //175 + 48, //176 + 49, //177 + 50, //178 + 51, //179 + 52, //180 + 53, //181 + 54, //182 + 55, //183 + 56, //184 + 57, //185 + 58, //186 + 59, //187 + 60, //188 + 61, //189 + 62, //190 + 63, //191 + 64, //192 + 65, //193 + 66, //194 + 67, //195 + 68, //196 + 69, //197 + 70, //198 + 71, //199 + 72, //200 + 73, //201 + 74, //202 + 75, //203 + 76, //204 + 77, //205 + 78, //206 + 79, //207 + 80, //208 + 81, //209 + 82, //210 + 83, //211 + 84, //212 + 85, //213 + 86, //214 + 87, //215 + 88, //216 + 89, //217 + 90, //218 + 91, //219 + 92, //220 + 93, //221 + 94, //222 + 95, //223 + 96, //224 + 97, //225 + 98, //226 + 99, //227 + 100, //228 + 101, //229 + 102, //230 + 103, //231 + 104, //232 + 105, //233 + 106, //234 + 107, //235 + 108, //236 + 109, //237 + 110, //238 + 111, //239 + 112, //240 + 113, //241 + 114, //242 + 115, //243 + 116, //244 + 117, //245 + 118, //246 + 119, //247 + 120, //248 + 121, //249 + 122, //250 + 123, //251 + 124, //252 + 125, //253 + 126, //254 + 127, //255 +}; +const PROGMEM char NoiseTable[] = +{ + -62, //0 + -72, //1 + -92, //2 + -98, //3 + 98, //4 + -103, //5 + 96, //6 + -89, //7 + -29, //8 + -55, //9 + 98, //10 + -8, //11 + -118, //12 + 13, //13 + 11, //14 + -1, //15 + 76, //16 + -8, //17 + -116, //18 + 51, //19 + 33, //20 + -85, //21 + -43, //22 + -16, //23 + -114, //24 + -47, //25 + -63, //26 + -113, //27 + 109, //28 + -39, //29 + -127, //30 + -59, //31 + 0, //32 + 118, //33 + 70, //34 + 62, //35 + 54, //36 + 85, //37 + 51, //38 + 122, //39 + 60, //40 + 30, //41 + -126, //42 + -25, //43 + 71, //44 + -82, //45 + -11, //46 + 64, //47 + -95, //48 + -110, //49 + 127, //50 + 37, //51 + -14, //52 + -57, //53 + 51, //54 + -4, //55 + -47, //56 + -80, //57 + 110, //58 + 7, //59 + -117, //60 + 89, //61 + 65, //62 + -58, //63 + 50, //64 + -21, //65 + 33, //66 + -113, //67 + -22, //68 + 111, //69 + -46, //70 + 108, //71 + 112, //72 + -57, //73 + -111, //74 + 53, //75 + -21, //76 + -22, //77 + -127, //78 + -18, //79 + -9, //80 + 95, //81 + 88, //82 + 99, //83 + -17, //84 + -3, //85 + 74, //86 + 2, //87 + 123, //88 + -31, //89 + 53, //90 + -7, //91 + 91, //92 + -80, //93 + 15, //94 + -112, //95 + 114, //96 + 14, //97 + -115, //98 + -55, //99 + 22, //100 + 95, //101 + 21, //102 + 53, //103 + -105, //104 + -67, //105 + -25, //106 + 25, //107 + 13, //108 + 58, //109 + -121, //110 + -62, //111 + 103, //112 + 87, //113 + 109, //114 + 38, //115 + -79, //116 + -60, //117 + -16, //118 + -68, //119 + -91, //120 + 90, //121 + 112, //122 + -99, //123 + 118, //124 + 87, //125 + -61, //126 + -36, //127 + -40, //128 + -39, //129 + -30, //130 + 34, //131 + 83, //132 + -100, //133 + -43, //134 + -114, //135 + -54, //136 + -8, //137 + -36, //138 + -52, //139 + 71, //140 + 22, //141 + -33, //142 + 116, //143 + 9, //144 + 114, //145 + 24, //146 + -91, //147 + -48, //148 + -106, //149 + -2, //150 + -31, //151 + 103, //152 + 21, //153 + 117, //154 + 44, //155 + 115, //156 + -59, //157 + 53, //158 + 97, //159 + 124, //160 + 66, //161 + 120, //162 + -44, //163 + 57, //164 + -96, //165 + -24, //166 + 46, //167 + 32, //168 + 111, //169 + -56, //170 + -123, //171 + 46, //172 + -11, //173 + 97, //174 + -70, //175 + -12, //176 + -89, //177 + -81, //178 + 24, //179 + -29, //180 + -23, //181 + 77, //182 + 42, //183 + -40, //184 + 8, //185 + -98, //186 + -35, //187 + -21, //188 + 116, //189 + 61, //190 + -41, //191 + 116, //192 + 66, //193 + -88, //194 + 22, //195 + 95, //196 + -31, //197 + 40, //198 + -51, //199 + -78, //200 + 28, //201 + 3, //202 + 124, //203 + 92, //204 + 81, //205 + -27, //206 + 78, //207 + 65, //208 + -16, //209 + -116, //210 + -73, //211 + -126, //212 + 55, //213 + -76, //214 + 78, //215 + 17, //216 + 43, //217 + 66, //218 + -24, //219 + 117, //220 + -38, //221 + -76, //222 + -10, //223 + -37, //224 + -47, //225 + -56, //226 + 33, //227 + 94, //228 + -40, //229 + 107, //230 + 36, //231 + -104, //232 + -11, //233 + -27, //234 + -23, //235 + 105, //236 + -96, //237 + 68, //238 + -25, //239 + 7, //240 + 67, //241 + 6, //242 + -69, //243 + 70, //244 + -10, //245 + 10, //246 + 5, //247 + 42, //248 + 120, //249 + -71, //250 + -122, //251 + -86, //252 + 113, //253 + 112, //254 + 119, //255 +}; +#endif diff --git a/midisynth/dds_06/dds_06.ino b/midisynth/dds_06/dds_06.ino new file mode 100644 index 0000000..9d5ce93 --- /dev/null +++ b/midisynth/dds_06/dds_06.ino @@ -0,0 +1,307 @@ + +#include "avr/pgmspace.h" +#include "tables.h" +#include "MIDIUSB.h" + +#include "pitchToFrequency.h" + +// wave select + + +// Fix Serial for SAMD +#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) +// Required for Serial on Zero based boards +#define Serial SERIAL_PORT_USBVIRTUAL +#endif + + + +const double refclk = 35780; +volatile uint32_t phaccu1; // pahse accumulator +volatile uint32_t tword_m1; // dds tuning word m + +volatile uint32_t phaccu2; // pahse accumulator +volatile uint32_t tword_m2; // dds tuning word m + +# define VERBOSE_LOGS false + +# define VOL1_CC 10 +# define VOL2_CC 114 +# define DETUNE2_CC 16 +# define WAVE1_CC 74 +# define WAVE2_CC 18 + +# define SIN_WAVE 1 +# define SAW_WAVE 2 +# define SQUARE_WAVE 3 +# define TRI_WAVE 4 +# define RAMP_WAVE 5 +# define NOISE_WAVE 6 + +volatile double volumeOsc1 = 1.0; // Will define now, but adjust later +volatile double volumeOsc2 = 1.0; // +volatile double detuneOsc2 = 1.0; // + +volatile byte waveSelect1 = SIN_WAVE; +volatile byte waveSelect2 = TRI_WAVE; + +void TC4_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC4->COUNT16.INTFLAG.bit.OVF && TC4->COUNT16.INTENSET.bit.OVF) + { + // Put your timer overflow (OVF) code here.... + // Will use in a bit + + TC4->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + } +} + + + +signed char readTable( byte waveSelect, uint32_t icnt) { + + if (waveSelect == SIN_WAVE) { + //Serial.println("sine"); + + return pgm_read_byte_near(SinTable + icnt); + } + + if (waveSelect == TRI_WAVE) { + return pgm_read_byte_near(TriangleTable + icnt); + } + if (waveSelect == SQUARE_WAVE) { + return pgm_read_byte_near(SquareTable + icnt); + } + + if (waveSelect == SAW_WAVE) { + return pgm_read_byte_near(SawTable + icnt); + } + + if (waveSelect == RAMP_WAVE) { + return pgm_read_byte_near(RampTable + icnt); + } + + if (waveSelect == NOISE_WAVE) { + return pgm_read_byte_near(NoiseTable + icnt); + } + + +} + + + + +byte calcWavetable( byte value) { + + if (value < 20) { + return SIN_WAVE; //1 + } else if (value < 40) { + return SAW_WAVE; //2 + } else if (value < 60) { + return SQUARE_WAVE; //3 + } else if (value < 80) { + return TRI_WAVE; //4 + } else if (value < 100) { + return RAMP_WAVE; + } else { + return NOISE_WAVE; + } + Serial.println("Panic up"); + +} +/* + High Frequency Interrupt + This is the interrupt that controls the actual signal + + +*/ + + + +void TC5_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC5->COUNT16.INTFLAG.bit.OVF && TC5->COUNT16.INTENSET.bit.OVF) + { + + + phaccu1 = phaccu1 + tword_m1; // soft DDS, phase accu with 32 bits + phaccu2 = phaccu2 + tword_m2; // soft DDS, phase accu with 32 bits + + uint32_t icnt1 = phaccu1 >> 24; // use upper 8 bits for phase accu as frequency information + // read value fron ROM sine table and send to PWM DAC + + uint32_t icnt2 = phaccu2 >> 24; // use upper 8 bits for phase accu as frequency information + // read value fron ROM sine table and send to PWM DAC + + + + signed int v1 = readTable(waveSelect1, icnt1) * volumeOsc1 ; + signed int v2 = readTable(waveSelect2, icnt2) * volumeOsc2; + //signed int v1 = pgm_read_byte_near(SinTable + icnt1) * volumeOsc1 ; + // signed int v2 = pgm_read_byte_near(SawTable + icnt2) * volumeOsc2; + + int value = ((v1 + v2) << 1) + 512; + + + analogWrite(A0, value); + + + + TC5->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + + } +} + +void setup() { + + Serial.begin(115200); + Serial.println("Setting up"); + analogWriteResolution(10); + tword_m1 = 0; + tword_m2 = 0; + setupTimer4_5(); +} + + + +// 0xB +void controlChange(byte channel, byte control, byte value) { + + //logData(0xB, channel, control, value) ; // optional + + if (control == VOL1_CC) { + volumeOsc1 = value / 128.0; + Serial.print("OSC1 volume:"); + Serial.println(volumeOsc1); + return; + } + + if (control == VOL2_CC) { + volumeOsc2 = value / 128.0; + Serial.print("OSC2 volume:"); + Serial.println(volumeOsc2); + return; + } + + + if (control == DETUNE2_CC) { + detuneOsc2 = (value + 64) / 128.0; + Serial.print("detune:"); + Serial.println(detuneOsc2); + return; + } + + if (control == WAVE1_CC) { + waveSelect1 = calcWavetable(value); + Serial.print("wave1:"); + Serial.println(waveSelect1); + return; + } + + if (control == WAVE2_CC) { + waveSelect2 = calcWavetable(value); + Serial.print("wave2:"); + Serial.println(waveSelect2); + return; + } + + + +} + +// 0x9 +void noteOn(byte channel, byte pitch, byte velocity) { + + // Channel 0 check is optional. Im not sure why Im getting stray notes on initialization + if (channel == 0) { + + // Calculate the frequency + double dfreq = pitchFrequency[pitch] ; + + tword_m1 = pow(2, 32) * dfreq / refclk; // calulate DDS new tuning word + + // tweak other + tword_m2 = tword_m1 * detuneOsc2; + + if (VERBOSE_LOGS == true) { + Serial.print("Note on 1:"); + Serial.println(pitchFrequency[pitch]); + } + } +} + +// 0x8 +void noteOff(byte channel, byte pitch, byte velocity) { + if (channel == 0) { + + tword_m2 = tword_m1 = 0; + + if (VERBOSE_LOGS == true) { + Serial.print("Note off 1:"); + Serial.println(pitch); + } + + } +} + + +void loop() { + + Serial.println("Enter Loop:"); + while (true) { + + // Midi packet taken from + // midiEventPacket_t rx = MidiUSB.read(); + // + // First parameter is the event type (0x09 = note on, 0x08 = note off). + // Second parameter is note-on/note-off, combined with the channel. + // Channel can be anything between 0-15. Typically reported to the user as 1-16. + // Third parameter is the note number (48 = middle C). + // Fourth parameter is the velocity (64 = normal, 127 = fastest). + + midiEventPacket_t rx = MidiUSB.read(); + switch (rx.header) { + case 0: + break; //No pending events + + case 0xB: + controlChange( + rx.byte1 & 0xF, //channel + rx.byte2, //control + rx.byte3 //value + ); + break; + + case 0x9: + noteOn( + rx.byte1 & 0xF, //channel + rx.byte2, //pitch + rx.byte3 //velocity + ); + + break; + + case 0x8: + noteOff( + rx.byte1 & 0xF, //channel + rx.byte2, //pitch + rx.byte3 //velocity + ); + + break; + + default: + // If your curious + //logData(rx.header, rx.byte1, rx.byte2, rx.byte3) ; + + break; + } + + + + + + } +} diff --git a/midisynth/dds_06/logging.ino b/midisynth/dds_06/logging.ino new file mode 100644 index 0000000..426d1f6 --- /dev/null +++ b/midisynth/dds_06/logging.ino @@ -0,0 +1,69 @@ +// Utils to show the key name and Midi logging in the serial port +// +// +const char* pitch_name(byte pitch) { + static const char* names[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; + return names[pitch % 12]; +} + +int pitch_octave(byte pitch) { + return (pitch / 12) - 1; +} + + +void logData(byte header, byte channel, byte byte2, byte byte3) { + + switch (header) { + case 0: + return; + + + case 0x9: + + Serial.print("Note On: "); + Serial.println(byte2); + Serial.print(pitch_name(byte2)); + Serial.print(pitch_octave(byte2)); + Serial.print(", channel="); + Serial.print(channel); + Serial.print(", velocity="); + Serial.println(byte3); + break; + + case 0x8: + Serial.print("Note Off: "); + Serial.println(byte2); + Serial.print(pitch_name(byte2)); + Serial.print(pitch_octave(byte2)); + Serial.print(", channel="); + Serial.print(channel); + Serial.print(", velocity="); + Serial.println(byte3); + + break; + + case 0xB: + Serial.print("Control change: control="); + Serial.print(byte2); + Serial.print(", value="); + Serial.print(byte3); + Serial.print(", channel="); + Serial.println(channel); + break; + + default: + Serial.print("Unhandled MIDI message: "); + Serial.print(header, HEX); + Serial.print("-"); + Serial.print(channel, HEX); + Serial.print("-"); + Serial.print(byte2, HEX); + Serial.print("-"); + Serial.println(byte3, HEX); + + break; + + } +} + + diff --git a/midisynth/dds_06/setTimers.ino b/midisynth/dds_06/setTimers.ino new file mode 100644 index 0000000..78c8034 --- /dev/null +++ b/midisynth/dds_06/setTimers.ino @@ -0,0 +1,57 @@ + +// Set timer TC4 and TC5 + +// TC4 is set up with a prescaler of 1024 : 48MHz/1024 = 46.875kHz +// The CC0 is set to 100 so ultimately this timer is happening every 469 HZ + +// TC5 is much faster at +// 48MHz/64 = 750kHz +// 750kHz/20 = 37,500 + + +// http://forum.arduino.cc/index.php?topic=599151.0 +void setupTimer4_5() { + // Feed GCLK0 to TC4 and TC5 + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK0 to TC4 and TC5 + GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0 + GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK0 to TC4 and TC5 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CC[0].reg = 100; // Set the TC4 CC0 register as the TOP value in match frequency mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest) + NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC4->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC4->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC4 interrupts + + TC4->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024, 48MHz/1024 = 46.875kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC4 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC4 + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + + + TC5->COUNT16.CC[0].reg = 20; // Set the TC5 CC0 register as the TOP value in match frequency mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC5_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC5 to 0 (highest) + NVIC_EnableIRQ(TC5_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC5->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC5->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC5 interrupts + + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV64 | // Set prescaler to 64, 48MHz/64 = 750 kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC5 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC5->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC5 + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization +} diff --git a/midisynth/dds_06/tables.h b/midisynth/dds_06/tables.h new file mode 100644 index 0000000..1ee775c --- /dev/null +++ b/midisynth/dds_06/tables.h @@ -0,0 +1,1565 @@ + +// Tables + +#ifndef _TABLES +#define _TABLES + +const PROGMEM char SinTable[] = +{ + 0, //0 + 3, //1 + 6, //2 + 9, //3 + 12, //4 + 15, //5 + 18, //6 + 21, //7 + 24, //8 + 27, //9 + 30, //10 + 33, //11 + 36, //12 + 39, //13 + 42, //14 + 45, //15 + 48, //16 + 51, //17 + 54, //18 + 57, //19 + 59, //20 + 62, //21 + 65, //22 + 67, //23 + 70, //24 + 73, //25 + 75, //26 + 78, //27 + 80, //28 + 82, //29 + 85, //30 + 87, //31 + 89, //32 + 91, //33 + 94, //34 + 96, //35 + 98, //36 + 100, //37 + 102, //38 + 103, //39 + 105, //40 + 107, //41 + 108, //42 + 110, //43 + 112, //44 + 113, //45 + 114, //46 + 116, //47 + 117, //48 + 118, //49 + 119, //50 + 120, //51 + 121, //52 + 122, //53 + 123, //54 + 123, //55 + 124, //56 + 125, //57 + 125, //58 + 126, //59 + 126, //60 + 126, //61 + 126, //62 + 126, //63 + 127, //64 + 126, //65 + 126, //66 + 126, //67 + 126, //68 + 126, //69 + 125, //70 + 125, //71 + 124, //72 + 123, //73 + 123, //74 + 122, //75 + 121, //76 + 120, //77 + 119, //78 + 118, //79 + 117, //80 + 116, //81 + 114, //82 + 113, //83 + 112, //84 + 110, //85 + 108, //86 + 107, //87 + 105, //88 + 103, //89 + 102, //90 + 100, //91 + 98, //92 + 96, //93 + 94, //94 + 91, //95 + 89, //96 + 87, //97 + 85, //98 + 82, //99 + 80, //100 + 78, //101 + 75, //102 + 73, //103 + 70, //104 + 67, //105 + 65, //106 + 62, //107 + 59, //108 + 57, //109 + 54, //110 + 51, //111 + 48, //112 + 45, //113 + 42, //114 + 39, //115 + 36, //116 + 33, //117 + 30, //118 + 27, //119 + 24, //120 + 21, //121 + 18, //122 + 15, //123 + 12, //124 + 9, //125 + 6, //126 + 3, //127 + 0, //128 + -3, //129 + -6, //130 + -9, //131 + -12, //132 + -15, //133 + -18, //134 + -21, //135 + -24, //136 + -27, //137 + -30, //138 + -33, //139 + -36, //140 + -39, //141 + -42, //142 + -45, //143 + -48, //144 + -51, //145 + -54, //146 + -57, //147 + -59, //148 + -62, //149 + -65, //150 + -67, //151 + -70, //152 + -73, //153 + -75, //154 + -78, //155 + -80, //156 + -82, //157 + -85, //158 + -87, //159 + -89, //160 + -91, //161 + -94, //162 + -96, //163 + -98, //164 + -100, //165 + -102, //166 + -103, //167 + -105, //168 + -107, //169 + -108, //170 + -110, //171 + -112, //172 + -113, //173 + -114, //174 + -116, //175 + -117, //176 + -118, //177 + -119, //178 + -120, //179 + -121, //180 + -122, //181 + -123, //182 + -123, //183 + -124, //184 + -125, //185 + -125, //186 + -126, //187 + -126, //188 + -126, //189 + -126, //190 + -126, //191 + -127, //192 + -126, //193 + -126, //194 + -126, //195 + -126, //196 + -126, //197 + -125, //198 + -125, //199 + -124, //200 + -123, //201 + -123, //202 + -122, //203 + -121, //204 + -120, //205 + -119, //206 + -118, //207 + -117, //208 + -116, //209 + -114, //210 + -113, //211 + -112, //212 + -110, //213 + -108, //214 + -107, //215 + -105, //216 + -103, //217 + -102, //218 + -100, //219 + -98, //220 + -96, //221 + -94, //222 + -91, //223 + -89, //224 + -87, //225 + -85, //226 + -82, //227 + -80, //228 + -78, //229 + -75, //230 + -73, //231 + -70, //232 + -67, //233 + -65, //234 + -62, //235 + -59, //236 + -57, //237 + -54, //238 + -51, //239 + -48, //240 + -45, //241 + -42, //242 + -39, //243 + -36, //244 + -33, //245 + -30, //246 + -27, //247 + -24, //248 + -21, //249 + -18, //250 + -15, //251 + -12, //252 + -9, //253 + -6, //254 + -4, //255 +}; + + + +const PROGMEM char TriangleTable[] = +{ + 0, //0 + 1, //1 + 3, //2 + 5, //3 + 7, //4 + 9, //5 + 11, //6 + 13, //7 + 15, //8 + 17, //9 + 19, //10 + 21, //11 + 23, //12 + 25, //13 + 27, //14 + 29, //15 + 31, //16 + 33, //17 + 35, //18 + 37, //19 + 39, //20 + 41, //21 + 43, //22 + 45, //23 + 47, //24 + 49, //25 + 51, //26 + 53, //27 + 55, //28 + 57, //29 + 59, //30 + 61, //31 + 63, //32 + 65, //33 + 67, //34 + 69, //35 + 71, //36 + 73, //37 + 75, //38 + 77, //39 + 79, //40 + 81, //41 + 83, //42 + 85, //43 + 87, //44 + 89, //45 + 91, //46 + 93, //47 + 95, //48 + 97, //49 + 99, //50 + 101, //51 + 103, //52 + 105, //53 + 107, //54 + 109, //55 + 111, //56 + 113, //57 + 115, //58 + 117, //59 + 119, //60 + 121, //61 + 123, //62 + 125, //63 + 127, //64 + 125, //65 + 123, //66 + 121, //67 + 119, //68 + 117, //69 + 115, //70 + 113, //71 + 111, //72 + 109, //73 + 107, //74 + 105, //75 + 103, //76 + 101, //77 + 99, //78 + 97, //79 + 95, //80 + 93, //81 + 91, //82 + 89, //83 + 87, //84 + 85, //85 + 83, //86 + 81, //87 + 79, //88 + 77, //89 + 75, //90 + 73, //91 + 71, //92 + 69, //93 + 67, //94 + 65, //95 + 63, //96 + 61, //97 + 59, //98 + 57, //99 + 55, //100 + 53, //101 + 51, //102 + 49, //103 + 47, //104 + 45, //105 + 43, //106 + 41, //107 + 39, //108 + 37, //109 + 35, //110 + 33, //111 + 31, //112 + 29, //113 + 27, //114 + 25, //115 + 23, //116 + 21, //117 + 19, //118 + 17, //119 + 15, //120 + 13, //121 + 11, //122 + 9, //123 + 7, //124 + 5, //125 + 3, //126 + 1, //127 + 0, //128 + -1, //129 + -3, //130 + -5, //131 + -7, //132 + -9, //133 + -11, //134 + -13, //135 + -15, //136 + -17, //137 + -19, //138 + -21, //139 + -23, //140 + -25, //141 + -27, //142 + -29, //143 + -31, //144 + -33, //145 + -35, //146 + -37, //147 + -39, //148 + -41, //149 + -43, //150 + -45, //151 + -47, //152 + -49, //153 + -51, //154 + -53, //155 + -55, //156 + -57, //157 + -59, //158 + -61, //159 + -63, //160 + -65, //161 + -67, //162 + -69, //163 + -71, //164 + -73, //165 + -75, //166 + -77, //167 + -79, //168 + -81, //169 + -83, //170 + -85, //171 + -87, //172 + -89, //173 + -91, //174 + -93, //175 + -95, //176 + -97, //177 + -99, //178 + -101, //179 + -103, //180 + -105, //181 + -107, //182 + -109, //183 + -111, //184 + -113, //185 + -115, //186 + -117, //187 + -119, //188 + -121, //189 + -123, //190 + -125, //191 + -127, //192 + -125, //193 + -123, //194 + -121, //195 + -119, //196 + -117, //197 + -115, //198 + -113, //199 + -111, //200 + -109, //201 + -107, //202 + -105, //203 + -103, //204 + -101, //205 + -99, //206 + -97, //207 + -95, //208 + -93, //209 + -91, //210 + -89, //211 + -87, //212 + -85, //213 + -83, //214 + -81, //215 + -79, //216 + -77, //217 + -75, //218 + -73, //219 + -71, //220 + -69, //221 + -67, //222 + -65, //223 + -63, //224 + -61, //225 + -59, //226 + -57, //227 + -55, //228 + -53, //229 + -51, //230 + -49, //231 + -47, //232 + -45, //233 + -43, //234 + -41, //235 + -39, //236 + -37, //237 + -35, //238 + -33, //239 + -31, //240 + -29, //241 + -27, //242 + -25, //243 + -23, //244 + -21, //245 + -19, //246 + -17, //247 + -15, //248 + -13, //249 + -11, //250 + -9, //251 + -7, //252 + -5, //253 + -3, //254 + -2, //255 +}; + +const PROGMEM char SquareTable[] = +{ + 127, //0 + 127, //1 + 127, //2 + 127, //3 + 127, //4 + 127, //5 + 127, //6 + 127, //7 + 127, //8 + 127, //9 + 127, //10 + 127, //11 + 127, //12 + 127, //13 + 127, //14 + 127, //15 + 127, //16 + 127, //17 + 127, //18 + 127, //19 + 127, //20 + 127, //21 + 127, //22 + 127, //23 + 127, //24 + 127, //25 + 127, //26 + 127, //27 + 127, //28 + 127, //29 + 127, //30 + 127, //31 + 127, //32 + 127, //33 + 127, //34 + 127, //35 + 127, //36 + 127, //37 + 127, //38 + 127, //39 + 127, //40 + 127, //41 + 127, //42 + 127, //43 + 127, //44 + 127, //45 + 127, //46 + 127, //47 + 127, //48 + 127, //49 + 127, //50 + 127, //51 + 127, //52 + 127, //53 + 127, //54 + 127, //55 + 127, //56 + 127, //57 + 127, //58 + 127, //59 + 127, //60 + 127, //61 + 127, //62 + 127, //63 + 127, //64 + 127, //65 + 127, //66 + 127, //67 + 127, //68 + 127, //69 + 127, //70 + 127, //71 + 127, //72 + 127, //73 + 127, //74 + 127, //75 + 127, //76 + 127, //77 + 127, //78 + 127, //79 + 127, //80 + 127, //81 + 127, //82 + 127, //83 + 127, //84 + 127, //85 + 127, //86 + 127, //87 + 127, //88 + 127, //89 + 127, //90 + 127, //91 + 127, //92 + 127, //93 + 127, //94 + 127, //95 + 127, //96 + 127, //97 + 127, //98 + 127, //99 + 127, //100 + 127, //101 + 127, //102 + 127, //103 + 127, //104 + 127, //105 + 127, //106 + 127, //107 + 127, //108 + 127, //109 + 127, //110 + 127, //111 + 127, //112 + 127, //113 + 127, //114 + 127, //115 + 127, //116 + 127, //117 + 127, //118 + 127, //119 + 127, //120 + 127, //121 + 127, //122 + 127, //123 + 127, //124 + 127, //125 + 127, //126 + 127, //127 + -125, //128 + -125, //129 + -125, //130 + -125, //131 + -125, //132 + -125, //133 + -125, //134 + -125, //135 + -125, //136 + -125, //137 + -125, //138 + -125, //139 + -125, //140 + -125, //141 + -125, //142 + -125, //143 + -125, //144 + -125, //145 + -125, //146 + -125, //147 + -125, //148 + -125, //149 + -125, //150 + -125, //151 + -125, //152 + -125, //153 + -125, //154 + -125, //155 + -125, //156 + -125, //157 + -125, //158 + -125, //159 + -125, //160 + -125, //161 + -125, //162 + -125, //163 + -125, //164 + -125, //165 + -125, //166 + -125, //167 + -125, //168 + -125, //169 + -125, //170 + -125, //171 + -125, //172 + -125, //173 + -125, //174 + -125, //175 + -125, //176 + -125, //177 + -125, //178 + -125, //179 + -125, //180 + -125, //181 + -125, //182 + -125, //183 + -125, //184 + -125, //185 + -125, //186 + -125, //187 + -125, //188 + -125, //189 + -125, //190 + -125, //191 + -125, //192 + -125, //193 + -125, //194 + -125, //195 + -125, //196 + -125, //197 + -125, //198 + -125, //199 + -125, //200 + -125, //201 + -125, //202 + -125, //203 + -125, //204 + -125, //205 + -125, //206 + -125, //207 + -125, //208 + -125, //209 + -125, //210 + -125, //211 + -125, //212 + -125, //213 + -125, //214 + -125, //215 + -125, //216 + -125, //217 + -125, //218 + -125, //219 + -125, //220 + -125, //221 + -125, //222 + -125, //223 + -125, //224 + -125, //225 + -125, //226 + -125, //227 + -125, //228 + -125, //229 + -125, //230 + -125, //231 + -125, //232 + -125, //233 + -125, //234 + -125, //235 + -125, //236 + -125, //237 + -125, //238 + -125, //239 + -125, //240 + -125, //241 + -125, //242 + -125, //243 + -125, //244 + -125, //245 + -125, //246 + -125, //247 + -125, //248 + -125, //249 + -125, //250 + -125, //251 + -125, //252 + -125, //253 + -125, //254 + -1, //255 +}; +const PROGMEM char SawTable[] = +{ + 127, //0 + 127, //1 + 126, //2 + 125, //3 + 124, //4 + 123, //5 + 122, //6 + 121, //7 + 120, //8 + 119, //9 + 118, //10 + 117, //11 + 116, //12 + 115, //13 + 114, //14 + 113, //15 + 112, //16 + 111, //17 + 110, //18 + 109, //19 + 108, //20 + 107, //21 + 106, //22 + 105, //23 + 104, //24 + 103, //25 + 102, //26 + 101, //27 + 100, //28 + 99, //29 + 98, //30 + 97, //31 + 96, //32 + 95, //33 + 94, //34 + 93, //35 + 92, //36 + 91, //37 + 90, //38 + 89, //39 + 88, //40 + 87, //41 + 86, //42 + 85, //43 + 84, //44 + 83, //45 + 82, //46 + 81, //47 + 80, //48 + 79, //49 + 78, //50 + 77, //51 + 76, //52 + 75, //53 + 74, //54 + 73, //55 + 72, //56 + 71, //57 + 70, //58 + 69, //59 + 68, //60 + 67, //61 + 66, //62 + 65, //63 + 64, //64 + 63, //65 + 62, //66 + 61, //67 + 60, //68 + 59, //69 + 58, //70 + 57, //71 + 56, //72 + 55, //73 + 54, //74 + 53, //75 + 52, //76 + 51, //77 + 50, //78 + 49, //79 + 48, //80 + 47, //81 + 46, //82 + 45, //83 + 44, //84 + 43, //85 + 42, //86 + 41, //87 + 40, //88 + 39, //89 + 38, //90 + 37, //91 + 36, //92 + 35, //93 + 34, //94 + 33, //95 + 32, //96 + 31, //97 + 30, //98 + 29, //99 + 28, //100 + 27, //101 + 26, //102 + 25, //103 + 24, //104 + 23, //105 + 22, //106 + 21, //107 + 20, //108 + 19, //109 + 18, //110 + 17, //111 + 16, //112 + 15, //113 + 14, //114 + 13, //115 + 12, //116 + 11, //117 + 10, //118 + 9, //119 + 8, //120 + 7, //121 + 6, //122 + 5, //123 + 4, //124 + 3, //125 + 2, //126 + 1, //127 + 0, //128 + 0, //129 + -1, //130 + -2, //131 + -3, //132 + -4, //133 + -5, //134 + -6, //135 + -7, //136 + -8, //137 + -9, //138 + -10, //139 + -11, //140 + -12, //141 + -13, //142 + -14, //143 + -15, //144 + -16, //145 + -17, //146 + -18, //147 + -19, //148 + -20, //149 + -21, //150 + -22, //151 + -23, //152 + -24, //153 + -25, //154 + -26, //155 + -27, //156 + -28, //157 + -29, //158 + -30, //159 + -31, //160 + -32, //161 + -33, //162 + -34, //163 + -35, //164 + -36, //165 + -37, //166 + -38, //167 + -39, //168 + -40, //169 + -41, //170 + -42, //171 + -43, //172 + -44, //173 + -45, //174 + -46, //175 + -47, //176 + -48, //177 + -49, //178 + -50, //179 + -51, //180 + -52, //181 + -53, //182 + -54, //183 + -55, //184 + -56, //185 + -57, //186 + -58, //187 + -59, //188 + -60, //189 + -61, //190 + -62, //191 + -63, //192 + -64, //193 + -65, //194 + -66, //195 + -67, //196 + -68, //197 + -69, //198 + -70, //199 + -71, //200 + -72, //201 + -73, //202 + -74, //203 + -75, //204 + -76, //205 + -77, //206 + -78, //207 + -79, //208 + -80, //209 + -81, //210 + -82, //211 + -83, //212 + -84, //213 + -85, //214 + -86, //215 + -87, //216 + -88, //217 + -89, //218 + -90, //219 + -91, //220 + -92, //221 + -93, //222 + -94, //223 + -95, //224 + -96, //225 + -97, //226 + -98, //227 + -99, //228 + -100, //229 + -101, //230 + -102, //231 + -103, //232 + -104, //233 + -105, //234 + -106, //235 + -107, //236 + -108, //237 + -109, //238 + -110, //239 + -111, //240 + -112, //241 + -113, //242 + -114, //243 + -115, //244 + -116, //245 + -117, //246 + -118, //247 + -119, //248 + -120, //249 + -121, //250 + -122, //251 + -123, //252 + -124, //253 + -125, //254 + -127, //255 +}; +const PROGMEM char RampTable[] = +{ + -127, //0 + -126, //1 + -125, //2 + -124, //3 + -123, //4 + -122, //5 + -121, //6 + -120, //7 + -119, //8 + -118, //9 + -117, //10 + -116, //11 + -115, //12 + -114, //13 + -113, //14 + -112, //15 + -111, //16 + -110, //17 + -109, //18 + -108, //19 + -107, //20 + -106, //21 + -105, //22 + -104, //23 + -103, //24 + -102, //25 + -101, //26 + -100, //27 + -99, //28 + -98, //29 + -97, //30 + -96, //31 + -95, //32 + -94, //33 + -93, //34 + -92, //35 + -91, //36 + -90, //37 + -89, //38 + -88, //39 + -87, //40 + -86, //41 + -85, //42 + -84, //43 + -83, //44 + -82, //45 + -81, //46 + -80, //47 + -79, //48 + -78, //49 + -77, //50 + -76, //51 + -75, //52 + -74, //53 + -73, //54 + -72, //55 + -71, //56 + -70, //57 + -69, //58 + -68, //59 + -67, //60 + -66, //61 + -65, //62 + -64, //63 + -63, //64 + -62, //65 + -61, //66 + -60, //67 + -59, //68 + -58, //69 + -57, //70 + -56, //71 + -55, //72 + -54, //73 + -53, //74 + -52, //75 + -51, //76 + -50, //77 + -49, //78 + -48, //79 + -47, //80 + -46, //81 + -45, //82 + -44, //83 + -43, //84 + -42, //85 + -41, //86 + -40, //87 + -39, //88 + -38, //89 + -37, //90 + -36, //91 + -35, //92 + -34, //93 + -33, //94 + -32, //95 + -31, //96 + -30, //97 + -29, //98 + -28, //99 + -27, //100 + -26, //101 + -25, //102 + -24, //103 + -23, //104 + -22, //105 + -21, //106 + -20, //107 + -19, //108 + -18, //109 + -17, //110 + -16, //111 + -15, //112 + -14, //113 + -13, //114 + -12, //115 + -11, //116 + -10, //117 + -9, //118 + -8, //119 + -7, //120 + -6, //121 + -5, //122 + -4, //123 + -3, //124 + -2, //125 + -1, //126 + 0, //127 + 0, //128 + 1, //129 + 2, //130 + 3, //131 + 4, //132 + 5, //133 + 6, //134 + 7, //135 + 8, //136 + 9, //137 + 10, //138 + 11, //139 + 12, //140 + 13, //141 + 14, //142 + 15, //143 + 16, //144 + 17, //145 + 18, //146 + 19, //147 + 20, //148 + 21, //149 + 22, //150 + 23, //151 + 24, //152 + 25, //153 + 26, //154 + 27, //155 + 28, //156 + 29, //157 + 30, //158 + 31, //159 + 32, //160 + 33, //161 + 34, //162 + 35, //163 + 36, //164 + 37, //165 + 38, //166 + 39, //167 + 40, //168 + 41, //169 + 42, //170 + 43, //171 + 44, //172 + 45, //173 + 46, //174 + 47, //175 + 48, //176 + 49, //177 + 50, //178 + 51, //179 + 52, //180 + 53, //181 + 54, //182 + 55, //183 + 56, //184 + 57, //185 + 58, //186 + 59, //187 + 60, //188 + 61, //189 + 62, //190 + 63, //191 + 64, //192 + 65, //193 + 66, //194 + 67, //195 + 68, //196 + 69, //197 + 70, //198 + 71, //199 + 72, //200 + 73, //201 + 74, //202 + 75, //203 + 76, //204 + 77, //205 + 78, //206 + 79, //207 + 80, //208 + 81, //209 + 82, //210 + 83, //211 + 84, //212 + 85, //213 + 86, //214 + 87, //215 + 88, //216 + 89, //217 + 90, //218 + 91, //219 + 92, //220 + 93, //221 + 94, //222 + 95, //223 + 96, //224 + 97, //225 + 98, //226 + 99, //227 + 100, //228 + 101, //229 + 102, //230 + 103, //231 + 104, //232 + 105, //233 + 106, //234 + 107, //235 + 108, //236 + 109, //237 + 110, //238 + 111, //239 + 112, //240 + 113, //241 + 114, //242 + 115, //243 + 116, //244 + 117, //245 + 118, //246 + 119, //247 + 120, //248 + 121, //249 + 122, //250 + 123, //251 + 124, //252 + 125, //253 + 126, //254 + 127, //255 +}; +const PROGMEM char NoiseTable[] = +{ + -62, //0 + -72, //1 + -92, //2 + -98, //3 + 98, //4 + -103, //5 + 96, //6 + -89, //7 + -29, //8 + -55, //9 + 98, //10 + -8, //11 + -118, //12 + 13, //13 + 11, //14 + -1, //15 + 76, //16 + -8, //17 + -116, //18 + 51, //19 + 33, //20 + -85, //21 + -43, //22 + -16, //23 + -114, //24 + -47, //25 + -63, //26 + -113, //27 + 109, //28 + -39, //29 + -127, //30 + -59, //31 + 0, //32 + 118, //33 + 70, //34 + 62, //35 + 54, //36 + 85, //37 + 51, //38 + 122, //39 + 60, //40 + 30, //41 + -126, //42 + -25, //43 + 71, //44 + -82, //45 + -11, //46 + 64, //47 + -95, //48 + -110, //49 + 127, //50 + 37, //51 + -14, //52 + -57, //53 + 51, //54 + -4, //55 + -47, //56 + -80, //57 + 110, //58 + 7, //59 + -117, //60 + 89, //61 + 65, //62 + -58, //63 + 50, //64 + -21, //65 + 33, //66 + -113, //67 + -22, //68 + 111, //69 + -46, //70 + 108, //71 + 112, //72 + -57, //73 + -111, //74 + 53, //75 + -21, //76 + -22, //77 + -127, //78 + -18, //79 + -9, //80 + 95, //81 + 88, //82 + 99, //83 + -17, //84 + -3, //85 + 74, //86 + 2, //87 + 123, //88 + -31, //89 + 53, //90 + -7, //91 + 91, //92 + -80, //93 + 15, //94 + -112, //95 + 114, //96 + 14, //97 + -115, //98 + -55, //99 + 22, //100 + 95, //101 + 21, //102 + 53, //103 + -105, //104 + -67, //105 + -25, //106 + 25, //107 + 13, //108 + 58, //109 + -121, //110 + -62, //111 + 103, //112 + 87, //113 + 109, //114 + 38, //115 + -79, //116 + -60, //117 + -16, //118 + -68, //119 + -91, //120 + 90, //121 + 112, //122 + -99, //123 + 118, //124 + 87, //125 + -61, //126 + -36, //127 + -40, //128 + -39, //129 + -30, //130 + 34, //131 + 83, //132 + -100, //133 + -43, //134 + -114, //135 + -54, //136 + -8, //137 + -36, //138 + -52, //139 + 71, //140 + 22, //141 + -33, //142 + 116, //143 + 9, //144 + 114, //145 + 24, //146 + -91, //147 + -48, //148 + -106, //149 + -2, //150 + -31, //151 + 103, //152 + 21, //153 + 117, //154 + 44, //155 + 115, //156 + -59, //157 + 53, //158 + 97, //159 + 124, //160 + 66, //161 + 120, //162 + -44, //163 + 57, //164 + -96, //165 + -24, //166 + 46, //167 + 32, //168 + 111, //169 + -56, //170 + -123, //171 + 46, //172 + -11, //173 + 97, //174 + -70, //175 + -12, //176 + -89, //177 + -81, //178 + 24, //179 + -29, //180 + -23, //181 + 77, //182 + 42, //183 + -40, //184 + 8, //185 + -98, //186 + -35, //187 + -21, //188 + 116, //189 + 61, //190 + -41, //191 + 116, //192 + 66, //193 + -88, //194 + 22, //195 + 95, //196 + -31, //197 + 40, //198 + -51, //199 + -78, //200 + 28, //201 + 3, //202 + 124, //203 + 92, //204 + 81, //205 + -27, //206 + 78, //207 + 65, //208 + -16, //209 + -116, //210 + -73, //211 + -126, //212 + 55, //213 + -76, //214 + 78, //215 + 17, //216 + 43, //217 + 66, //218 + -24, //219 + 117, //220 + -38, //221 + -76, //222 + -10, //223 + -37, //224 + -47, //225 + -56, //226 + 33, //227 + 94, //228 + -40, //229 + 107, //230 + 36, //231 + -104, //232 + -11, //233 + -27, //234 + -23, //235 + 105, //236 + -96, //237 + 68, //238 + -25, //239 + 7, //240 + 67, //241 + 6, //242 + -69, //243 + 70, //244 + -10, //245 + 10, //246 + 5, //247 + 42, //248 + 120, //249 + -71, //250 + -122, //251 + -86, //252 + 113, //253 + 112, //254 + 119, //255 +}; +#endif diff --git a/nandsynth/M0_Simple_Synth_09/M0_Simple_Synth_09.ino b/nandsynth/M0_Simple_Synth_09/M0_Simple_Synth_09.ino index 70e3d80..b1abef3 100644 --- a/nandsynth/M0_Simple_Synth_09/M0_Simple_Synth_09.ino +++ b/nandsynth/M0_Simple_Synth_09/M0_Simple_Synth_09.ino @@ -17,7 +17,7 @@ Added: - a Vibrato effect + a Vibrato effect. But just one one of the cores/voices */ /* @@ -33,7 +33,8 @@ // The code is just doing the squarewaves at the moment with very simple counters. // In the interrupt, we just count the number of ticks here until flipping the bit. -// LFO Counters. minLFO is actually a high number because its a larger tick to +// LFO Counters. minLFO is actually a high number because it takes more ticks to flip the +// counter. # define maxLFO 40 # define minLFO 500 diff --git a/nandsynth/M0_Simple_Synth_09/images/circuit.svg b/nandsynth/M0_Simple_Synth_09/images/circuit.svg deleted file mode 100644 index 5c5bc36..0000000 --- a/nandsynth/M0_Simple_Synth_09/images/circuit.svg +++ /dev/null @@ -1,774 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - 5v - - - - - - - - - - - - - - - - - - - 5v - - - - - - - - - - - LFO on - LFO CC - HF CC - - - - - - - - - - - - - - - - - - - - - - 5v - - - - - - - - - - - - - - - - - - - 5v - - - - - - - - - - - LFO on - LFO CC - HF CC - - - - - - mix - - - - diff --git a/nandsynth/M0_Simple_Synth_10/M0_Simple_Synth_10.ino b/nandsynth/M0_Simple_Synth_10/M0_Simple_Synth_10.ino new file mode 100644 index 0000000..2e330a9 --- /dev/null +++ b/nandsynth/M0_Simple_Synth_10/M0_Simple_Synth_10.ino @@ -0,0 +1,507 @@ + +#include "MIDIUSB.h" +#include +/* + #include "pitchToFrequency.h" +*/ + +/** + M0 Trinket Synth - Exercise 10 + + Two Squarewave oscillator(2 Cores) with 3 CCs each + - HfCC - CC to control pitch + - LfoCC - CC to control LFO Frequency + - LfoOnCC - CC to turn core on/off/LFO so its always on, always off or squarewave LFO + + + CC for the mixer - Toggle Mixer to be sum/nand/xor + So we had up to 7 knobs. + + +*/ + +/* + Note some of the boilerplate/extra stuff as been moved to other .ino files. Arduino IDE just combines them + with the dir filename.ino first and the remaining in alphabetical order. + +*/ + + +// Setup Onboard Dot +#define NUMPIXELS 1 // Number of LEDs in strip + +// The code is just doing the squarewaves at the moment with very simple counters. +// In the interrupt, we just count the number of ticks here until flipping the bit. + +// LFO Counters. minLFO is actually a high number because its a larger tick to +# define maxLFO 40 +# define minLFO 500 + +# define maxHF 70 +# define minHF 800 + + +# define CORE_COUNT 2 +# define PARAMETER_COUNT 13 + +# define CORE1 0 +# define CORE2 1 + +# define ALWAYS_ON 1 +# define LFO_ON 2 +# define ALWAYS_OFF 3 + +# define CC_LFO1 10 +# define CC_HF1 74 +# define CC_LFO_STATE1 71 +# define CC_TRILL1 44 + +# define CC_LFO2 114 +# define CC_HF2 18 +# define CC_LFO_STATE2 19 +# define CC_TRILL2 45 + +# define CC_MIX_MODE 7 + +volatile uint8_t mix_mode_value = 10; // default on at 50/50 + + +typedef struct CoreState { + uint8_t lfoCC; + uint32_t lfoCounter; + uint8_t lfoState; // counts each time the compare value is set. + uint8_t lfoCounterCompare; + + + uint8_t hfCC; + uint32_t hfCounter; + uint8_t hfState; // counts each time the compare value is set. Lowest bit is on/off + uint8_t hfCounterCompare; + boolean doTrill; + uint8_t hfTrill; // modulation value to add to hfValueCompare + + + uint8_t lfoOnCC; + uint8_t lfoSwitchState; + uint8_t color; +}; + + +// using global memory. You could use local variables in loop as well if your +// good with pointers. + +// Initialize with a random speed and silence count +volatile CoreState coreArray[] = { + { + // LFO CC = 10; + // initialize at 91 + CC_LFO1, 0, 0, random(maxLFO, minLFO) , + + // HF CC = 74; + CC_HF1, 0, 0, random(maxHF, minHF), false, 0, + + // LFO STATE CC = 71; + CC_LFO_STATE1, LFO_ON, 0x00 + }, + // CORE 2 + { + // LFO CC = 114; + // initialize at 130 + CC_LFO2, 0, 0, random(maxLFO, minLFO), + + // LFO CC = 18; + CC_HF2, 0, 0, random(maxHF, minHF), false, 0, + + // LFO ON CC = 19; + CC_LFO_STATE2, LFO_ON, 0x00 + }, +}; + + +// Here's how to control the LEDs from any two pins: +#define DATAPIN 7 +#define CLOCKPIN 8 + +Adafruit_DotStar strip = Adafruit_DotStar( + NUMPIXELS, DATAPIN, CLOCKPIN, DOTSTAR_BGR); + +// Fix Serial for SAMD +#if defined(ARDUINO_SAMD_ZERO) && defined(SERIAL_PORT_USBVIRTUAL) +// Required for Serial on Zero based boards +#define Serial SERIAL_PORT_USBVIRTUAL +#endif + + + + + +/* + TC4 LFO Interrupt + + Manipulates the LFO state which is either + - Always OFF + - Always ON + - LFO-ing Squarewave on off. Note, this is not a bool, but a value, so later we can use it to manipulate Amplitude + + DID I just copy paste the code twice...yes + Force of habit. Making it a function only adds a level of indirection to the interrupt code (wasted CPU) + and + Sketch uses 14156 bytes (5%) of program storage space. Maximum is 262144 bytes. + + so its not like we are hurting for program storage +*/ + +void TC4_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC4->COUNT16.INTFLAG.bit.OVF && TC4->COUNT16.INTENSET.bit.OVF) + { + // Put your timer overflow (OVF) code here.... + + if (coreArray[CORE1].lfoSwitchState == ALWAYS_ON) { + // LFO CODE. Always on + coreArray[CORE1].lfoState = 127; + } else { + if (coreArray[CORE1].lfoSwitchState == LFO_ON) { + // LFO CODE. When we hit the counter, flip the state bool (and the color of the light) + + if (coreArray[CORE1].lfoCounter > coreArray[CORE1].lfoCounterCompare) { + coreArray[CORE1].lfoState++; + coreArray[CORE1].lfoCounter = 0; + } + coreArray[CORE1].lfoCounter++; + } else { + // LFO CODE. Always off + coreArray[CORE1].lfoState = 0; + } + } + + if (coreArray[CORE2].lfoSwitchState == ALWAYS_ON) { + // LFO CODE. Always on + coreArray[CORE2].lfoState = 127; + } else { + if (coreArray[CORE2].lfoSwitchState == LFO_ON) { + // LFO CODE. When we hit the counter, flip the state bool (and the color of the light) + + if (coreArray[CORE2].lfoCounter > coreArray[CORE2].lfoCounterCompare) { + coreArray[CORE2].lfoState++; + coreArray[CORE2].lfoCounter = 0; + } + coreArray[CORE2].lfoCounter++; + } else { + // LFO CODE. Always off + coreArray[CORE2].lfoState = 0; + } + } + + TC4->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + } +} + +/* + High Frequency Interrupt + This is the interrupt that controls the actual signal + + Frequency is determined by countdown timers. The Larger the number, the lower the freq. + LFO is checked here as well as basically an on/off thing. + + Value is finally mixed with one of three strategies + - NAND + - SUM + - XOR +*/ + +void TC5_Handler() // Interrupt Service Routine (ISR) for timer TC4 +{ + // Check for overflow (OVF) interrupt + if (TC5->COUNT16.INTFLAG.bit.OVF && TC5->COUNT16.INTENSET.bit.OVF) + { + // Put your timer overflow (OVF) code here.... + + // Higher Frequency Interrupt. + + //CORE 1 + if (coreArray[CORE1].hfCounter > (coreArray[CORE1].hfCounterCompare + coreArray[CORE1].hfTrill)) { + coreArray[CORE1].hfState++; + coreArray[CORE1].hfCounter = 0; + + // Modulate if trill is on. Really, we are just messing with the counters + if (coreArray[CORE1].doTrill == true) { + if (coreArray[CORE1].hfTrill > 8) { + coreArray[CORE1].hfTrill = 0; + } + if (coreArray[CORE1].hfState % 32 == 1) { + coreArray[CORE1].hfTrill++; + } + } + } + coreArray[CORE1].hfCounter++; + + boolean value1 = ( (coreArray[CORE1].lfoState % 2 == 1) && (coreArray[CORE1].hfState % 2 == 1)); + + //CORE 2 + if (coreArray[CORE2].hfCounter > (coreArray[CORE2].hfCounterCompare + coreArray[CORE2].hfTrill)) { + coreArray[CORE2].hfState++; + coreArray[CORE2].hfCounter = 0; + + // Modulate if trill is on. Really, we are just messing with the counters + if (coreArray[CORE2].doTrill == true) { + if (coreArray[CORE2].hfTrill > 8) { + coreArray[CORE2].hfTrill = 0; + } + if (coreArray[CORE2].hfState % 32 == 1) { + coreArray[CORE2].hfTrill++; + } + } + + } + coreArray[CORE2].hfCounter++; + + boolean value2 = ( (coreArray[CORE2].lfoState % 2 == 1) && (coreArray[CORE2].hfState % 2 == 1)); + + + if (mix_mode_value < 45) { + + // NAND MIXER + if ( !value1 && !value2) { + analogWrite(A0, 127); + } else { + analogWrite(A0, 0); + } + } else { + + if (mix_mode_value < 100 ) { + + // SUM mixer + + int value = 0; + if (value1 ) { + value = 63; + } + if (value2 ) { + value = value + 64; + } + + analogWrite(A0, value); + + } else { + + // XOR Mixer + + if ( (value1 && !value2) || (!value1 && value2) ) { + analogWrite(A0, 127); + } else { + analogWrite(A0, 0); + } + } + } + + TC5->COUNT16.INTFLAG.reg = TC_INTFLAG_OVF; // Clear the OVF interrupt flag + } +} + + +void setup() { + Serial.begin(115200); + Serial.println("Setting up: Version 05"); + + strip.begin(); // Initialize pins for output + strip.show(); // Turn all LEDs off ASAP + + setupTimer4_5(); + +} + + +// Wrap Map into a function that is a little 1-logish. Simple break it a bit in ranges. +// Assumes a midi note in the range of 0-127 and makes it kinda 1-log(x) without a whole lot of +// processing. +// +// +int mapMidiLowBudget(int value, int v1, int v2) { + int octave = v1 - v2; + int point1 = v1 - (octave / 2) ; + + if (value < 33) { + return map(value, 0, 32, v1, point1); + } else { + return map(value, 32, 127, point1, v2); + } +} + + +// 0xB +void controlChange(byte channel, byte control, byte value) { + + logData(0xB, channel, control, value) ; // optional + + + // Is LFO CC + if (control == coreArray[CORE1].lfoCC) { + + + coreArray[CORE1].lfoCounterCompare = mapMidiLowBudget(value, minLFO, maxLFO); + return; + } + + if (control == coreArray[CORE2].lfoCC) { + coreArray[CORE2].lfoCounterCompare = mapMidiLowBudget(value, minLFO, maxLFO); + return; + } + + // Is HF CC + if (control == coreArray[CORE1].hfCC) { + coreArray[CORE1].hfCounterCompare = mapMidiLowBudget(value, minHF, maxHF); + return; + } + + + if (control == coreArray[CORE2].hfCC) { + coreArray[CORE2].hfCounterCompare = mapMidiLowBudget(value, minHF, maxHF); + return; + } + + + if (control == CC_MIX_MODE) { + Serial.print("mix_mode_value:"); + Serial.println(value); + mix_mode_value = value; + } + + + // CC to control LFO + // 0-50 OFF NO sound + // 50-100 LFO on + // 100 + NO LFO always on + + if (control == coreArray[CORE1].lfoOnCC) { + if (value > 100) { + coreArray[CORE1].lfoSwitchState = ALWAYS_ON; + } else { + if (value > 50) { + coreArray[CORE1].lfoSwitchState = LFO_ON; + } else { + coreArray[CORE1].lfoSwitchState = ALWAYS_OFF; + } + } + + } + + if (control == coreArray[CORE2].lfoOnCC) { + if (value > 100) { + coreArray[CORE2].lfoSwitchState = ALWAYS_ON; + } else { + if (value > 50) { + coreArray[CORE2].lfoSwitchState = LFO_ON; + } else { + coreArray[CORE2].lfoSwitchState = ALWAYS_OFF; + } + } + } + +} + +// 0x9 +void noteOn(byte channel, byte pitch, byte velocity) { + + // Channel 0 check is optional. Im not sure why Im getting stray notes on initialization + if (channel == 0) { + if (pitch == CC_TRILL1) { + Serial.print("Note on 1:"); + Serial.println(pitch); + coreArray[CORE1].doTrill = true; + + } + if (pitch == CC_TRILL2) { + Serial.print("Note on 2:"); + Serial.println(pitch); + coreArray[CORE2].doTrill = true; + } + } +} + +// 0x8 +void noteOff(byte channel, byte pitch, byte velocity) { + if (channel == 0) { + if (pitch == CC_TRILL1) { + Serial.print("Note off 1:"); + Serial.println(pitch); + coreArray[CORE1].doTrill = false; + coreArray[CORE1].hfTrill = 0; + + + } + if (pitch == CC_TRILL2) { + Serial.print("Note on 2:"); + Serial.println(pitch); + coreArray[CORE2].doTrill = false; + coreArray[CORE2].hfTrill = 0; + + } + } +} + + +void loop() { + + Serial.println("Enter Loop:"); + + initSequence(); // Blinky intro + + while (true) { + + setColor(CORE1); + setColor(CORE2); + strip.setPixelColor(0, coreArray[CORE1].color, coreArray[CORE2].color, 0); //set the pixel colors + + strip.show(); + + + // Midi packet taken from + // midiEventPacket_t rx = MidiUSB.read(); + // + // First parameter is the event type (0x09 = note on, 0x08 = note off). + // Second parameter is note-on/note-off, combined with the channel. + // Channel can be anything between 0-15. Typically reported to the user as 1-16. + // Third parameter is the note number (48 = middle C). + // Fourth parameter is the velocity (64 = normal, 127 = fastest). + + midiEventPacket_t rx = MidiUSB.read(); + switch (rx.header) { + case 0: + break; //No pending events + + case 0xB: + controlChange( + rx.byte1 & 0xF, //channel + rx.byte2, //control + rx.byte3 //value + ); + break; + + case 0x9: + noteOn( + rx.byte1 & 0xF, //channel + rx.byte2, //pitch + rx.byte3 //velocity + ); + + break; + + case 0x8: + noteOff( + rx.byte1 & 0xF, //channel + rx.byte2, //pitch + rx.byte3 //velocity + ); + + break; + + default: + // If your curious + //logData(rx.header, rx.byte1, rx.byte2, rx.byte3) ; + + break; + } + } +} diff --git a/nandsynth/M0_Simple_Synth_10/README.md b/nandsynth/M0_Simple_Synth_10/README.md new file mode 100644 index 0000000..ae447bf --- /dev/null +++ b/nandsynth/M0_Simple_Synth_10/README.md @@ -0,0 +1,23 @@ +# M0_Simple_Synth_09 + +This was an experiment with a vibrato of sorts. +BAsically, you can incr or decr your bounds in the LFO loop for all kinds of neat effects. + + +In this case, I added it just to the first core to see what it sounds like. +I was planning on refactoring the code to put this in a loop, but did not have time +for that. + +At this point, the code is pretty wacky/specialized anyways. +We are no longer at a point where we are simulating a NAND circuit that much. + + + + +# Example + +![example](https://www.youtube.com/watch?v=T83fdontQuo) + +You can also have Ableton automate a lot of your steps + +![Driven by Ableton](https://www.youtube.com/watch?v=Z0RH7yxyefg) \ No newline at end of file diff --git a/nandsynth/M0_Simple_Synth_10/colorSet.ino b/nandsynth/M0_Simple_Synth_10/colorSet.ino new file mode 100644 index 0000000..d447e1c --- /dev/null +++ b/nandsynth/M0_Simple_Synth_10/colorSet.ino @@ -0,0 +1,18 @@ +void setColor(byte coreIndex) { + + if (coreArray[coreIndex].lfoSwitchState == ALWAYS_ON) { + coreArray[coreIndex].color = 0xFF; + } else { + if (coreArray[coreIndex].lfoSwitchState == LFO_ON) { + + if (coreArray[coreIndex].lfoState % 2 == 0) { + coreArray[coreIndex].color = 0x00; + } else { + coreArray[coreIndex].color = 0xFF; + } + } else { + // LFO CODE. Always off + coreArray[coreIndex].color = 0x00; + } + } +} diff --git a/nandsynth/M0_Simple_Synth_10/initSequnce.ino b/nandsynth/M0_Simple_Synth_10/initSequnce.ino new file mode 100644 index 0000000..47ed94d --- /dev/null +++ b/nandsynth/M0_Simple_Synth_10/initSequnce.ino @@ -0,0 +1,20 @@ +// Pretty sequence to know it started up. Just Call it from init or the loop code (assuming your loop has a while-true loop in there as well) + +// This is optional. But I like to see a little sequence indicator to know that it uploaded or restarted. + +void initSequence() { + strip.setPixelColor(0, 0x1F0000); // red + strip.show(); + delay(500); + + strip.setPixelColor(0, 0x001F00); // green + strip.show(); + delay(050); + + strip.setPixelColor(0, 0x00001F); // blue + strip.show(); + delay(500); + + strip.setPixelColor(0, 0x000000); // blue + strip.show(); +} diff --git a/nandsynth/M0_Simple_Synth_10/logging.ino b/nandsynth/M0_Simple_Synth_10/logging.ino new file mode 100644 index 0000000..426d1f6 --- /dev/null +++ b/nandsynth/M0_Simple_Synth_10/logging.ino @@ -0,0 +1,69 @@ +// Utils to show the key name and Midi logging in the serial port +// +// +const char* pitch_name(byte pitch) { + static const char* names[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"}; + return names[pitch % 12]; +} + +int pitch_octave(byte pitch) { + return (pitch / 12) - 1; +} + + +void logData(byte header, byte channel, byte byte2, byte byte3) { + + switch (header) { + case 0: + return; + + + case 0x9: + + Serial.print("Note On: "); + Serial.println(byte2); + Serial.print(pitch_name(byte2)); + Serial.print(pitch_octave(byte2)); + Serial.print(", channel="); + Serial.print(channel); + Serial.print(", velocity="); + Serial.println(byte3); + break; + + case 0x8: + Serial.print("Note Off: "); + Serial.println(byte2); + Serial.print(pitch_name(byte2)); + Serial.print(pitch_octave(byte2)); + Serial.print(", channel="); + Serial.print(channel); + Serial.print(", velocity="); + Serial.println(byte3); + + break; + + case 0xB: + Serial.print("Control change: control="); + Serial.print(byte2); + Serial.print(", value="); + Serial.print(byte3); + Serial.print(", channel="); + Serial.println(channel); + break; + + default: + Serial.print("Unhandled MIDI message: "); + Serial.print(header, HEX); + Serial.print("-"); + Serial.print(channel, HEX); + Serial.print("-"); + Serial.print(byte2, HEX); + Serial.print("-"); + Serial.println(byte3, HEX); + + break; + + } +} + + diff --git a/nandsynth/M0_Simple_Synth_10/setTimers.ino b/nandsynth/M0_Simple_Synth_10/setTimers.ino new file mode 100644 index 0000000..7311807 --- /dev/null +++ b/nandsynth/M0_Simple_Synth_10/setTimers.ino @@ -0,0 +1,61 @@ +// Set timer TC4 and TC5 + +// TC4 is set up with a prescaler of 1024 : 48MHz/1024 = 46.875kHz +// The CC0 is set to 100 so ultimately this timer is happening every 469 HZ +// The Basic strategy for the LFO is to track an ADDITIONAL counter and flip the +// LFO value accordingly. +// # define minLFO 500 means that we flip the LFO bit at +// 469/( 500 * 2) = .46 HZ. +// # define maxLFO 40 means that we flip the LFO bit at +// 469/( 40 * 2) = 5.8625 HZ. + +// TC5 is much faster at +// 48MHz/64 = 750kHz + + +// http://forum.arduino.cc/index.php?topic=599151.0 +void setupTimer4_5() { + // Feed GCLK0 to TC4 and TC5 + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | // Enable GCLK0 to TC4 and TC5 + GCLK_CLKCTRL_GEN_GCLK0 | // Select GCLK0 + GCLK_CLKCTRL_ID_TC4_TC5; // Feed the GCLK0 to TC4 and TC5 + while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CC[0].reg = 100; // Set the TC4 CC0 register as the TOP value in match frequency mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC4_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC4 to 0 (highest) + NVIC_EnableIRQ(TC4_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC4->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC4->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC4 interrupts + + TC4->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV1024 | // Set prescaler to 1024, 48MHz/1024 = 46.875kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC4 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC4->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC4 + while (TC4->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + + + TC5->COUNT16.CC[0].reg = 10; // Set the TC5 CC0 register as the TOP value in match frequency mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + NVIC_SetPriority(TC5_IRQn, 0); // Set the Nested Vector Interrupt Controller (NVIC) priority for TC5 to 0 (highest) + NVIC_EnableIRQ(TC5_IRQn); // Connect TC4 to Nested Vector Interrupt Controller (NVIC) + + TC5->COUNT16.INTFLAG.reg |= TC_INTFLAG_OVF; // Clear the interrupt flags + TC5->COUNT16.INTENSET.reg = TC_INTENSET_OVF; // Enable TC5 interrupts + + TC5->COUNT16.CTRLA.reg |= TC_CTRLA_PRESCSYNC_PRESC | // Reset timer on the next prescaler clock + TC_CTRLA_PRESCALER_DIV64 | // Set prescaler to 64, 48MHz/64 = 750 kHz + TC_CTRLA_WAVEGEN_MFRQ | // Put the timer TC5 into match frequency (MFRQ) mode + TC_CTRLA_MODE_COUNT16; // Set the timer to 16-bit mode + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization + + TC5->COUNT16.CTRLA.bit.ENABLE = 1; // Enable TC5 + while (TC5->COUNT16.STATUS.bit.SYNCBUSY); // Wait for synchronization +}