//VERSIONE 3.3
//MODIFICHE:
//compatibilità completa con terra-pirata (rb reader)
//modificata mappa 2 (RB) andando a renderla compatibile con terra-pirata. Joystick&levetta scorrono RB, rosso-blu trip, nero LP carattere Z per azzeramento trip
//INCLUSIONE LIBRERIE PER OTA
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <AsyncElegantOTA.h>
const char* ssid = "WLPcom TRAX UPD";
const char* password = "123456789";
AsyncWebServer server(80);
//GESTIONE LED RGB DI STATO
/******************** definizione delle costanti **********************************/
int portarossa = D9; // porta 11 da collegare all’anodo “rosso” del modulo RGB
int portaverde = D8; // porta 10 da collegare all’anodo “verde” del modulo RGB
int portablu = D7; // porta 9 da collegare all’anodo “blu” del modulo RBG
/**********************routine di accensione del led ********************************
nelle prossime righe viene definita la routine “colore” che, al momento del lancio, e’
accompagnata da tre variabili (rosso, verde e blu) che contengono i valori dell’intensita’
luminosa, di volta in volta voluta, per ogni singolo led (0 = minim0a e 255 = massima) */
//INIZIALIZZO PIN LETTURA VELOCITA
const int Vpin = D10;
int vel = LOW;
int Mvel = 0;
const int Vel_ab = 1; //se 0 allora la velocità sul pin non è abilitata, se 1 è abilitata
//GESTIONE SIMULAZIONE VELOCITA
unsigned long prevMillis = 0;
const long interval = 40;
unsigned long prevMilLP = 0;
// Keypad library to handle matrix keypad setup
#include <Keypad.h>
// For ESP32 Bluetooth keyboard HID https://github.com/T-vK/ESP32-BLE-Keyboard
//#include <BleKeyboard.h>
#include <USB.h>
#include <USBHIDKeyboard.h>
// Set up the bleKeyboard instance
USBHIDKeyboard Keyboard;
//BleKeyboard bleKeyboard("TRAX3-test", "WLP.com", 100);
// Keypad library set up
////////////////////////
// This needs to be aligned with how you wired the buttons exactly.
// see https://www.circuitbasics.com/how-to-set-up-a-keypad-on-an-arduino/ for an intro into the keypad library
const byte ROWS = 2;
const byte COLS = 5;
// for this project we'll number the keys, and use their value to 'press' the correct button
// The layout is a bit weird due to changes in the layout of the buttons, but maintaining pin compatibility
char keys[ROWS][COLS] = {
{'6', '4', '2', '8', '5'}, //{ '6', '4', '2', '8', '5'} PER TRAX3 { '2', '8', '4', '6', '5'} PER TRAX1 { '8', '2', '6', '4', '5'} COMMON
{ '1', '7', '3', '9', 'A'}
};
// pin assignments (https://randomnerdtutorials.com/esp32-pinout-reference-gpios/)
// IMPORTANT: choose pins that are actually broken out on your board, otherwise the ESP won't boot
//////////////////
// pins for keypad library, these need to be aligned with how you wired the buttons exactly.
byte rowPins[ROWS] = {D0, D1}; // top to bottom
byte colPins[COLS] = {D2, D3, D4, D5, D6}; // left to right
//INIZIALIZZO MAPPA
// include library to read and write from flash memory
#include <EEPROM.h>
// define the number of bytes you want to access
#define EEPROM_SIZE 1
int current_keymap = 1;
int key_mem = current_keymap;
// Initialization
/////////////////
// Initialize keypad library
Keypad TRAX = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
int last_keypad_state = IDLE; // Used to distinguish between button release from HOLD or PRESSED.
// Initialize variable that determines how long a key is pressed to the current time in milliseconds
unsigned long hold_time = millis();
// define time for a long press (ms)
const int long_press_time = 440;
const int long_press_repeat_interval = 80;
// How many keymaps do we have?
const int KEYMAP_COUNT = 2;
// These keys will be repeated (and also sent on initial press of the button).
// Other keys will have an alternate function on long press
// First dimension is keymap
char repeating_keys[4][10] = {
{'1', '2', '5', '6', '7', '8', '9' },
{'1', '2', '5', '8' },
{'1', '2' },
{}
};
/*
The 2 functions below determine what key gets sent.
See here for special keys:
- https://github.com/T-vK/ESP32-BLE-Keyboard/blob/master/BleKeyboard.h
- https://www.arduino.cc/en/Reference/KeyboardModifiers
Candidates are:
NUM_PLUS / NUM_MINUS
KEY_MEDIA_VOLUME_UP / KEY_MEDIA_VOLUME_DOWN
KEY_UP_ARROW / KEY_DOWN_ARROW / KEY_LEFT_ARROW / KEY_RIGHT_ARROW
KEY_MEDIA_PLAY_PAUSE
*/
// Routine to send the keystrokes on a short press of the keypad
void send_short_press(KeypadEvent key) {
// We're in the main menu
switch (current_keymap) {
case 1:
switch (key) {
case '1': Keyboard.write('+'); break;//ROSSO
case '2': Keyboard.write(KEY_UP_ARROW); break;//JOY UP
case '3': Keyboard.write('c'); break;//NERO
case '4': Keyboard.write(KEY_LEFT_ARROW); break;//JOY LEFT
//case '5': bleKeyboard.write('c'); break;//JOY SW
case '6': Keyboard.write(KEY_RIGHT_ARROW); break;//JOY RIGHT
case '7': Keyboard.write('?'); break;//BLU
case '8': Keyboard.write(KEY_DOWN_ARROW); break;//JOY DOWN
case '9': Keyboard.write('f'); break;//GIALLO
}
break;
case 2:
switch (key) {
case '1': Keyboard.write(KEY_RIGHT_ARROW); break;//ROSSO
case '2': Keyboard.write(KEY_UP_ARROW); break;//JOY UP
case '3': Keyboard.write('z'); break;//NERO
//case '4': bleKeyboard.write(KEY_LEFT_ARROW); break;//JOY LEFT
//case '5': bleKeyboard.write('c'); break;//JOY SW
//case '6': bleKeyboard.write(KEY_RIGHT_ARROW); break;//JOY RIGHT
case '7': Keyboard.write(KEY_LEFT_ARROW); break;//BLU
case '8': Keyboard.write(KEY_DOWN_ARROW); break;//JOY DOWN
//case '9': bleKeyboard.write(KEY_MEDIA_VOLUME_UP); break;//GIALLO
}
break;
case 3:
switch (key) {
case '1': Keyboard.write(KEY_UP_ARROW); break;
case '2': Keyboard.write('+'); break;
case '3': Keyboard.write(KEY_UP_ARROW); break;
case '4': Keyboard.write(KEY_LEFT_ARROW); break;
case '5': Keyboard.write('c'); break;
case '6': Keyboard.write(KEY_RIGHT_ARROW); break;
case '7': Keyboard.write(KEY_DOWN_ARROW); break;
case '8': Keyboard.write('?'); break;
case '9': Keyboard.write(KEY_DOWN_ARROW); break;
}
break;
//
// case 4:
// switch (key) {
// case '1': bleKeyboard.write(KEY_F1); flash_led(1, 150, 0); break;
// case '2': bleKeyboard.write(KEY_F2); flash_led(1, 150, 0); break;
// case '3': bleKeyboard.write(KEY_F3); flash_led(1, 150, 0); break;
// case '4': bleKeyboard.write(KEY_F4); flash_led(1, 150, 0); break;
// case '5': bleKeyboard.write(KEY_F5); flash_led(1, 150, 0); break;
// case '6': bleKeyboard.write(KEY_F6); flash_led(1, 150, 0); break;
// case '7': bleKeyboard.write(KEY_F7); flash_led(1, 150, 0); break;
// case '8': bleKeyboard.write(KEY_F8); flash_led(1, 150, 0); break;
// }
// break;
}
}
// Routine to send the keystrokes on a long press of the keypad
void send_long_press(KeypadEvent key) {
// We're in the main menu
switch (current_keymap) {
case 1:
switch (key) {
case '1': send_repeating_key('+'); break;//ROSSO
case '2': send_repeating_key(KEY_UP_ARROW); break;//JOY UP
case '3': Keyboard.write('d'); break;//NERO
case '4': send_repeating_key(KEY_LEFT_ARROW); break;//JOY LEFT
//case '5'://JOY SW
// cycle to next keymap
//current_keymap = 2;
// break;
case '6': send_repeating_key(KEY_RIGHT_ARROW); break;//JOY RIGHT
case '7': send_repeating_key('?'); break;//BLU
case '8': send_repeating_key(KEY_DOWN_ARROW); break;//JOY DOWN
// case '9': bleKeyboard.write('g');
case '9'://GIALLO
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press(KEY_TAB);
Keyboard.releaseAll();
break;
}
break;
case 2:
switch (key) {
case '1': send_repeating_key(KEY_RIGHT_ARROW); break;//ROSSO
case '2': send_repeating_key(KEY_UP_ARROW); break;//JOY UP
case '3': Keyboard.write('r'); break;//NERO
case '4': send_repeating_key(KEY_LEFT_ARROW); break;//JOY LEFT
//case '5'://JOY SW
// cycle to next keymap
//current_keymap = 1;
//break;
case '6': send_repeating_key(KEY_RIGHT_ARROW); break;//JOY RIGHT
case '7': send_repeating_key(KEY_LEFT_ARROW); break;//BLU
case '8': Keyboard.write(KEY_DOWN_ARROW); break;//JOY DOWN
case '9'://GIALLO
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press(KEY_TAB);
Keyboard.releaseAll();
break;
}
break;
case 3:
switch (key) {
case '1': send_repeating_key(KEY_UP_ARROW); break;//ROSSO
case '2': send_repeating_key('+'); break;//JOY UP
case '3': send_repeating_key('d'); break;//NERO
case '4': send_repeating_key(KEY_LEFT_ARROW); break;//JOY LEFT
//case '5'://JOY SW
// cycle to next keymap
//current_keymap = 1;
//break;
case '6': send_repeating_key(KEY_RIGHT_ARROW); break;//JOY RIGHT
case '7': send_repeating_key(KEY_DOWN_ARROW); break;//BLU
case '8': send_repeating_key('?'); break;//JOY DOWN
case '9'://GIALLO
Keyboard.press(KEY_LEFT_ALT);
Keyboard.press(KEY_TAB);
Keyboard.releaseAll();
break;
}
break;
//
// case 4:
// switch (key) {
// case '1': bleKeyboard.write(KEY_F11); flash_led(1, 150, 0); break;
// case '2': bleKeyboard.write(KEY_F12); flash_led(1, 150, 0); break;
// case '3': bleKeyboard.write(KEY_F13); flash_led(1, 150, 0); break;
// case '4': app_status = 1; break;
// case '5': bleKeyboard.write(KEY_F15); flash_led(1, 150, 0); break;
// case '6': bleKeyboard.write(KEY_F16); flash_led(1, 150, 0); break;
// case '7': bleKeyboard.write(KEY_F17); flash_led(1, 150, 0); break;
// case '8': bleKeyboard.write(KEY_F18); flash_led(1, 150, 0); break;
// }
// break;
//
}
switch (current_keymap) {
case 1:
for (int i = 0; i < 3; i++) // Scan the whole key list.
{
if ( TRAX.key[i].stateChanged ) // Only find keys that have changed state.
{
if ((TRAX.key[0].kchar == '1') && (TRAX.key[1].kchar == '7'))
current_keymap = 2;
}
//Serial.println(acumaP5.key[i].kchar);
}
break;
case 2:
for (int i = 0; i < 3; i++) // Scan the whole key list.
{
if ( TRAX.key[i].stateChanged ) // Only find keys that have changed state.
{
if ((TRAX.key[0].kchar == '1') && (TRAX.key[1].kchar == '7'))
current_keymap = 3;
}
//Serial.println(acumaP5.key[i].kchar);
}
break;
case 3:
for (int i = 0; i < 3; i++) // Scan the whole key list.
{
if ( TRAX.key[i].stateChanged ) // Only find keys that have changed state.
{
if ((TRAX.key[0].kchar == '1') && (TRAX.key[1].kchar == '7'))
current_keymap = 1;
}
//Serial.println(acumaP5.key[i].kchar);
}
break;
}
}
// Routine that sends a key repeatedly (for single char)
void send_repeating_key(uint8_t key) {
while (TRAX.getState() == HOLD) {
int vel = digitalRead(Vpin); //SCOMMENTARE QUANDO NON SI VUOLE SIMULARE VELOCITA
switch (Vel_ab) {
case 1:
if (vel == HIGH && Mvel == 0) {
Keyboard.press('t');
Keyboard.releaseAll();
Mvel = 1;
}
else if (vel == LOW && Mvel == 1) {
Mvel = 0;
}
break;
case 0:
break;
}
unsigned long curLPMillis = millis();
if (curLPMillis - prevMilLP >= long_press_repeat_interval) {
prevMilLP = curLPMillis;
Keyboard.write(key);
}
// bleKeyboard.write(key);
// delay(long_press_repeat_interval); // pause between presses
TRAX.getKey(); // update keypad event handler
}
}
// This function handles events from the keypad.h library. Each event is only called once
void keypad_handler(KeypadEvent key) {
// State changes for the buttons
switch (TRAX.getState()) {
case PRESSED: // Directly on the press of a button
if (is_key_repeating(key)) {
send_short_press(key);
}
break;
case HOLD: // When a button is held beyond the long_press_time value
send_long_press(key);
break;
case RELEASED: // When a button is released
//
if (last_keypad_state == PRESSED) {
if (!is_key_repeating(key)) {
send_short_press(key);
}
}
break;
case IDLE: // not sure why this generates a callback
break;
}
last_keypad_state = TRAX.getState();
}
// Arduino built-in setup loop
void setup() {
Serial.begin(115200);
// initialize EEPROM with predefined size
EEPROM.begin(EEPROM_SIZE);
// read the last LED state from flash memory
if (EEPROM.read(0) != 1 && EEPROM.read(0) != 2 ) {
current_keymap = 1;
EEPROM.write(0, current_keymap);
EEPROM.commit();
}
else {
current_keymap = EEPROM.read(0);
}
//SETTING OTA
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
//Serial.println("");
//
//while (WiFi.status() != WL_CONNECTED) {
// delay(500);
// Serial.print(".");
//}
server.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
request->send(200, "text/plain", "Hi! I am WLP.com TRAX 1.");
});
AsyncElegantOTA.begin(&server); // Start ElegantOTA
server.begin();
Serial.println("HTTP server started");
// Handle all keypad events through this listener
TRAX.addEventListener(keypad_handler); // Add an event listener for this keypad
// set HoldTime
TRAX.setHoldTime(long_press_time);
// Start bluetooth keyboard module
Keyboard.begin();
USB.begin();
pinMode(portarossa, OUTPUT); // dichiara la porta 11 come porta di output
pinMode(portaverde, OUTPUT); // dichiara la porta 10 come porta di output
pinMode(portablu, OUTPUT); // dichiara la porta 9 come porta di output
//GESTIONE PIN VELOCITA
pinMode(Vpin, INPUT);
// End of setup()
}
void loop() {
if (current_keymap != key_mem) {
EEPROM.write(0, current_keymap);
EEPROM.commit();
key_mem = current_keymap;
}
// Need to call this function constantly to make the keypad library work
TRAX.getKey();
//delay(10);
//gestione colori mappe
switch (current_keymap) {
case 1: colore(0, 255, 0);
break;
case 2: colore(0, 0, 255);
break;
case 3: colore(255, 255, 0);
break;
}
//GESTIONE LETTURA VELOCITA CHE VIENE ATTIVATA SOLO CON MAPPA ROADBOOK
int vel = digitalRead(Vpin); //SCOMMENTARE QUANDO NON SI VUOLE SIMULARE VELOCITA
if (vel == HIGH && Mvel == 0) {
Keyboard.press('t');
Keyboard.releaseAll();
Mvel = 1;
}
else if (vel == LOW && Mvel == 1) {
Keyboard.releaseAll();
Mvel = 0;
}
}
// Helper function to determine if a key is supposed to be repeating, or special
int is_key_repeating(char key_pressed) {
for ( int i = 0; i < sizeof (repeating_keys[current_keymap]); i++) {
if ( repeating_keys[current_keymap][i] == key_pressed) {
return true;
}
}
return false;
}
void colore (unsigned char rosso, unsigned char verde, unsigned char blu)
{
analogWrite(portarossa, rosso); //attiva il led rosso con l’intensita’ definita nella variabile rosso
analogWrite(portablu, blu); //attiva il led blu con l’intensita’ definita nella variabile blu
analogWrite(portaverde, verde); //attiva il led verde con l’intensita’ definita nella variabile verde
}
// This function cycles the keymap and signals the new keymap via the LED
//void switch_keymap() {
//
// // Serial.println("Switching keymap");
//
// // cycle to next keymap
// current_keymap++;
// if (current_keymap > KEYMAP_COUNT ) {
// current_keymap = 1;
// }
//}