sohotcall

STM32duino Virtual Chicken Keyboard Firmware

May 19th, 2020
135
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Install arduino
  2. // Install Arduino SAM Boards (32-bits ARM Cortex-M3) from Boards Manager
  3. // Install https://github.com/rogerclarkmelbourne/Arduino_STM32/ to Documents/Arduino/hardware
  4. // Install https://github.com/arpruss/USBComposite_stm32f1/ to Documents/Arduino/libraries
  5. // Install your usb-to-ttl driver
  6. // Connect your blue pill to usb-to-ttl: 5V-5V, Gnd-Gnd, Tx(PA9)-Rx, Rx(PA10)-Tx
  7. // Connect usb-to-ttl to PC
  8. // Choose Tools->Boards->Generic STM32F103C series
  9. // Choose Tools->Variant->STM32F103C8 (20k RAM 64k Flash)
  10. // Choose Tools->Upload method->Serial
  11. // Choose Tools->CPU Speed (MHz)->48MHz (Slow, with USB)
  12. // Choose Tools->Port->COM1, or COM2, or COMsomething, I don't know
  13. // Ready? Upload
  14. // Unconnect blue pill from usb-to-ttl
  15. // Connect blue pill to PC with USB cable data
  16. #include <USBComposite.h>
  17. #define DEBUGNOTME
  18. USBHID HID;
  19. HIDKeyboard BootKeyboard( HID, 0 );
  20.  
  21. // HID key code matrix
  22. // Key code > 0x80 has modifier flag; its actual key code value is 0x80 less.
  23. // Key code = 0x00 is special key (Sym), illegal (---), or unused (???)
  24. const uint8_t QWERTIES[64] PROGMEM = {
  25.   0x00, 0x29, 0x14, 0x1A, 0x08, 0x15, 0x17, 0x00, // ---  Esc  Q    W    E    R    T    ???
  26.   0x2B, 0x00, 0x04, 0x16, 0x07, 0x09, 0x0A, 0x00, // Tab  ---  A    S    D    F    G    ???
  27.   0x82, 0x1D, 0x00, 0x1B, 0x06, 0x19, 0x05, 0x00, //(Shf) Z    ---  X    C    V    B    ???
  28.   0x81, 0x84, 0x88, 0x00, 0x49, 0x00, 0x2A, 0x00, //(Ctr)(Alt)(Win) ---  Ins (Sym) BSp  ???
  29.   0x0C, 0x18, 0x1C, 0x00, 0x00, 0x4C, 0x13, 0x12, // I    U    Y    ???  ---  Del  P    O
  30.   0x0E, 0x0D, 0x0B, 0x00, 0x28, 0x00, 0x33, 0x0F, // K    J    H    ???  Ret  ---  ;    L
  31.   0x36, 0x10, 0x11, 0X00, 0xA0, 0x38, 0x00, 0x37, // ,    L    K    ??? (Shf) /    ---  .
  32.   0x50, 0x00, 0x2C, 0x00, 0x4F, 0x52, 0x51, 0x00  // Lft (Sym) Spc  ???  Rgt  Up   Dwn  ---
  33. };
  34. const uint8_t SYMBOLS[64] PROGMEM = {
  35.   0x00, 0x35, 0x43, 0x44, 0x45, 0x3A, 0x3B, 0x00, // ---  `    F10  F11  F12  F1   F2   ???
  36.   0x39, 0x00, 0x42, 0x2F, 0x31, 0x30, 0x3C, 0x00, // Cap  ---  F9   [    \    ]    F3   ???
  37.   0x82, 0x41, 0x00, 0x40, 0x3F, 0x3E, 0x3D, 0x00, //(Shf) F8   ---  F7   F6   F5   F4   ???
  38.   0x81, 0x84, 0x88, 0x00, 0x00, 0x00, 0x2C, 0x00, //(Ctr)(Alt)(Win) --- (Qw) (Sym) Spc  ???
  39.   0x26, 0x25, 0x24, 0x00, 0x00, 0x46, 0x2D, 0x2E, // 9    8    7    ???  ---  Prt  -    =
  40.   0x23, 0x22, 0x21, 0x00, 0x58, 0x00, 0x33, 0x34, // 6    5    4    ???  Ret  ---  ;    '
  41.   0x20, 0x1F, 0x1E, 0x00, 0xA0, 0x38, 0x00, 0x37, // 3    2    1    ??? (Shf) /    ---  .
  42.   0x4A, 0x00, 0x27, 0x00, 0x4D, 0x4B, 0x4E, 0x00  // Hom (Sym) 0    ???  End  PgU  PgD  ---
  43. };
  44. const uint8_t WORKMANS[64] PROGMEM = {
  45.   0x00, 0x29, 0x14, 0x07, 0x15, 0x1A, 0x05, 0x00, // ---  Esc  Q    D    R    W    B    ???
  46.   0x2B, 0x00, 0x04, 0x16, 0x0B, 0x17, 0x0A, 0x00, // Tab  ---  A    S    H    T    G    ???
  47.   0x82, 0x1D, 0x00, 0x1B, 0x10, 0x06, 0x19, 0x00, //(Shf) Z    ---  X    M    C    V    ???
  48.   0x81, 0x84, 0x88, 0x00, 0x49, 0x00, 0x2A, 0x00, //(Ctr)(Alt)(Win) ---  Ins (Sym) BSp  ???
  49.   0x18, 0x09, 0x0D, 0x00, 0x00, 0x4C, 0x2D, 0x13, // U    F    J    ???  ---  Del  -    P
  50.   0x08, 0x11, 0x1C, 0x00, 0x28, 0x00, 0x0c, 0x12, // E    N    Y    ???  Ret  ---  I    O
  51.   0x36, 0x0F, 0x0E, 0x00, 0xA0, 0x38, 0x00, 0x37, // ,    L    K    ??? (Shf) /    ---  .
  52.   0x50, 0x00, 0x2C, 0x00, 0x4F, 0x52, 0x51, 0x00  // Lft (Sym) Spc  ???  Rgt  Up   Dwn  ---
  53. };
  54.  
  55. uint8_t scan[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  56. uint8_t keys[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  57. uint8_t matchCounter = 0;
  58.  
  59. uint8_t isWorkman = 1;
  60. void setup(){
  61.   Serial.begin( 115200 );
  62.   HID.begin( HID_BOOT_KEYBOARD );
  63.   BootKeyboard.begin();
  64.   delay( 1000 );
  65.   #ifdef DEBUGME
  66.     Serial.println( "Hello, world!" );
  67.   #endif
  68. }
  69. void loop(){
  70.   for ( uint8_t i = 0; i < 8; i++ ){
  71.     GPIOA->regs->CRL = 0x88888888 ^ ( 0x0000000B << ( i << 2 ) ); // Set pin i output, other pin input
  72.     GPIOA->regs->BSRR = ( 0x00000001 << i ) | 0x00FF0000 ^ ( 0x00010000 << i ); // Set pin i high, other pin low
  73.     delay(2);
  74.     uint8_t scanNow = GPIOA->regs->IDR & 0xFF; // Read pins (scan)
  75.     if ( scanNow == scan[i] )
  76.       matchCounter++; // Count how many times current scan are persistent with previous scan's
  77.     else {
  78.       matchCounter = 0; // If current scan differs than previous, reset counter
  79.       scan[i] = scanNow;
  80.     }
  81.     #ifdef DEBUGME
  82.       Serial.print( i );
  83.       Serial.print( " CRL " );
  84.       Serial.print( GPIOA->regs->CRL, HEX );
  85.       Serial.print( " BSRR " );
  86.       Serial.print( ( 0x00000001 << i ) | 0x00FF0000 ^ ( 0x00010000 << i ), BIN );
  87.       Serial.print( " IDR " );
  88.       Serial.print( GPIOA->regs->IDR & 0xFF, BIN );
  89.       Serial.print( " match " );
  90.       Serial.print( matchCounter );
  91.       Serial.print( " scanNow " );
  92.       Serial.println( scanNow, BIN );
  93.     #endif
  94.   }
  95.   if ( matchCounter >= 40 ){ // Scan result not change for 5 iterations ( 40 / 8 = 5 )
  96.     matchCounter = 0;
  97.     // Shift = (Sym:key71) xor (Shf:key20 or Shf:key64)
  98.     uint8_t isShift = ( ( scan[7] >> 1 ) ^ ( scan[2] | ( scan[6] >> 4 ) ) ) & 1;
  99.     // Symbol = (Sym:key71 or Sym:key35)
  100.     uint8_t isSymbol = ( scan[7] & 0x02 ) || ( scan[3] & 0x20 );
  101.     // activate workman mode on Shift+Symbol+(Qw), disactivate on Symbol+(Qw)
  102.     if ( isSymbol & ( scan[3] >> 4 ) )
  103.       isWorkman = isShift;
  104.     // Modifier = (Ctr:key30) or (Alt:key31) or (Win:key32)
  105.     uint8_t isModifier = scan[3] & 0x07;
  106.     // if Symbol use simbol matrix,
  107.     // elseif Modifier use qwerty matrix (because shortcut sucks in nonqwerty)
  108.     // elseif workman is activated use workman matrix
  109.     // else use qwerty matrix
  110.     const uint8_t *useWhich;
  111.     useWhich = QWERTIES;
  112.     if ( isSymbol )
  113.       useWhich = SYMBOLS;
  114.     else if ( ! isModifier && isWorkman )
  115.       useWhich = WORKMANS;
  116.     #ifdef DEBUGME
  117.       Serial.print( " isShift " );
  118.       Serial.print( isShift );
  119.       Serial.print( " isSymbol " );
  120.       Serial.print( isSymbol );
  121.       Serial.print( " isWorkman " );
  122.       Serial.println( isWorkman );
  123.     #endif
  124.     // build key set based on scan, capacity is limited. modifier + reserved + 6 keys = 8 slot
  125.     uint8_t keysNow[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
  126.     uint8_t keysNowPointer = 2;
  127.     for ( uint8_t i = 0; i < 8; i++ ){
  128.       for ( uint8_t j = 0; j < 8; j++ ){
  129.         if ( scan[i] & ( 1 << j ) ){
  130.           uint8_t scanCode = pgm_read_byte( useWhich + 8 * i + j ); // find key code from matrix
  131.           #ifdef DEBUGME
  132.             Serial.print( "Key " );
  133.             Serial.print( i );
  134.             Serial.print( j );
  135.             Serial.print(" Scan code " );
  136.             Serial.println( scanCode );
  137.           #endif
  138.           if ( scanCode & 0x80 ){
  139.             keysNow[0] |= scanCode & 0x7F; // It has modifier flag, combine to modifier slot
  140.           } else if ( scanCode && keysNowPointer < 8 ){ // do not overcapacity
  141.             keysNow[keysNowPointer] = scanCode; // normal key
  142.             keysNowPointer++;
  143.           }
  144.         }
  145.       }
  146.     }
  147.     uint8_t toSend = 0; // send key set if differ than previous sent
  148.     for ( uint8_t i = 0; i < 8; i++ ){
  149.       if ( keysNow[i] != keys[i] ){
  150.         keys[i] = keysNow[i];
  151.         toSend = 1;
  152.       }
  153.     }
  154.     #ifdef DEBUGME
  155.       Serial.print( " toSend " );
  156.       Serial.print( toSend );
  157.       Serial.print( " keys " );
  158.       Serial.print( keysNow[0], HEX ); Serial.print( '.' );
  159.       Serial.print( keysNow[1], HEX ); Serial.print( ' ' );
  160.       Serial.print( keysNow[2], HEX ); Serial.print( '.' );
  161.       Serial.print( keysNow[3], HEX ); Serial.print( '.' );
  162.       Serial.print( keysNow[4], HEX ); Serial.print( '.' );
  163.       Serial.print( keysNow[5], HEX ); Serial.print( '.' );
  164.       Serial.print( keysNow[6], HEX ); Serial.print( '.' );
  165.       Serial.print( keysNow[7], HEX ); Serial.println();
  166.     #endif
  167.     if ( toSend ){
  168.       #ifndef DEBUGME
  169.         Serial.print( keys[0], HEX ); Serial.print( '.' );
  170.         Serial.print( keys[1], HEX ); Serial.print( ' ' );
  171.         Serial.print( keys[2], HEX ); Serial.print( '.' );
  172.         Serial.print( keys[3], HEX ); Serial.print( '.' );
  173.         Serial.print( keys[4], HEX ); Serial.print( '.' );
  174.         Serial.print( keys[5], HEX ); Serial.print( '.' );
  175.         Serial.print( keys[6], HEX ); Serial.print( '.' );
  176.         Serial.print( keys[7], HEX ); Serial.println();
  177.       #endif
  178.       BootKeyboard.keyReport.modifiers = keys[0];
  179.       BootKeyboard.keyReport.reserved = keys[1];
  180.       BootKeyboard.keyReport.keys[0] = keys[2];
  181.       BootKeyboard.keyReport.keys[1] = keys[3];
  182.       BootKeyboard.keyReport.keys[2] = keys[4];
  183.       BootKeyboard.keyReport.keys[3] = keys[5];
  184.       BootKeyboard.keyReport.keys[4] = keys[6];
  185.       BootKeyboard.keyReport.keys[5] = keys[7];
  186.       BootKeyboard.sendReport();
  187.       delay(2);
  188.     }
  189.   }
  190.   #ifdef DEBUGME
  191.     delay( 10000 );
  192.   #endif
  193. }
RAW Paste Data