Skip to content

Instantly share code, notes, and snippets.

@tomhermans
Created April 25, 2023 12:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomhermans/83eb8d9cf1aa557fd9a597676628b0cf to your computer and use it in GitHub Desktop.
Save tomhermans/83eb8d9cf1aa557fd9a597676628b0cf to your computer and use it in GitHub Desktop.
/* based on @file MultiKey.ino || @version 1.0 || @author Mark Stanley|| @contact mstanley@technologist.com
|| @description This sketch is an example of how you can get multiple key presses from a keypad or keyboard.
|| #
*/
#include <Keypad.h>
#include <BleKeyboard.h>
// 135x240px display
#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific
TFT_eSPI tft = TFT_eSPI(135, 240);
TFT_eSprite img = TFT_eSprite(&tft);
BleKeyboard bleKeyboard("Toms-Buttons");
// define rotary encoder
#define outputA 36
#define outputB 37
#define rotSwitch 32
// define joystick
#define joyVRX 15
#define joyVRX 13
#define joySW 12
int deltaX = 0;
int deltaY = 0;
char joyDirX[] = "Center";
char joyDirY[] = "Center";
// array technique to debounce the joystick switch
const unsigned int numReadings = 3;
unsigned int analogVals[numReadings];
unsigned int i = 0;
int counter = 0;
int aState;
int aLastState;
int lastMillis = 0;
int w = 135;
int h = 240;
int bg = TFT_BLACK;
char keys[4][4] = {
{'T', '0', 'M', 'A'},
{'7', '8', '9', 'B'},
{'4', '5', '6', 'C'},
{'1', '2', '3', 'D'}
};
// BLUE
byte rowPins[4] = {33, 25, 26, 27}; //connect to the row pinouts of the keypad
// ORANGE
byte colPins[4] = {21, 22, 17, 2}; //connect to the column pinouts of the keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, 4, 4 );
//unsigned long loopCount;
//unsigned long startTime;
String msg;
int states[4] = { TFT_PURPLE, TFT_MAROON, TFT_BLACK, TFT_RED };
int curState = 0;
void setup() {
Serial.begin(115200);
tft.begin();
tft.setRotation(0); // 0 & 2 Portrait. 1 & 3 landscape
tft.fillScreen(bg);
//
img.createSprite(w, h);
img.setTextColor(TFT_WHITE);
img.drawString("MultiKey", 10, 50, 4);
img.pushSprite(0, 0);
pinMode (outputA, INPUT);
pinMode (outputB, INPUT);
pinMode (rotSwitch, INPUT_PULLUP);
aLastState = digitalRead(outputA);
bleKeyboard.begin();
Serial.println("bleKeyb setup");
// loopCount = 0;
// startTime = millis();
msg = "";
}
void loop() {
getJoyStick();
// loopCount++;
// if ( (millis() - startTime) > 5000 ) {
// Serial.print("Average loops per second = ");
// Serial.println(loopCount / 5);
// startTime = millis();
// loopCount = 0;
// }
aState = digitalRead(outputA);
if(digitalRead(rotSwitch) < 1) { // reset counter on rotary press
counter = 0;
Serial.print("rot Switch pressed, counter reset. Counter = ");
Serial.println(counter);
bleKeyboard.write(KEY_NUM_ENTER);
}
int interval = millis()-lastMillis; //interval = time between 2 correct cycles in milliseconds.
lastMillis = millis();
if (aStat44e != aLastState) {
Serial.print(interval);
Serial.println(" - pulse");
// If the outputB state is different to the outputA state, that means the encoder is rotating clockwise
if (interval > 1) {
Serial.println("OKAY");
if (digitalRead(outputB) != aState) {
Serial.println("PLUS");
bleKeyboard.write(KEY_UP_ARROW);
delay(30);
counter ++;
changeScreenBottom("rotary", String(counter), 0);
} else {
Serial.println("MINUS");
bleKeyboard.write(KEY_DOWN_ARROW);
delay(30);
counter --;
changeScreenBottom("rotary", String(counter), 0);
}
// Serial.println(aState, aLastState, digitalRead(outputB), digitalRead(outputA));
Serial.print("Position: ");
Serial.println(counter);
} else {
Serial.println("too fast");
}
}
// Fills kpd.key[ ] array with up-to 10 active keys.
// Returns true if there are ANY active keys.
if (kpd.getKeys())
{
for (int i = 0; i < LIST_MAX; i++) // Scan the whole key list.
{
if ( kpd.key[i].stateChanged ) // Only find keys that have changed state.
{
switch (kpd.key[i].kstate) { // Report active key state : IDLE, PRESSED, HOLD, or RELEASED
case PRESSED:
msg = " PRESSED.";
break;
case HOLD:
msg = " HOLD.";
break;
case RELEASED:
msg = " RELEASED.";
break;
case IDLE:
msg = " IDLE.";
}
// Serial.print("Key ");
// Serial.print(kpd.key[i].kchar);
// Serial.println(msg);
Serial.println(kpd.key[i].kchar);
if (bleKeyboard.isConnected()) {
if (msg == " PRESSED." || msg == " HOLD.") {
if (kpd.key[i].kchar == 'A') {
Serial.println('A');
curState = curState + 1;
if (curState > 4) {
curState = 0;
}
bg = states[curState];
break;
}
if (kpd.key[i].kchar == 'B') {
Serial.println('B');
Serial.println(KEY_TAB);
bleKeyboard.write(KEY_TAB);
}
if (kpd.key[i].kchar == 'C') {
Serial.println('C');
Serial.println(KEY_TAB);
bleKeyboard.press(KEY_LEFT_SHIFT);
bleKeyboard.press(KEY_TAB);
delay(100);
bleKeyboard.releaseAll();
}
if (kpd.key[i].kchar == 'T') {
Serial.println(KEY_F11);
bleKeyboard.write(KEY_F11);
}
if (kpd.key[i].kchar == '0') {
Serial.println(KEY_F12);
bleKeyboard.write(KEY_F12);
}
if (kpd.key[i].kchar == 'M') {
Serial.println(KEY_F13);
bleKeyboard.write(KEY_F13);
}
if (kpd.key[i].kchar != 'T'
&& kpd.key[i].kchar != '0'
&& kpd.key[i].kchar != 'M'
&& kpd.key[i].kchar != 'A'
&& kpd.key[i].kchar != 'C'
&& kpd.key[i].kchar != 'B'
) {
bleKeyboard.write(kpd.key[i].kchar);
}
}
changeScreen(String(curState), String(kpd.key[i].kchar), 20);
}
}
}
}
} // End loop
void getJoyStick() {
deltaX = 0;
deltaY = 0;
if(analogRead(15) < 10) {
Serial.println(" - RIGHT"); deltaX = w / 3; strcpy(joyDirX, "RIGHT");
bleKeyboard.write(KEY_RIGHT_ARROW);
delay(20);
}
else if(analogRead(15) < 1840) { Serial.println(" - slight right"); deltaX = w / 6; strcpy(joyDirX, "right"); }
else if(analogRead(15) > 4050) {
Serial.println(" - LEFT"); deltaX = w / 3 * -1; strcpy(joyDirX, "LEFT");
bleKeyboard.write(KEY_LEFT_ARROW);
delay(20);
}
else if(analogRead(15) > 1920) { Serial.println(" - slight left"); deltaX = w / 6 * -1; strcpy(joyDirX, "left");}
else { strcpy(joyDirX, "- C -"); }
if(analogRead(13) < 10) {
Serial.println(" - BOTTOM"); deltaY = h / 3;
strcpy(joyDirY, "BOTTOM");
bleKeyboard.write(KEY_DOWN_ARROW);
delay(20);
}
else if (analogRead(13) < 1840) {
Serial.println(" - slight bottom"); deltaY = h / 6; strcpy(joyDirY, "bottom");
bleKeyboard.write(KEY_DOWN_ARROW);
delay(20);
}
else if(analogRead(13) > 4050) {
Serial.println(" - TOP"); deltaY = h / 3 * -1; strcpy(joyDirY, "TOP");
Serial.println(KEY_UP_ARROW);
bleKeyboard.write(KEY_UP_ARROW);
delay(20);
}
else if (analogRead(13) > 1920) { Serial.println(" - slight top"); deltaY = h / 6 * -1; strcpy(joyDirY, "top"); }
else { strcpy(joyDirY, "- C -"); }
analogVals[i] = analogRead(12);
i++;
if (i>=numReadings)
{
i=0; //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
}
if(average(analogVals, numReadings) == 0) { Serial.println(" - SW PRESSED"); } else { Serial.println(" - ");}
changeScreenBottom(String(joyDirX), String(joyDirY), 60);
}
void changeScreen(String curState, String keychar, int y) {
img.fillRect(0, 0, w, 80, bg);
img.drawString(String(curState), 10, y, 4);
img.drawString(String(keychar), 10, 20 + y, 4);
img.pushSprite(0, 0);
}
void changeScreenBottom(String curState, String keychar, int y) {
img.fillRect(0, 90 + y, w, h, bg);
img.drawString(String(curState), 10, 90 + y, 4);
img.drawString(String(keychar), 10, 90 + 20 + y, 4);
img.pushSprite(0, 0);
}
float average (unsigned int * array, int len) // assuming array is int.
{
long sum = 0L ; // sum will be larger than an item, long for safety.
for (int i = 0 ; i < len ; i++)
sum += array [i] ;
return ((float) sum) / len ; // average will be fractional, so float may be appropriate.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment