CVtoOSC Converter for Nucleo F303K8

Dependencies:   DebouncedInterrupt MIDI mbed osc-cnmat BufferedSerial

OSC to CV Converter

http://gtbts.tumblr.com/post/142840140501/cvtoosc-converter-for-modular-synthesizer

main.cpp

Committer:
casiotone401
Date:
2016-02-20
Revision:
2:7997fb939580
Parent:
1:0a963a78f2bd

File content as of revision 2:7997fb939580:

/*
    CVtoOSC&MIDI Converter for Nucleo F303K8
    https://developer.mbed.org/platforms/ST-Nucleo-F303K8/
*/

#pragma O3
#pragma Otime

#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string>

#include "mbed.h"
#include "BufferedSerial.h"
#include "DebouncedInterrupt.h"
#include "MIDI.h"
#include "OSCBundle.h"

//-------------------------------------------------------------
// Macros

#define MIDI_OFFSET          4
#define MAP_OFFSET           0
#define CALIB_OFFSET        37

#define QUAN_RES1          116      // Quantize voltage Steps
#define QUAN_RES2           68
#define QUAN_RES3           46
#define QUAN_RES4           40
#define QUAN_RES5           68
#define QUAN_RES6           68  
#define QUAN_RES7           16
#define QUAN_RES8           58

#define Lin                 0        // Linear LinearCV
#define Chr                 1        // Chromatic
#define Maj                 2        // Major
#define M7                  3        // Major7
#define Min7                4        // Minor7
#define Dor                 5        // Dorian
#define Min                 6        // Minor
#define S5th                7        // 5th
#define Wht                 8        // Wholetone

#define SCALE_TOTAL         9

#define SEND_BUFF_SIZE   1024        // OSC send buffer size
#define WAIT_SEND          20        // wait time(ms) for esp8266 transmission complete

#define MIDI_CHANNEL        1        // MIDI channel

//-------------------------------------------------------------
// Global Variables

// Silentway Calibration Data Mapping
// http://www.expert-sleepers.co.uk/silentway.html

//  Chromatic Scale
const float calibMap1[QUAN_RES1] = {
0.00076928,   0.00900736,   0.01724544,   0.02548352,   0.03372160,
0.04195968,   0.05019776,   0.05843584,   0.06667392,   0.07491200,
0.08315008,   0.09138816,   0.09962624,   0.10786432,   0.11610240,
0.12434047,   0.13258974,   0.14083999,   0.14909023,   0.15734047,
0.16559070,   0.17384095,   0.18209119,   0.19034143,   0.19859168,
0.20684192,   0.21509215,   0.22334240,   0.23159264,   0.23984288,
0.24809311,   0.25634655,   0.26460093,   0.27285531,   0.28110969,
0.28936407,   0.29761845,   0.30587283,   0.31412721,   0.32238159,
0.33063596,   0.33889034,   0.34714472,   0.35539910,   0.36365348,
0.37190786,   0.38017464,   0.38844886,   0.39672306,   0.40499726,
0.41327149,   0.42154568,   0.42981988,   0.43809411,   0.44636831,
0.45464250,   0.46291673,   0.47119093,   0.47946513,   0.48773935,
0.49601355,   0.50430328,   0.51260746,   0.52091163,   0.52921581,
0.53751999,   0.54582411,   0.55412829,   0.56243247,   0.57073665,
0.57904083,   0.58734500,   0.59564912,   0.60395330,   0.61225748,
0.62056166,   0.62890279,   0.63728637,   0.64566994,   0.65405351,
0.66243708,   0.67082065,   0.67920423,   0.68758780,   0.69597137,
0.70435494,   0.71273851,   0.72112209,   0.72950566,   0.73788923,
0.74627280,   0.75476575,   0.76334614,   0.77192658,   0.78050703,
0.78908741,   0.79766786,   0.80624831,   0.81482869,   0.82340914,
0.83198959,   0.84056997,   0.84915042,   0.85773087,   0.86631125,
0.87489170,   0.88425636,   0.89363104,   0.90300572,   0.91238040,
0.92175508,   0.93112975,   0.94050443,   0.94987911,   0.95925385,
0.96862853
};

