How to use a blackberry Q10 keyboard with ESP32?

Hi,

I have managed to build some arduino and esp8266 and esp32 projects using the arduino IDE, but I am just figuring things out by trying, reading/watching tutorials and googeling issues as the come. I am aware that I lack a lot of basic programming skills, but I am not able to learn it all before looking for help. Please just ignore this, if you mind. I certainly I don't expect anyone to solve my problem for me and I don't mind to be pointed in the right direction ("you should read about …") - actually I would love to understand how to best approach my problem:

I have a "Lilygo T-Keyboard" (containing an esp32c3 dev module, a blackberry Q10 keyboard and a small 0.99" TFT display, for which I want to create my own program code. The manufacturer provides some librarys and code examples, from which I am trying to extract the code that only takes input from the keyboard and print the keystokes to the serial monitor as a first step. Unfortunatelly, I don't understand much of what they do in the examples and I am just monkey-coding in the hopes to figure out what works, but so far quite unsucessfull.

This is the code I have so far:

#include <Arduino.h>
#include <stdint.h>
#include <string.h>
#include <SPI.h>

#define keyborad_BL_PIN  9

const uint8_t KEY_LEFT_CTRL = 0x80;
const uint8_t KEY_LEFT_SHIFT = 0x81;
const uint8_t KEY_LEFT_ALT = 0x82;
const uint8_t KEY_LEFT_GUI = 0x83;
const uint8_t KEY_RIGHT_CTRL = 0x84;
const uint8_t KEY_RIGHT_SHIFT = 0x85;
const uint8_t KEY_RIGHT_ALT = 0x86;
const uint8_t KEY_RIGHT_GUI = 0x87;

const uint8_t KEY_UP_ARROW = 0xDA;
const uint8_t KEY_DOWN_ARROW = 0xD9;
const uint8_t KEY_LEFT_ARROW = 0xD8;
const uint8_t KEY_RIGHT_ARROW = 0xD7;
const uint8_t KEY_BACKSPACE = 0xB2;
const uint8_t KEY_TAB = 0xB3;
const uint8_t KEY_RETURN = 0xB0;
const uint8_t KEY_ESC = 0xB1;
const uint8_t KEY_INSERT = 0xD1;
const uint8_t KEY_PRTSC = 0xCE;
const uint8_t KEY_DELETE = 0xD4;
const uint8_t KEY_PAGE_UP = 0xD3;
const uint8_t KEY_PAGE_DOWN = 0xD6;
const uint8_t KEY_HOME = 0xD2;
const uint8_t KEY_END = 0xD5;
const uint8_t KEY_CAPS_LOCK = 0xC1;
const uint8_t KEY_F1 = 0xC2;
const uint8_t KEY_F2 = 0xC3;
const uint8_t KEY_F3 = 0xC4;
const uint8_t KEY_F4 = 0xC5;
const uint8_t KEY_F5 = 0xC6;
const uint8_t KEY_F6 = 0xC7;
const uint8_t KEY_F7 = 0xC8;
const uint8_t KEY_F8 = 0xC9;
const uint8_t KEY_F9 = 0xCA;
const uint8_t KEY_F10 = 0xCB;
const uint8_t KEY_F11 = 0xCC;
const uint8_t KEY_F12 = 0xCD;
const uint8_t KEY_F13 = 0xF0;
const uint8_t KEY_F14 = 0xF1;
const uint8_t KEY_F15 = 0xF2;
const uint8_t KEY_F16 = 0xF3;
const uint8_t KEY_F17 = 0xF4;
const uint8_t KEY_F18 = 0xF5;
const uint8_t KEY_F19 = 0xF6;
const uint8_t KEY_F20 = 0xF7;
const uint8_t KEY_F21 = 0xF8;
const uint8_t KEY_F22 = 0xF9;
const uint8_t KEY_F23 = 0xFA;
const uint8_t KEY_F24 = 0xFB;

const uint8_t KEY_NUM_0 = 0xEA;
const uint8_t KEY_NUM_1 = 0xE1;
const uint8_t KEY_NUM_2 = 0xE2;
const uint8_t KEY_NUM_3 = 0xE3;
const uint8_t KEY_NUM_4 = 0xE4;
const uint8_t KEY_NUM_5 = 0xE5;
const uint8_t KEY_NUM_6 = 0xE6;
const uint8_t KEY_NUM_7 = 0xE7;
const uint8_t KEY_NUM_8 = 0xE8;
const uint8_t KEY_NUM_9 = 0xE9;
const uint8_t KEY_NUM_SLASH = 0xDC;
const uint8_t KEY_NUM_ASTERISK = 0xDD;
const uint8_t KEY_NUM_MINUS = 0xDE;
const uint8_t KEY_NUM_PLUS = 0xDF;
const uint8_t KEY_NUM_ENTER = 0xE0;
const uint8_t KEY_NUM_PERIOD = 0xEB;

byte rows[] = {0, 3, 18, 12, 11, 6, 7};
const int rowCount = sizeof(rows) / sizeof(rows[0]);

byte cols[] = {1, 4, 5, 19, 13};
const int colCount = sizeof(cols) / sizeof(cols[0]);

bool keys[colCount][rowCount];
bool lastValue[colCount][rowCount];
bool changedValue[colCount][rowCount];

char keyboard[colCount][rowCount];
char keyboard_symbol[colCount][rowCount];

bool symbolSelected;
int OffsetX = 0;
uint16_t flow_i = 0;
bool case_locking = false;
bool alt_active = false;
unsigned long previousMillis_1 = 0; //Millisecond time record
unsigned long previousMillis_2 = 0; //Millisecond time record
const long backlight_off_time = 20000;       //Turn off the screen backlight
const long display_Wait_blue_time = 2000;       //The screen shows waiting for bluetooth connection

void readMatrix();
bool keyPressed(int colIndex, int rowIndex);
bool keyActive(int colIndex, int rowIndex);
bool isPrintableKey(int colIndex, int rowIndex);
void printMatrix();
void clear_sccreen();

void setup() {
  Serial.println("setup()");
  Serial.printf("setup \n");
  keyboard[0][0] = 'q';
  keyboard[0][1] = 'w';
  keyboard[0][2] = NULL; // symbol
  keyboard[0][3] = 'a';
  keyboard[0][4] = NULL; // ALT
  keyboard[0][5] = ' ';
  keyboard[0][6] = NULL; // Mic

  keyboard[1][0] = 'e';
  keyboard[1][1] = 's';
  keyboard[1][2] = 'd';
  keyboard[1][3] = 'p';
  keyboard[1][4] = 'x';
  keyboard[1][5] = 'z';
  keyboard[1][6] = NULL; // Left Shift

  keyboard[2][0] = 'r';
  keyboard[2][1] = 'g';
  keyboard[2][2] = 't';
  keyboard[2][3] = NULL; // Right Shit
  keyboard[2][4] = 'v';
  keyboard[2][5] = 'c';
  keyboard[2][6] = 'f';

  keyboard[3][0] = 'u';
  keyboard[3][1] = 'h';
  keyboard[3][2] = 'y';
  keyboard[3][3] = NULL; // Enter
  keyboard[3][4] = 'b';
  keyboard[3][5] = 'n';
  keyboard[3][6] = 'j';

  keyboard[4][0] = 'o';
  keyboard[4][1] = 'l';
  keyboard[4][2] = 'i';
  keyboard[4][3] = NULL; // Backspace
  keyboard[4][4] = '$';
  keyboard[4][5] = 'm';
  keyboard[4][6] = 'k';

  keyboard_symbol[0][0] = '#';
  keyboard_symbol[0][1] = '1';
  keyboard_symbol[0][2] = NULL;
  keyboard_symbol[0][3] = '*';
  keyboard_symbol[0][4] = NULL;
  keyboard_symbol[0][5] = NULL;
  keyboard_symbol[0][6] = '0';

  keyboard_symbol[1][0] = '2';
  keyboard_symbol[1][1] = '4';
  keyboard_symbol[1][2] = '5';
  keyboard_symbol[1][3] = '@';
  keyboard_symbol[1][4] = '8';
  keyboard_symbol[1][5] = '7';
  keyboard_symbol[1][6] = NULL;

  keyboard_symbol[2][0] = '3';
  keyboard_symbol[2][1] = '/';
  keyboard_symbol[2][2] = '(';
  keyboard_symbol[2][3] = NULL;
  keyboard_symbol[2][4] = '?';
  keyboard_symbol[2][5] = '9';
  keyboard_symbol[2][6] = '6';

  keyboard_symbol[3][0] = '_';
  keyboard_symbol[3][1] = ':';
  keyboard_symbol[3][2] = ')';
  keyboard_symbol[3][3] = NULL;
  keyboard_symbol[3][4] = '!';
  keyboard_symbol[3][5] = ',';
  keyboard_symbol[3][6] = ';';

  keyboard_symbol[4][0] = '+';
  keyboard_symbol[4][1] = '"';
  keyboard_symbol[4][2] = '-';
  keyboard_symbol[4][3] = NULL;
  keyboard_symbol[4][4] = NULL;
  keyboard_symbol[4][5] = '.';
  keyboard_symbol[4][6] = '\'';

  delay(500);
  pinMode(keyborad_BL_PIN, OUTPUT);

  for (int x = 0; x < rowCount; x++) {
    Serial.print(rows[x]); Serial.println(" as input");
    pinMode(rows[x], INPUT);
  }

  for (int x = 0; x < colCount; x++) {
    Serial.print(cols[x]); Serial.println(" as input-pullup");
    pinMode(cols[x], INPUT_PULLUP);
  }

  symbolSelected = false;
}

void readMatrix() {
  Serial.println("readMatrix");
  int delayTime = 0;
  // iterate the columns
  for (int colIndex = 0; colIndex < colCount; colIndex++) {
    // col: set to output to low
    byte curCol = cols[colIndex];
    pinMode(curCol, OUTPUT);
    digitalWrite(curCol, LOW);

    // row: interate through the rows
    for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
      byte rowCol = rows[rowIndex];
      pinMode(rowCol, INPUT_PULLUP);
      delay(1); // arduino is not fast enought to switch input/output modes so wait 1 ms

      bool buttonPressed = (digitalRead(rowCol) == LOW);

      keys[colIndex][rowIndex] = buttonPressed;
      if ((lastValue[colIndex][rowIndex] != buttonPressed)) {
        changedValue[colIndex][rowIndex] = true;
      } else {
        changedValue[colIndex][rowIndex] = false;
      }

      lastValue[colIndex][rowIndex] = buttonPressed;
      pinMode(rowCol, INPUT);
    }

    // disable the column
    pinMode(curCol, INPUT);
  }

  // symbolSelected = !symbolSelected;
  if (keyPressed(0, 2)) {
      symbolSelected = true;
  }
}

bool keyPressed(int colIndex, int rowIndex) {
  return changedValue[colIndex][rowIndex] && keys[colIndex][rowIndex] == true;
}

bool keyActive(int colIndex, int rowIndex) {
  return keys[colIndex][rowIndex] == true;
}

bool isPrintableKey(int colIndex, int rowIndex) {
  return keyboard_symbol[colIndex][rowIndex] != NULL || keyboard[colIndex][rowIndex] != NULL;
}

void printMatrix() {
  Serial.println("printMatrix");
  for (int rowIndex = 0; rowIndex < rowCount; rowIndex++) {
    for (int colIndex = 0; colIndex < colCount; colIndex++) {
        
        // we only want to print if the key is pressed and it is a printable character
        if (keyPressed(colIndex, rowIndex) && isPrintableKey(colIndex, rowIndex)) {
          String toPrint;
          if (symbolSelected) {
            symbolSelected = false;
            toPrint = String(keyboard_symbol[colIndex][rowIndex]);
          } else {
            toPrint = String(keyboard[colIndex][rowIndex]);
          }

        if (keyActive(0, 4)) {
          alt_active = true;
          keys[0][4] = false;
          return;
        }

        // keys 1,6 and 2,3 are Shift keys, so we want to upper case
        if (case_locking || keyActive(1, 6)) {
          toPrint.toUpperCase();
        }

        char c[2];
        strcpy(c, toPrint.c_str());
        Serial.println(c);
        Serial.print(toPrint);
        previousMillis_1 = millis();
      }
    }
  }
}

