// // a 2-dimensional ringringrain touch-pad(board) // // D. Yi @ 2023 4 9 // ////network! #include const char* ssid = "nolink2"; const char* password = "2222277777"; const int NETWORK_PORT = 27016; #include #include "utility/WiFiClientStream.h" #include "utility/WiFiServerStream.h" WiFiServerStream serverStream(NETWORK_PORT); #include ////pad structure // #define FLIPPED // --> comment/uncomment for horizontal flipping of the installation. #define NUMKEYS 42 // columns : 14, rows : 3 // --> how many keys are available for this pad int keystat[NUMKEYS] = {0, }; // --> a buffer to store statuses of all keys // --> needed to extract only 'the change' of key statuses #define MAXCHANGES 10 int keychanges[MAXCHANGES] = {0, }; int n_keychg = 0; // --> for monitoring only 'changed' keys. #define NUMCOLS 14 #ifdef FLIPPED int pins_cols[NUMCOLS] = {16, 15, 17, 18, 20, 19, 33, 34, 35, 36, 37, 38, 39, 40}; //14 // --> cols is horizontal offsets on the board // --> to be read as input. #else int pins_cols[NUMCOLS] = {40, 39, 38, 37, 36, 35, 34, 33, 19, 20, 18, 17, 15, 16}; //14 // --> cols is horizontal offsets on the board // --> to be read as input. #endif #define NUMROWS 2 int pins_rows[NUMROWS] = {7, 6}; //2 // #define NUMROWS 3 // int pins_rows[NUMROWS] = {8, 7, 6}; //3 // --> rows is vertical offsets on the board // --> to be driven as output (or high impedance) void setup() { //serial Serial.begin(115200); //pinmodes // cols : to be read as input. (PULL-UP) for (int idx = 0; idx < NUMCOLS; idx++) { pinMode(pins_cols[idx], INPUT_PULLUP); } //wifi WiFi.mode(WIFI_STA); // Connect to WiFi network Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); Serial.println("Mac address: " + WiFi.macAddress()); //firmata Firmata.disableBlinkVersion(); Firmata.begin(serverStream); //ota ArduinoOTA.onStart([]() { Serial.println("Start"); }); ArduinoOTA.onEnd([]() { Serial.println("\nEnd"); }); ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { Serial.printf("Progress: %u%%\r", (progress / (total / 100))); }); ArduinoOTA.onError([](ota_error_t error) { Serial.printf("Error[%u]: ", error); if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); else if (error == OTA_END_ERROR) Serial.println("End Failed"); }); ArduinoOTA.begin(); } void loop() { // perform a full scan of the key statuses! // update row voltages static int row = 0; pinMode(pins_rows[row], INPUT); // let old 'on' row goes 'hi-z' first. row++; if (row >= NUMROWS) { row = 0; } pinMode(pins_rows[row], OUTPUT); digitalWrite(pins_rows[row], LOW); // let new 'hi-z' row goes 'on'.. -> ready to scan. // 100us ~ 200us, waiting for the electricity ready... //delayMicroseconds(200); delay(2); // 2000us == 2ms // read all cols for (int col = 0; col < NUMCOLS; col++) { int key = row * NUMCOLS + col; if (key < NUMKEYS) { int cur_key = !digitalRead(pins_cols[col]); //logic inversion. (HIGH = noteoff, LOW = noteon.) // if it is 'changed', if (cur_key != keystat[key]) { // if there is a room to record this change, if (n_keychg < MAXCHANGES) { // make a memo. int keycoded = (key) * 10 + cur_key; // for example : C4 note-on --> 601 ( == 60*10 + 1) keychanges[n_keychg] = keycoded; n_keychg++; // send Firmata msg. over WIFI. Firmata.sendAnalog(0, keycoded); //@Pd //[pduino/arduino] will divide this by 1023.0 to map 0-1023 -> 0.0-1.0 //so, to recover original values, multiply back by 1023.0. } } // okay. good. now, apply the change. keystat[key] = cur_key; } } // at the moment of 'full scan done' if (row == NUMROWS - 1) { // // print out the buffer status. // for (int key = 0; key < NUMKEYS; key++) { // Serial.print(keystat[key]); Serial.print(" "); // } // Serial.println(); // print out the changes. for (int chg = 0; chg < n_keychg; chg++) { Serial.print(keychanges[chg]); Serial.print(" "); } // clear 'keychanges' array for (int idx = 0; idx < MAXCHANGES; idx++) { keychanges[idx] = 0; n_keychg = 0; } // send out alive counter static int loopcounter = 0; static int alivecounter = 0; loopcounter++; if (loopcounter % 100 == 0) { Firmata.sendAnalog(1, alivecounter); alivecounter++; if (alivecounter == 1000) { alivecounter = 0; } } } // // // discard all incoming MIDI msgs. // while (usbMIDI.read()) { } serverStream.maintain(); // ArduinoOTA.handle(); }