//  Major Scale
const float calibMap2[QUAN_RES2] = {
calibMap1[0], calibMap1[2], calibMap1[4], calibMap1[5], calibMap1[7],
calibMap1[9], calibMap1[11], calibMap1[12], calibMap1[14], calibMap1[16],
calibMap1[17], calibMap1[19], calibMap1[21], calibMap1[23], calibMap1[24],
calibMap1[26], calibMap1[28], calibMap1[29], calibMap1[31], calibMap1[33],
calibMap1[35], calibMap1[36], calibMap1[38], calibMap1[40], calibMap1[41],
calibMap1[43], calibMap1[45], calibMap1[47], calibMap1[48], calibMap1[50],
calibMap1[52], calibMap1[53], calibMap1[55], calibMap1[57], calibMap1[59],
calibMap1[60], calibMap1[62], calibMap1[64], calibMap1[65], calibMap1[67],
calibMap1[69], calibMap1[71], calibMap1[72], calibMap1[74], calibMap1[76],
calibMap1[77], calibMap1[79], calibMap1[81], calibMap1[83], calibMap1[84],
calibMap1[86], calibMap1[88], calibMap1[89], calibMap1[91], calibMap1[93],
calibMap1[95], calibMap1[96], calibMap1[98], calibMap1[100], calibMap1[101],
calibMap1[103], calibMap1[105], calibMap1[107], calibMap1[108], calibMap1[110],
calibMap1[112], calibMap1[113], calibMap1[115]
};

//  M7(9)
const float calibMap3[QUAN_RES3] = {
calibMap1[0],  calibMap1[4], calibMap1[7], calibMap1[11], calibMap1[12], 
calibMap1[14], calibMap1[16], calibMap1[19], calibMap1[23], calibMap1[24],
calibMap1[26], calibMap1[28], calibMap1[31], calibMap1[35], calibMap1[36], 
calibMap1[38], calibMap1[40], calibMap1[43], calibMap1[47], calibMap1[48], 
calibMap1[50], calibMap1[52], calibMap1[55], calibMap1[59], calibMap1[60], 
calibMap1[62], calibMap1[64], calibMap1[67], calibMap1[71], calibMap1[72], 
calibMap1[76], calibMap1[79], calibMap1[83], calibMap1[84], calibMap1[86], 
calibMap1[88], calibMap1[91], calibMap1[95], calibMap1[96], calibMap1[100],
calibMap1[103], calibMap1[107], calibMap1[108], calibMap1[110], calibMap1[112], 
calibMap1[115]
};

//  m7(9)
const float calibMap4[QUAN_RES4] = {
calibMap1[0], calibMap1[3], calibMap1[7], calibMap1[10], calibMap1[12], 
calibMap1[15], calibMap1[19], calibMap1[22], calibMap1[26], calibMap1[27], 
calibMap1[31], calibMap1[34], calibMap1[36], calibMap1[38], calibMap1[39], 
calibMap1[43], calibMap1[46], calibMap1[50], calibMap1[53], calibMap1[55], 
calibMap1[58], calibMap1[60], calibMap1[63], calibMap1[67], calibMap1[70], 
calibMap1[72], calibMap1[74], calibMap1[75], calibMap1[79], calibMap1[82], 
calibMap1[86], calibMap1[89], calibMap1[91], calibMap1[94], calibMap1[96], 
calibMap1[99],  calibMap1[103], calibMap1[106], calibMap1[110], calibMap1[113]
};

