Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Install arduino
- // Install Arduino SAM Boards (32-bits ARM Cortex-M3) from Boards Manager
- // Install https://github.com/rogerclarkmelbourne/Arduino_STM32/ to Documents/Arduino/hardware
- // Install https://github.com/arpruss/USBComposite_stm32f1/ to Documents/Arduino/libraries
- // Install your usb-to-ttl driver
- // Connect your blue pill to usb-to-ttl: 5V-5V, Gnd-Gnd, Tx(PA9)-Rx, Rx(PA10)-Tx
- // Connect usb-to-ttl to PC
- // Choose Tools->Boards->Generic STM32F103C series
- // Choose Tools->Variant->STM32F103C8 (20k RAM 64k Flash)
- // Choose Tools->Upload method->Serial
- // Choose Tools->CPU Speed (MHz)->48MHz (Slow, with USB)
- // Choose Tools->Port->COM1, or COM2, or COMsomething, I don't know
- // Ready? Upload
- // Unconnect blue pill from usb-to-ttl
- // Connect blue pill to PC with USB cable data
- #include <USBComposite.h>
- #define DEBUGNOTME
- USBHID HID;
- HIDKeyboard BootKeyboard( HID, 0 );
- // HID key code matrix
- // Key code > 0x80 has modifier flag; its actual key code value is 0x80 less.
- // Key code = 0x00 is special key (Sym), illegal (---), or unused (???)
- const uint8_t QWERTIES[64] PROGMEM = {
- 0x00, 0x29, 0x14, 0x1A, 0x08, 0x15, 0x17, 0x00, // --- Esc Q W E R T ???
- 0x2B, 0x00, 0x04, 0x16, 0x07, 0x09, 0x0A, 0x00, // Tab --- A S D F G ???
- 0x82, 0x1D, 0x00, 0x1B, 0x06, 0x19, 0x05, 0x00, //(Shf) Z --- X C V B ???
- 0x81, 0x84, 0x88, 0x00, 0x49, 0x00, 0x2A, 0x00, //(Ctr)(Alt)(Win) --- Ins (Sym) BSp ???
- 0x0C, 0x18, 0x1C, 0x00, 0x00, 0x4C, 0x13, 0x12, // I U Y ??? --- Del P O
- 0x0E, 0x0D, 0x0B, 0x00, 0x28, 0x00, 0x33, 0x0F, // K J H ??? Ret --- ; L
- 0x36, 0x10, 0x11, 0X00, 0xA0, 0x38, 0x00, 0x37, // , L K ??? (Shf) / --- .
- 0x50, 0x00, 0x2C, 0x00, 0x4F, 0x52, 0x51, 0x00 // Lft (Sym) Spc ??? Rgt Up Dwn ---
- };
- const uint8_t SYMBOLS[64] PROGMEM = {
- 0x00, 0x35, 0x43, 0x44, 0x45, 0x3A, 0x3B, 0x00, // --- ` F10 F11 F12 F1 F2 ???
- 0x39, 0x00, 0x42, 0x2F, 0x31, 0x30, 0x3C, 0x00, // Cap --- F9 [ \ ] F3 ???
- 0x82, 0x41, 0x00, 0x40, 0x3F, 0x3E, 0x3D, 0x00, //(Shf) F8 --- F7 F6 F5 F4 ???
- 0x81, 0x84, 0x88, 0x00, 0x00, 0x00, 0x2C, 0x00, //(Ctr)(Alt)(Win) --- (Qw) (Sym) Spc ???
- 0x26, 0x25, 0x24, 0x00, 0x00, 0x46, 0x2D, 0x2E, // 9 8 7 ??? --- Prt - =
- 0x23, 0x22, 0x21, 0x00, 0x58, 0x00, 0x33, 0x34, // 6 5 4 ??? Ret --- ; '
- 0x20, 0x1F, 0x1E, 0x00, 0xA0, 0x38, 0x00, 0x37, // 3 2 1 ??? (Shf) / --- .
- 0x4A, 0x00, 0x27, 0x00, 0x4D, 0x4B, 0x4E, 0x00 // Hom (Sym) 0 ??? End PgU PgD ---
- };
- const uint8_t WORKMANS[64] PROGMEM = {
- 0x00, 0x29, 0x14, 0x07, 0x15, 0x1A, 0x05, 0x00, // --- Esc Q D R W B ???
- 0x2B, 0x00, 0x04, 0x16, 0x0B, 0x17, 0x0A, 0x00, // Tab --- A S H T G ???
- 0x82, 0x1D, 0x00, 0x1B, 0x10, 0x06, 0x19, 0x00, //(Shf) Z --- X M C V ???
- 0x81, 0x84, 0x88, 0x00, 0x49, 0x00, 0x2A, 0x00, //(Ctr)(Alt)(Win) --- Ins (Sym) BSp ???
- 0x18, 0x09, 0x0D, 0x00, 0x00, 0x4C, 0x2D, 0x13, // U F J ??? --- Del - P
- 0x08, 0x11, 0x1C, 0x00, 0x28, 0x00, 0x0c, 0x12, // E N Y ??? Ret --- I O
- 0x36, 0x0F, 0x0E, 0x00, 0xA0, 0x38, 0x00, 0x37, // , L K ??? (Shf) / --- .
- 0x50, 0x00, 0x2C, 0x00, 0x4F, 0x52, 0x51, 0x00 // Lft (Sym) Spc ??? Rgt Up Dwn ---
- };
- uint8_t scan[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- uint8_t keys[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- uint8_t matchCounter = 0;
- uint8_t isWorkman = 1;
- void setup(){
- Serial.begin( 115200 );
- HID.begin( HID_BOOT_KEYBOARD );
- BootKeyboard.begin();
- delay( 1000 );
- #ifdef DEBUGME
- Serial.println( "Hello, world!" );
- #endif
- }
- void loop(){
- for ( uint8_t i = 0; i < 8; i++ ){
- GPIOA->regs->CRL = 0x88888888 ^ ( 0x0000000B << ( i << 2 ) ); // Set pin i output, other pin input
- GPIOA->regs->BSRR = ( 0x00000001 << i ) | 0x00FF0000 ^ ( 0x00010000 << i ); // Set pin i high, other pin low
- delay(2);
- uint8_t scanNow = GPIOA->regs->IDR & 0xFF; // Read pins (scan)
- if ( scanNow == scan[i] )
- matchCounter++; // Count how many times current scan are persistent with previous scan's
- else {
- matchCounter = 0; // If current scan differs than previous, reset counter
- scan[i] = scanNow;
- }
- #ifdef DEBUGME
- Serial.print( i );
- Serial.print( " CRL " );
- Serial.print( GPIOA->regs->CRL, HEX );
- Serial.print( " BSRR " );
- Serial.print( ( 0x00000001 << i ) | 0x00FF0000 ^ ( 0x00010000 << i ), BIN );
- Serial.print( " IDR " );
- Serial.print( GPIOA->regs->IDR & 0xFF, BIN );
- Serial.print( " match " );
- Serial.print( matchCounter );
- Serial.print( " scanNow " );
- Serial.println( scanNow, BIN );
- #endif
- }
- if ( matchCounter >= 40 ){ // Scan result not change for 5 iterations ( 40 / 8 = 5 )
- matchCounter = 0;
- // Shift = (Sym:key71) xor (Shf:key20 or Shf:key64)
- uint8_t isShift = ( ( scan[7] >> 1 ) ^ ( scan[2] | ( scan[6] >> 4 ) ) ) & 1;
- // Symbol = (Sym:key71 or Sym:key35)
- uint8_t isSymbol = ( scan[7] & 0x02 ) || ( scan[3] & 0x20 );
- // activate workman mode on Shift+Symbol+(Qw), disactivate on Symbol+(Qw)
- if ( isSymbol & ( scan[3] >> 4 ) )
- isWorkman = isShift;
- // Modifier = (Ctr:key30) or (Alt:key31) or (Win:key32)
- uint8_t isModifier = scan[3] & 0x07;
- // if Symbol use simbol matrix,
- // elseif Modifier use qwerty matrix (because shortcut sucks in nonqwerty)
- // elseif workman is activated use workman matrix
- // else use qwerty matrix
- const uint8_t *useWhich;
- useWhich = QWERTIES;
- if ( isSymbol )
- useWhich = SYMBOLS;
- else if ( ! isModifier && isWorkman )
- useWhich = WORKMANS;
- #ifdef DEBUGME
- Serial.print( " isShift " );
- Serial.print( isShift );
- Serial.print( " isSymbol " );
- Serial.print( isSymbol );
- Serial.print( " isWorkman " );
- Serial.println( isWorkman );
- #endif
- // build key set based on scan, capacity is limited. modifier + reserved + 6 keys = 8 slot
- uint8_t keysNow[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
- uint8_t keysNowPointer = 2;
- for ( uint8_t i = 0; i < 8; i++ ){
- for ( uint8_t j = 0; j < 8; j++ ){
- if ( scan[i] & ( 1 << j ) ){
- uint8_t scanCode = pgm_read_byte( useWhich + 8 * i + j ); // find key code from matrix
- #ifdef DEBUGME
- Serial.print( "Key " );
- Serial.print( i );
- Serial.print( j );
- Serial.print(" Scan code " );
- Serial.println( scanCode );
- #endif
- if ( scanCode & 0x80 ){
- keysNow[0] |= scanCode & 0x7F; // It has modifier flag, combine to modifier slot
- } else if ( scanCode && keysNowPointer < 8 ){ // do not overcapacity
- keysNow[keysNowPointer] = scanCode; // normal key
- keysNowPointer++;
- }
- }
- }
- }
- uint8_t toSend = 0; // send key set if differ than previous sent
- for ( uint8_t i = 0; i < 8; i++ ){
- if ( keysNow[i] != keys[i] ){
- keys[i] = keysNow[i];
- toSend = 1;
- }
- }
- #ifdef DEBUGME
- Serial.print( " toSend " );
- Serial.print( toSend );
- Serial.print( " keys " );
- Serial.print( keysNow[0], HEX ); Serial.print( '.' );
- Serial.print( keysNow[1], HEX ); Serial.print( ' ' );
- Serial.print( keysNow[2], HEX ); Serial.print( '.' );
- Serial.print( keysNow[3], HEX ); Serial.print( '.' );
- Serial.print( keysNow[4], HEX ); Serial.print( '.' );
- Serial.print( keysNow[5], HEX ); Serial.print( '.' );
- Serial.print( keysNow[6], HEX ); Serial.print( '.' );
- Serial.print( keysNow[7], HEX ); Serial.println();
- #endif
- if ( toSend ){
- #ifndef DEBUGME
- Serial.print( keys[0], HEX ); Serial.print( '.' );
- Serial.print( keys[1], HEX ); Serial.print( ' ' );
- Serial.print( keys[2], HEX ); Serial.print( '.' );
- Serial.print( keys[3], HEX ); Serial.print( '.' );
- Serial.print( keys[4], HEX ); Serial.print( '.' );
- Serial.print( keys[5], HEX ); Serial.print( '.' );
- Serial.print( keys[6], HEX ); Serial.print( '.' );
- Serial.print( keys[7], HEX ); Serial.println();
- #endif
- BootKeyboard.keyReport.modifiers = keys[0];
- BootKeyboard.keyReport.reserved = keys[1];
- BootKeyboard.keyReport.keys[0] = keys[2];
- BootKeyboard.keyReport.keys[1] = keys[3];
- BootKeyboard.keyReport.keys[2] = keys[4];
- BootKeyboard.keyReport.keys[3] = keys[5];
- BootKeyboard.keyReport.keys[4] = keys[6];
- BootKeyboard.keyReport.keys[5] = keys[7];
- BootKeyboard.sendReport();
- delay(2);
- }
- }
- #ifdef DEBUGME
- delay( 10000 );
- #endif
- }
Add Comment
Please, Sign In to add comment