├── README.md ├── .gitignore ├── .vscode ├── extensions.json └── settings.json ├── test └── README ├── platformio.ini ├── LICENSE ├── lib └── README ├── include └── README ├── .travis.yml └── src └── main.cpp /README.md: -------------------------------------------------------------------------------- 1 | # blackberry_q10_kd_esp32 2 | SnapOnAir Q10 Keyboard with ESP32 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .pioenvs 2 | .piolibdeps 3 | .vscode/.browse.c_cpp.db* 4 | .vscode/c_cpp_properties.json 5 | .vscode/launch.json 6 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "platformio.platformio-ide" 6 | ] 7 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "terminal.integrated.env.osx": { 3 | "PATH": "/Users/tony/.platformio/penv/bin:/Users/tony/.platformio/penv:/Users/tony/.rbenv/bin:/Users/tony/.nvm/versions/node/v8.11.2/bin:/Users/tony/Downloads/google-cloud-sdk/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin", 4 | "PLATFORMIO_CALLER": "vscode" 5 | } 6 | } -------------------------------------------------------------------------------- /test/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for PIO Unit Testing and project tests. 3 | 4 | Unit Testing is a software testing method by which individual units of 5 | source code, sets of one or more MCU program modules together with associated 6 | control data, usage procedures, and operating procedures, are tested to 7 | determine whether they are fit for use. Unit testing finds problems early 8 | in the development cycle. 9 | 10 | More information about PIO Unit Testing: 11 | - https://docs.platformio.org/page/plus/unit-testing.html 12 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:esp32dev] 12 | platform = espressif32 13 | board = esp32dev 14 | framework = arduino 15 | lib_deps = 16 | Keypad 17 | U8g2 18 | Spi 19 | Wire 20 | monitor_speed = 115200 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Tony Rieker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project specific (private) libraries. 3 | PlatformIO will compile them to static libraries and link into executable file. 4 | 5 | The source code of each library should be placed in a an own separate directory 6 | ("lib/your_library_name/[here are source files]"). 7 | 8 | For example, see a structure of the following two libraries `Foo` and `Bar`: 9 | 10 | |--lib 11 | | | 12 | | |--Bar 13 | | | |--docs 14 | | | |--examples 15 | | | |--src 16 | | | |- Bar.c 17 | | | |- Bar.h 18 | | | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html 19 | | | 20 | | |--Foo 21 | | | |- Foo.c 22 | | | |- Foo.h 23 | | | 24 | | |- README --> THIS FILE 25 | | 26 | |- platformio.ini 27 | |--src 28 | |- main.c 29 | 30 | and a contents of `src/main.c`: 31 | ``` 32 | #include 33 | #include 34 | 35 | int main (void) 36 | { 37 | ... 38 | } 39 | 40 | ``` 41 | 42 | PlatformIO Library Dependency Finder will find automatically dependent 43 | libraries scanning project source files. 44 | 45 | More information about PlatformIO Library Dependency Finder 46 | - https://docs.platformio.org/page/librarymanager/ldf.html 47 | -------------------------------------------------------------------------------- /include/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project header files. 3 | 4 | A header file is a file containing C declarations and macro definitions 5 | to be shared between several project source files. You request the use of a 6 | header file in your project source file (C, C++, etc) located in `src` folder 7 | by including it, with the C preprocessing directive `#include'. 8 | 9 | ```src/main.c 10 | 11 | #include "header.h" 12 | 13 | int main (void) 14 | { 15 | ... 16 | } 17 | ``` 18 | 19 | Including a header file produces the same results as copying the header file 20 | into each source file that needs it. Such copying would be time-consuming 21 | and error-prone. With a header file, the related declarations appear 22 | in only one place. If they need to be changed, they can be changed in one 23 | place, and programs that include the header file will automatically use the 24 | new version when next recompiled. The header file eliminates the labor of 25 | finding and changing all the copies as well as the risk that a failure to 26 | find one copy will result in inconsistencies within a program. 27 | 28 | In C, the usual convention is to give header files names that end with `.h'. 29 | It is most portable to use only letters, digits, dashes, and underscores in 30 | header file names, and at most one dot. 31 | 32 | Read more about using header files in official GCC documentation: 33 | 34 | * Include Syntax 35 | * Include Operation 36 | * Once-Only Headers 37 | * Computed Includes 38 | 39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html 40 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # Continuous Integration (CI) is the practice, in software 2 | # engineering, of merging all developer working copies with a shared mainline 3 | # several times a day < https://docs.platformio.org/page/ci/index.html > 4 | # 5 | # Documentation: 6 | # 7 | # * Travis CI Embedded Builds with PlatformIO 8 | # < https://docs.travis-ci.com/user/integration/platformio/ > 9 | # 10 | # * PlatformIO integration with Travis CI 11 | # < https://docs.platformio.org/page/ci/travis.html > 12 | # 13 | # * User Guide for `platformio ci` command 14 | # < https://docs.platformio.org/page/userguide/cmd_ci.html > 15 | # 16 | # 17 | # Please choose one of the following templates (proposed below) and uncomment 18 | # it (remove "# " before each line) or use own configuration according to the 19 | # Travis CI documentation (see above). 20 | # 21 | 22 | 23 | # 24 | # Template #1: General project. Test it using existing `platformio.ini`. 25 | # 26 | 27 | # language: python 28 | # python: 29 | # - "2.7" 30 | # 31 | # sudo: false 32 | # cache: 33 | # directories: 34 | # - "~/.platformio" 35 | # 36 | # install: 37 | # - pip install -U platformio 38 | # - platformio update 39 | # 40 | # script: 41 | # - platformio run 42 | 43 | 44 | # 45 | # Template #2: The project is intended to be used as a library with examples. 46 | # 47 | 48 | # language: python 49 | # python: 50 | # - "2.7" 51 | # 52 | # sudo: false 53 | # cache: 54 | # directories: 55 | # - "~/.platformio" 56 | # 57 | # env: 58 | # - PLATFORMIO_CI_SRC=path/to/test/file.c 59 | # - PLATFORMIO_CI_SRC=examples/file.ino 60 | # - PLATFORMIO_CI_SRC=path/to/test/directory 61 | # 62 | # install: 63 | # - pip install -U platformio 64 | # - platformio update 65 | # 66 | # script: 67 | # - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N 68 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | // display 8 | U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE); 9 | const byte LCDROWS = 5; 10 | const byte LCDCOLS = 21; 11 | const byte FONTHEIGHT = 11; 12 | char buf[LCDROWS][LCDCOLS + 1]; 13 | // cursor 14 | short int pos = 0; 15 | 16 | // keyboard 17 | const byte ROWS = 7; 18 | const byte COLS = 5; 19 | 20 | const byte KS1 = '^'; // case shift character 21 | const byte KS2 = '%'; // symbol lock character 22 | 23 | char lowerKeys[ROWS][COLS] = { 24 | {'q', 'e', 'r', 'u', 'o'}, 25 | {'w', 's', 'g', 'h', 'l'}, 26 | {KS2, 'd', 't', 'y', 'i'}, 27 | {'a', 'p', KS1, '{', '<'}, 28 | {'>', 'x', 'v', 'b', '$'}, 29 | {' ', 'z', 'c', 'n', 'm'}, 30 | {'&', KS1, 'f', 'j', 'k'}}; 31 | 32 | char upperKeys[ROWS][COLS] = { 33 | {'Q', 'E', 'R', 'U', 'O'}, 34 | {'W', 'S', 'G', 'H', 'L'}, 35 | {KS2, 'D', 'T', 'Y', 'I'}, 36 | {'A', 'P', KS1, '{', '<'}, 37 | {'>', 'X', 'V', 'B', '$'}, 38 | {' ', 'Z', 'C', 'N', 'M'}, 39 | {'&', KS1, 'F', 'J', 'K'}}; 40 | 41 | char symKeys[ROWS][COLS] = { 42 | {'#', '2', '3', '_', '+'}, 43 | {'1', '4', '/', ':', '"'}, 44 | {KS2, '5', '(', ')', '-'}, 45 | {'*', '@', KS1, '{', '<'}, 46 | {'>', '8', '?', '!', '$'}, 47 | {' ', '7', '9', ',', '.'}, 48 | {'0', KS1, '6', ';', '\''}}; 49 | 50 | // all numbers are +1 since 0 is equal to NO_KEY 51 | // we're using this keyboard as a lookup table for the 52 | // above character arrays 53 | char indexKeys[ROWS][COLS] = { 54 | {1, 2, 3, 4, 5}, 55 | {6, 7, 8, 9, 10}, 56 | {11, 12, 13, 14, 15}, 57 | {16, 17, 18, 19, 20}, 58 | {21, 22, 23, 24, 25}, 59 | {26, 27, 28, 29, 30}, 60 | {31, 32, 33, 34, 35}}; 61 | 62 | byte rowPins[ROWS] = {15, 2, 0, 4, 16, 17, 13}; 63 | byte colPins[COLS] = {12, 14, 27, 26, 25}; 64 | 65 | Keypad indexedKeypad = Keypad(makeKeymap(indexKeys), rowPins, colPins, ROWS, COLS); 66 | 67 | bool symbolShift = false; 68 | bool capShift = false; 69 | 70 | void setupDisplay(void) 71 | { 72 | u8g2.begin(); 73 | u8g2.setFont(u8g2_font_t0_11_mr); 74 | u8g2.clearDisplay(); 75 | } 76 | 77 | void draw(void) 78 | { 79 | u8g2.clearBuffer(); // clear the internal memory 80 | 81 | for (int i = 0; i < LCDROWS; i++) 82 | { 83 | // draw each row 84 | u8g2.drawStr(0, FONTHEIGHT * (i + 1), buf[i]); 85 | } 86 | 87 | u8g2.sendBuffer(); // transfer internal memory to the display 88 | } 89 | 90 | char setKeyXY(int n, int &x, int &y) 91 | { 92 | // account for off by one since indexKeys starts at 1 93 | if (n > 0) 94 | { 95 | --n; 96 | } 97 | 98 | if (n < COLS) 99 | { 100 | x = 0; 101 | y = n; 102 | } 103 | else 104 | { 105 | x = n / COLS; 106 | y = n % COLS; 107 | } 108 | } 109 | 110 | bool isSymShift(int x, int y) 111 | { 112 | return lowerKeys[x][y] == KS2; 113 | } 114 | 115 | bool isCaseShift(int x, int y) 116 | { 117 | return lowerKeys[x][y] == KS1; 118 | } 119 | 120 | char getKeypadChar() 121 | { 122 | char key = NO_KEY; 123 | char indexKeyChar = indexedKeypad.getKey(); 124 | 125 | if (indexKeyChar != NO_KEY) 126 | { 127 | int x, y; 128 | setKeyXY((int)indexKeyChar, x, y); 129 | 130 | if (isSymShift(x, y)) 131 | { 132 | symbolShift = !symbolShift; 133 | capShift = false; 134 | } 135 | else if (isCaseShift(x, y)) 136 | { 137 | capShift = true; 138 | } 139 | else 140 | { 141 | if (symbolShift) 142 | { 143 | key = symKeys[x][y]; 144 | } 145 | else if (capShift) 146 | { 147 | key = upperKeys[x][y]; 148 | capShift = false; 149 | } 150 | else 151 | { 152 | key = lowerKeys[x][y]; 153 | } 154 | } 155 | } 156 | return key; 157 | } 158 | 159 | void clearBuf() 160 | { 161 | for (int i = 0; i < LCDROWS; i++) 162 | { 163 | for (int j = 0; j < LCDCOLS; j++) 164 | { 165 | buf[i][j] = 0; 166 | } 167 | } 168 | } 169 | 170 | void setup() 171 | { 172 | Serial.begin(115200); 173 | 174 | clearBuf(); 175 | setupDisplay(); 176 | 177 | Serial.println("end of setup"); 178 | } 179 | 180 | void loop() 181 | { 182 | char key = getKeypadChar(); 183 | 184 | if (key != NO_KEY) 185 | { 186 | Serial.println(key); 187 | 188 | int x = 0, y = 0; 189 | 190 | // basic cursor positioning 191 | if (pos == LCDROWS * LCDCOLS) 192 | { 193 | pos = 0; 194 | clearBuf(); 195 | } 196 | else 197 | { 198 | x = pos / LCDCOLS; 199 | y = pos % LCDCOLS; 200 | } 201 | buf[x][y] = key; 202 | ++pos; 203 | 204 | u8g2.firstPage(); 205 | do 206 | { 207 | draw(); 208 | } while (u8g2.nextPage()); 209 | } 210 | } 211 | --------------------------------------------------------------------------------