//  Dorian Scale
const float calibMap5[QUAN_RES5] = {
calibMap1[0], calibMap1[2], calibMap1[3], calibMap1[5], calibMap1[7],
calibMap1[9], calibMap1[10], calibMap1[12], calibMap1[14], calibMap1[15],
calibMap1[17], calibMap1[19], calibMap1[20], calibMap1[21], calibMap1[24],
calibMap1[26], calibMap1[27], calibMap1[29], calibMap1[31], calibMap1[33],
calibMap1[34], calibMap1[36], calibMap1[38], calibMap1[39], calibMap1[41],
calibMap1[43], calibMap1[45], calibMap1[46], calibMap1[48], calibMap1[50],
calibMap1[51], calibMap1[53], calibMap1[55], calibMap1[57], calibMap1[58],
calibMap1[60], calibMap1[62], calibMap1[63], calibMap1[65], calibMap1[67],
calibMap1[69], calibMap1[70], calibMap1[72], calibMap1[74], calibMap1[75],
calibMap1[77], calibMap1[79], calibMap1[81], calibMap1[82], calibMap1[84],
calibMap1[86], calibMap1[87], calibMap1[89], calibMap1[91], calibMap1[93],
calibMap1[94], calibMap1[96], calibMap1[98], calibMap1[99], calibMap1[101],
calibMap1[103], calibMap1[105], calibMap1[106], calibMap1[108], calibMap1[110],
calibMap1[111], calibMap1[113], calibMap1[115]
};

//  Minor Scale
const float calibMap6[QUAN_RES6] = {
calibMap1[0], calibMap1[2], calibMap1[3], calibMap1[5], calibMap1[7],
calibMap1[8], calibMap1[10], calibMap1[12], calibMap1[14], calibMap1[15],
calibMap1[17], calibMap1[19], calibMap1[20], calibMap1[22], calibMap1[24],
calibMap1[26], calibMap1[27], calibMap1[29], calibMap1[31], calibMap1[32],
calibMap1[34], calibMap1[36], calibMap1[38], calibMap1[39], calibMap1[41],
calibMap1[43], calibMap1[44], calibMap1[46], calibMap1[48], calibMap1[50],
calibMap1[51], calibMap1[53], calibMap1[55], calibMap1[56], calibMap1[58],
calibMap1[60], calibMap1[62], calibMap1[63], calibMap1[65], calibMap1[67],
calibMap1[68], calibMap1[70], calibMap1[72], calibMap1[74], calibMap1[75],
calibMap1[77], calibMap1[79], calibMap1[80], calibMap1[82], calibMap1[84],
calibMap1[86], calibMap1[87], calibMap1[89], calibMap1[91], calibMap1[92],
calibMap1[94], calibMap1[96], calibMap1[98], calibMap1[99], calibMap1[101],
calibMap1[103], calibMap1[104], calibMap1[106], calibMap1[108], calibMap1[110],
calibMap1[111], calibMap1[113], calibMap1[115]
};

//  5th
const float calibMap7[QUAN_RES7] = {
calibMap1[0], calibMap1[7], calibMap1[14], calibMap1[21], calibMap1[28],
calibMap1[35], calibMap1[42], calibMap1[49], calibMap1[56], calibMap1[63],
calibMap1[70], calibMap1[77], calibMap1[84], calibMap1[91], calibMap1[98],
calibMap1[105]
};

//  Whole tone
const float calibMap8[QUAN_RES8] = {
calibMap1[0], calibMap1[1], calibMap1[2], calibMap1[6], calibMap1[8],
calibMap1[10], calibMap1[12], calibMap1[14], calibMap1[16], calibMap1[18],
calibMap1[20], calibMap1[22], calibMap1[24], calibMap1[26], calibMap1[28],
calibMap1[30], calibMap1[32], calibMap1[34], calibMap1[36], calibMap1[38],
calibMap1[40], calibMap1[42], calibMap1[44], calibMap1[46], calibMap1[48],
calibMap1[50], calibMap1[52], calibMap1[54], calibMap1[56], calibMap1[58],
calibMap1[60], calibMap1[62], calibMap1[64], calibMap1[66], calibMap1[68],
calibMap1[70], calibMap1[72], calibMap1[74], calibMap1[76], calibMap1[78],
calibMap1[80], calibMap1[82], calibMap1[84], calibMap1[86], calibMap1[88],
calibMap1[90], calibMap1[92], calibMap1[94], calibMap1[96], calibMap1[98],
calibMap1[100], calibMap1[102], calibMap1[104], calibMap1[106], calibMap1[108],
calibMap1[110], calibMap1[112], calibMap1[114]
};

