199 lines
5.2 KiB
C++
199 lines
5.2 KiB
C++
//
|
|
// a 2-dimensional ringringrain touch-pad(board)
|
|
//
|
|
// D. Yi @ 2023 4 9
|
|
//
|
|
|
|
////network!
|
|
|
|
#include <ConfigurableFirmata.h>
|
|
|
|
const char* ssid = "nolink2";
|
|
const char* password = "2222277777";
|
|
const int NETWORK_PORT = 27016;
|
|
|
|
#include <WiFi.h>
|
|
#include "utility/WiFiClientStream.h"
|
|
#include "utility/WiFiServerStream.h"
|
|
WiFiServerStream serverStream(NETWORK_PORT);
|
|
|
|
#include <ArduinoOTA.h>
|
|
|
|
////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();
|
|
}
|