void loop() {
  Serial.println("start loop");
  //Right Shift  ,Toggle case locking
  if (keyPressed(2, 3)) {  
    case_locking = !case_locking;
    Serial.println("Right Shift  ,Toggle case locking");
  }

  readMatrix();
  printMatrix();

  // key 3,3 is the enter key
  if (keyPressed(3, 3)) {
      Serial.println("clear_sccreen");
  }

  //BACKSPACE
  if (keyPressed(4, 3)) {
    Serial.println("BACKSPACE");
  }

  //SHIFT
  if (keyPressed(1, 6)) {
    Serial.println("KEY_RIGHT_SHIFT");
  }

  //alt+left shit, trigger ctrl+shift(Switch the input method)
  if (keyActive(0, 4) && keyPressed(1, 6)) {
      Serial.println("alt+left shit, trigger ctrl+shift(Switch the input method");
  }
}

It compiles and copies to the board without errors, but the serial monitor shows only this:

14:14:05.918 -> ESP-ROM:esp32c3-api1-20210207
14:14:05.918 -> Build:Feb  7 2021
14:14:05.918 -> rst:0x1 (POWEROESP-ROM:esp32c3-api1-20210207
14:33:17.276 -> Build:Feb  7 2021
14:33:17.276 -> rst:0x1 (POWERON),boot:0xd (SPI_FAST_FLASH_BO

It looks to me that it crashes very soon afte (or while) booting, since it seems not even to enter the setup function, where it would first

Serial.println("setup()");

Thanks for any advice!

for a start you are missing Serial.begin()

void setup() {
  Serial.begin(115200);
  Serial.println("setup()");
1 Like

Haha, well, that was easy... :joy:

Thanks much! I can continue with my quest now...

try putting in Serial.println() statement at points in the code to see how far it gets
in particular I am doubtful about using pin GPIO9

pinMode(keyborad_BL_PIN, OUTPUT);

have a look at esp32-pinout-reference-gpios

It actually just worked after adding

Serial.begin(115200);

I was flooded with my debug messages, but after removing them, I got exactly what I wanted for the first step :slight_smile:

Why would GPIO9 not be suitable? I just took what the vendor used in their examples...

running on a Node MCU ESP-WROOM-32 it crashes on

pinMode(keyborad_BL_PIN, OUTPUT);

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.