//  Major Scale
const uint8_t calibMapMidi2[QUAN_RES2] = {
0, 2, 4, 5, 7, 9, 11, 
12, 14, 16, 17, 19, 21, 23, 
24, 26, 28, 29, 31, 33, 35, 
36, 38, 40, 41, 43, 45, 47, 
48, 50, 52, 53, 55, 57, 59,
60, 62, 64, 65, 67, 69, 71, 
72, 74, 76, 77, 79, 81, 83, 
84, 86, 88, 89, 91, 93, 95, 
96, 98, 100, 101, 103, 105, 107, 
108, 110, 112, 113, 115
};

//  M7(9)
const uint8_t calibMapMidi3[QUAN_RES3] = {
0,  4, 7, 11, 
12, 14, 16, 19, 23, 
24, 26, 28, 31, 35,
36, 38, 40, 43, 47, 
48, 50, 52, 55, 59, 
60, 62, 64, 67, 71, 
72, 76, 79, 83, 
84, 86, 88, 91, 95, 
96, 100, 103, 107, 
108, 110, 112, 115
};

//  m7(9)
const uint8_t calibMapMidi4[QUAN_RES4] = {
0, 3, 7, 10, 
12, 15, 19, 22, 
26, 27, 31, 34, 
36, 38, 39, 43, 46, 
50, 53, 55, 58, 
60, 63, 67, 70, 
72, 74, 75, 79, 82, 
86, 89, 91, 94, 
96, 99, 103, 106, 110, 113
};

//  Dorian Scale
const uint8_t calibMapMidi5[QUAN_RES5] = {
0, 2, 3, 5, 7, 9, 10, 
12, 14, 15, 17, 19, 20, 21, 
24, 26, 27, 29, 31, 33, 34, 
36, 38, 39, 41, 43, 45, 46, 
48, 50, 51, 53, 55, 57, 58, 
60, 62, 63, 65, 67, 69, 70, 
72, 74, 75, 77, 79, 81, 82, 
84, 86, 87, 89, 91, 93, 94, 
96, 98, 99, 101, 103, 105, 106, 
108, 110, 111, 113, 115
};

//  Minor Scale
const uint8_t calibMapMidi6[QUAN_RES6] = {
0, 2, 3, 5, 7, 8, 10, 
12, 14, 15, 17, 19, 20, 22, 
24, 26, 27, 29, 31, 32, 34, 
36, 38, 39, 41, 43, 44, 46, 
48, 50, 51, 53, 55, 56, 58,
60, 62, 63, 65, 67, 68, 70, 
72, 74, 75, 77, 79, 80, 82, 
84, 86, 87, 89, 91, 92, 94, 
96, 98, 99, 101, 103, 104, 106, 
108, 110, 111, 113, 115
};

//  5th
const uint8_t calibMapMidi7[QUAN_RES7] = {
0, 7, 14, 21, 28, 35, 
42, 49, 56, 63, 70, 77, 
84, 91, 98, 105
};

//  Whole tone
const uint8_t calibMapMidi8[QUAN_RES8] = {
0, 1, 2, 6, 8, 10, 
12, 14, 16, 18,20, 22, 
24, 26, 28, 30, 32, 34,  
36, 38, 40, 42, 44, 46, 
48, 50, 52, 54, 56, 58, 
60, 62, 64, 66, 68, 70, 
72, 74, 76, 78, 80, 82, 
84, 86, 88, 90, 92, 94, 
96, 98, 100, 102, 104, 106, 
108, 110, 112, 114
};

volatile bool changeFlag = false;

//-------------------------------------------------------------
// mbed Functions
/*
//Nucleo F303K8  //MCP3204
CS  : pin 10 --  pin 8 (CS/SHDN)
MOSI: pin 11 --  pin 9 (D in)
MISO: pin 12 --  pin 10(D out)
SCK : pin 13 --  pin 11(CLK)
*/
SPI          spi(D11, D12, D13);
DigitalOut   csPin(D10);

AnalogIn     scalePin(A0); // Scale Pin 

AnalogIn     potPin1(A1);     // Pot1~2
AnalogIn     potPin2(D6);

DebouncedInterrupt switch1(D8);   // SW1
DebouncedInterrupt switch2(D9);   // SW2

// esp8266 wi-fi settings
#define SSID        "SSID"
#define PASSWORD    "PASSWORD"

#define REMOTE_ADDRESS   "192.168.1.2"
#define REMOTE_PORT      "8000"

#define STATIC_IP // if you use DHCP comment out this line 

#define LOCAL_ADDRESS    "192.168.1.8"
#define LOCAL_PORT       "9000"

// Serial for esp8266 (tx, rx)
BufferedSerial esp8266Serial(D1, D0);

// Serial for debug (tx, rx)
Serial pc(USBTX, USBRX);

// MIDI (tx, rx)
MIDI midi(A7, NC);

// declare the OSC bundle
OSCBundle bndl;

// Timer
Timer timer;

//-------------------------------------------------------------
// Functions

int map(int, int, int, int, int);
uint16_t adcRead(uint8_t);
void interruptSW1();
void interruptSW2();
void getESP8266Response();
void connectWifi();


//-------------------------------------------------------------
// Remaps value from one range to another range.

inline int map(int x, int in_min, int in_max, int out_min, int out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

//-------------------------------------------------------------
// Read MCP3208 AD Converter

uint16_t adcRead(uint8_t ch) {
    uint8_t b1, b2;
    uint8_t address = 0B01100000 | ((ch & 0B11) << 2);
    
    csPin = 0; // CS pin Low
    
    spi.write(address);
    b1 = spi.write(0x00);
    b2 = spi.write(0x00);

    csPin = 1; // CS pin Hi
        
    return (b1 << 4) | (b2 >> 4);
}

//-------------------------------------------------------------
// Check SW Status

void interruptSW1() {
    volatile static uint8_t sw1State;
        
    if (!sw1State) {
                 
        sw1State = 1;
            
    } else {
        
        sw1State = 0;
    }
    
    bndl.add("/sw1").add(sw1State);
    changeFlag = true;
}

void interruptSW2() {
    volatile static uint8_t sw2State;
    
    if (!sw2State) {
                 
        sw2State = 1;
            
    } else {

        sw2State = 0;
    }
    
    bndl.add("/sw2").add(sw2State);
    changeFlag = true;
}

//-------------------------------------------------------------
//  get & print esp8266 response

void getESP8266Response(int timeout)
{
    char resBuff[256] = {0};
    
    timer.start();
    
    uint8_t i = 0;
    
    while (!(timer.read() > timeout)) {
        
        if (esp8266Serial.readable()) {
            
            resBuff[i++] = esp8266Serial.getc();
        }
    }
    
    pc.printf(resBuff);
    
    timer.stop();
    timer.reset();
}

//-------------------------------------------------------------
// Setup esp8266 wi-fi module

void connectWifi() {
    
    pc.printf("\n---------- Starting ESP8266 Config ----------\r\n");
    wait(2);
    
    // set station mode
    pc.printf("\n---------- Set Station Mode ----------\r\n");
    
    esp8266Serial.printf("AT+CWMODE=1\r\n");
    
    getESP8266Response(1);
    wait(1);
    
    // restart
    pc.printf("\n---------- Reset ESP8266 ----------\r\n");
    
    esp8266Serial.printf("AT+RST\r\n");
    
    getESP8266Response(2);    
    wait(1);
    
#ifdef STATIC_IP
    
    // set static IP
    pc.printf("\n---------- Setting Static IP ----------\r\n");
    
    esp8266Serial.printf("AT+CIPSTA=\"");
    esp8266Serial.printf(LOCAL_ADDRESS);
    esp8266Serial.printf("\"\r\n");
    
    getESP8266Response(3);
    wait(1);
    
#endif    
    
    // connect wifi
    pc.printf("\n---------- Wi-fi Connect ----------\r\n");
    
    esp8266Serial.printf("AT+CWJAP=\"");
    esp8266Serial.printf(SSID);
    esp8266Serial.printf("\",\"");
    esp8266Serial.printf(PASSWORD);
    esp8266Serial.printf("\"\r\n");
    
    getESP8266Response(3);
    wait(2);
    
    // single connection
    pc.printf("\n---------- Setting Connection Mode ----------\r\n");
    
    esp8266Serial.printf("AT+CIPMUX=0\r\n");
    
    getESP8266Response(1);
    wait(1);
    
    // set UDP connection
    pc.printf("\n---------- Setting UDP Connection ----------\r\n");
    
    esp8266Serial.printf("AT+CIPSTART=");
    esp8266Serial.printf("\"UDP\",\"");
    esp8266Serial.printf(REMOTE_ADDRESS);
    esp8266Serial.printf("\",");
    esp8266Serial.printf(REMOTE_PORT);
    esp8266Serial.printf(",");
    esp8266Serial.printf(LOCAL_PORT);
    esp8266Serial.printf(",");
    esp8266Serial.printf("0\r\n");
    
    getESP8266Response(3);
    wait(1);

    // set data transmission mode
    pc.printf("\n---------- Setting Data Transmission Mode ----------\r\n");
    
    esp8266Serial.printf("AT+CIPMODE=1\r\n");
    
    getESP8266Response(1);
    wait(1);
    
    // change Baud Rate 
    pc.printf("\n---------- Change Baud Rate 4Mbps ----------\r\n");
    
    esp8266Serial.printf("AT+UART_CUR=4000000,8,1,0,0\r\n");
    getESP8266Response(3);
    
    esp8266Serial.baud(4000000);
    wait(1);
    
    // ready to send data
    pc.printf("\n---------- Ready to Send Data ----------\r\n");
    
    esp8266Serial.printf("AT+CIPSEND\r\n");
    
    getESP8266Response(2);
    wait(1);
}

//-------------------------------------------------------------
// Main

int main() {
    
    uint8_t i, idx;
    uint8_t oscBuff[SEND_BUFF_SIZE] = {0};
    static uint8_t scale;
    uint8_t note[4] = {0};
    static uint8_t _note[4];
    uint16_t adc[4] = {0};
    static uint16_t _adc[4];
    float pot[2] = {0};
    static float _pot[2] = {potPin1.read(), potPin2.read()};
    
    // Init SPI (4MHz clock)
    spi.format(8, 0);
    spi.frequency(4000000);
    csPin = 1;
    
    // setup esp8266 wi-fi
    esp8266Serial.baud(115200);
    connectWifi();
    
    // start MIDI (ch1)
    midi.begin(MIDI_CHANNEL);
    
    // start InterruptIn rising edge 
    switch1.attach(&interruptSW1, IRQ_RISE, 10);
    switch2.attach(&interruptSW2, IRQ_RISE, 10);
    
    // start timer (wait untile esp8266 transmission completed)
    timer.start();
    
    while (1) {
        
        scale = map(scalePin.read_u16(), 0, 51890, 0, (SCALE_TOTAL - 1));

        for (i = 0; i < 4; ++i) {
            // read ADC
            adc[i] = adcRead(i);

            if (abs(adc[i] - _adc[i]) > 10) {
                
                changeFlag = true;
                
                switch (i) {
                    case 0:
                        bndl.add("/acv1").add(adc[i]);
                        break;
                    case 1:
                        bndl.add("/acv2").add(adc[i]);
                        break;
                    case 2:
                        bndl.add("/acv3").add(adc[i]);
                        break;
                    case 3:
                        bndl.add("/acv4").add(adc[i]);
                        break;
                }
            }
            
            if (abs(adc[i] - _adc[i]) > 31) {
                
                // MIDI quantize
                switch (scale) {
                    
                    case Lin:
                    case Chr:
                        note[i] = map(adc[i], 825, 3757, 0, (84 - MAP_OFFSET)) + CALIB_OFFSET; // C0(12) ~ C7(96)
                        break;
                        
                    case Maj:
                        note[i] = calibMapMidi2[map(adc[i], 0, 4095, 0, QUAN_RES2 - 1)] + MIDI_OFFSET;
                        break;
                        
                    case M7:
                        note[i] = calibMapMidi3[map(adc[i], 0, 4095, 0, QUAN_RES3 - 1)] + MIDI_OFFSET;
                        break;
                        
                    case Min7:
                        note[i] = calibMapMidi4[map(adc[i], 0, 4095, 0, QUAN_RES4 - 1)] + MIDI_OFFSET;
                        break;
                        
                    case Dor:
                        note[i] = calibMapMidi5[map(adc[i], 0, 4095, 0, QUAN_RES5 - 1)] + MIDI_OFFSET;
                        break;
                        
                    case Min:
                        note[i] = calibMapMidi6[map(adc[i], 0, 4095, 0, QUAN_RES6 - 1)] + MIDI_OFFSET;
                        break;
                        
                    case S5th:
                        note[i] = calibMapMidi7[map(adc[i], 0, 4095, 0, QUAN_RES7 - 1)] + MIDI_OFFSET;
                        break;
                        
                    case Wht:
                        note[i] = calibMapMidi8[map(adc[i], 0, 4095, 0, QUAN_RES8 - 1)] + MIDI_OFFSET;
                        break;
                
                }
                    
            
                if (_note[i] != note[i]) {
                    
                    midi.sendNoteOff(_note[i], 0, MIDI_CHANNEL);
                    midi.sendNoteOn(note[i], 100, MIDI_CHANNEL);
                    
                    _note[i] = note[i];
                }
                
            }
            
            _adc[i] = adc[i];
        }

        // check potentiometer value
        pot[0] = potPin1.read();
        pot[1] = potPin2.read();

        if (fabs(pot[0] - _pot[0]) > 0.02f) {

            bndl.add("/pot1").add(pot[0] * 1023.0f);
            midi.sendControlChange(0x16, map(potPin1.read_u16(), 0, 65535, 0, 127), MIDI_CHANNEL); // microKorg Noise Level

            _pot[0] = pot[0];
            changeFlag = true;
        
        } else if (fabs(pot[1] - _pot[1]) > 0.02f) {

            bndl.add("/pot2").add(pot[1] * 1023.0f);
            midi.sendControlChange(0x5E, map(potPin2.read_u16(), 0, 65535, 0, 127), MIDI_CHANNEL); // microKorg Delay Level

            _pot[1] = pot[1];
            changeFlag = true;
        }
        
        if (changeFlag && timer.read_ms() > WAIT_SEND) {
            
            idx = 0;
            int len = bndl.send(oscBuff);
            
            while (len--) {
                // send OSC to esp8266 wifi
                esp8266Serial.putc(oscBuff[idx++]);
            }

            changeFlag = false;
            bndl.empty(); // empty the bundle to free room for a new one
            
            timer.reset();
        }

    }
    
}