SHARE
TWEET

Untitled

a guest Jan 17th, 2019 53 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*********************************************************************
  2.  This is an example for our nRF52 based Bluefruit LE modules
  3.  
  4.  Pick one up today in the adafruit shop!
  5.  
  6.  Adafruit invests time and resources providing this open source code,
  7.  please support Adafruit and open-source hardware by purchasing
  8.  products from Adafruit!
  9.  
  10.  MIT license, check LICENSE for more information
  11.  All text above, and the splash screen below must be included in
  12.  any redistribution
  13. *********************************************************************/
  14. #include <bluefruit.h>
  15.  
  16. /*
  17.  * Implement the Bluefruit command AT+BLEKEYBOARDCODE command.
  18.  * Nothing else useful. Useful for testing a Python program designed to work
  19.  * with a BF LE UART Friend. Lots of this code is from an Adafruit example.
  20.  */
  21.  
  22. BLEDis bledis;
  23. BLEHidAdafruit blehid;
  24.  
  25. void setup()
  26. {
  27.   Serial.begin(115200);
  28.   while ( !Serial && millis() < 2000) delay(10);   // for nrf52840 with native usb
  29.  
  30.   Serial.println("Bluefruit52 HID Keyboard Example");
  31.   Serial.println("--------------------------------\n");
  32.  
  33.   Serial.println();
  34.   Serial.println("Go to your phone's Bluetooth settings to pair your device");
  35.   Serial.println("then open an application that accepts keyboard input");
  36.  
  37.   Bluefruit.begin();
  38.   // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
  39.   Bluefruit.setTxPower(4);
  40.   Bluefruit.setName("Bluefruit52");
  41.  
  42.   // Configure and Start Device Information Service
  43.   bledis.setManufacturer("Adafruit Industries");
  44.   bledis.setModel("Bluefruit Feather 52");
  45.   bledis.begin();
  46.  
  47.   /* Start BLE HID
  48.    * Note: Apple requires BLE device must have min connection interval >= 20m
  49.    * ( The smaller the connection interval the faster we could send data).
  50.    * However for HID and MIDI device, Apple could accept min connection interval
  51.    * up to 11.25 ms. Therefore BLEHidAdafruit::begin() will try to set the min and max
  52.    * connection interval to 11.25  ms and 15 ms respectively for best performance.
  53.    */
  54.   blehid.begin();
  55.  
  56.   // Set callback for set LED from central
  57.   blehid.setKeyboardLedCallback(set_keyboard_led);
  58.  
  59.   /* Set connection interval (min, max) to your perferred value.
  60.    * Note: It is already set by BLEHidAdafruit::begin() to 11.25ms - 15ms
  61.    * min = 9*1.25=11.25 ms, max = 12*1.25= 15 ms
  62.    */
  63.   /* Bluefruit.setConnInterval(9, 12); */
  64.  
  65.   // Set up and start advertising
  66.   startAdv();
  67. }
  68.  
  69. void startAdv(void)
  70. {  
  71.   // Advertising packet
  72.   Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  73.   Bluefruit.Advertising.addTxPower();
  74.   Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);
  75.  
  76.   // Include BLE HID service
  77.   Bluefruit.Advertising.addService(blehid);
  78.  
  79.   // There is enough room for the dev name in the advertising packet
  80.   Bluefruit.Advertising.addName();
  81.  
  82.   /* Start Advertising
  83.    * - Enable auto advertising if disconnected
  84.    * - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
  85.    * - Timeout for fast mode is 30 seconds
  86.    * - Start(timeout) with timeout = 0 will advertise forever (until connected)
  87.    *
  88.    * For recommended advertising interval
  89.    * https://developer.apple.com/library/content/qa/qa1931/_index.html  
  90.    */
  91.   Bluefruit.Advertising.restartOnDisconnect(true);
  92.   Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
  93.   Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  94.   Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds
  95. }
  96.  
  97. typedef void (*action_func_t)(char *myLine);
  98.  
  99. typedef struct {
  100.   char command[32+1];    // max 32 characters plus '\0' terminator
  101.   action_func_t action;
  102. } command_action_t;
  103.  
  104. // force lower case
  105. void toLower(char *s) {
  106.   while (*s) {
  107.     if (isupper(*s)) {
  108.       *s += 0x20;
  109.     }
  110.     s++;
  111.   }
  112. }
  113.  
  114. void sendHIDReport(char *myLine) {
  115.   uint8_t keys[8];  // USB keyboard HID report
  116.  
  117.   memset(keys, 0, sizeof(keys));
  118.   // myLine example: "00-00-04-00-00-00-00-00"
  119.   char *p = strtok(myLine, "-");
  120.   for (size_t i = 0; p && (i < sizeof(keys)); i++) {
  121.     keys[i] = strtoul(p, NULL, 16);
  122.     p = strtok(NULL, "-");
  123.   }
  124.   blehid.keyboardReport(keys[0], &keys[2]);
  125.   Serial.println("OK");
  126. }
  127.  
  128. const command_action_t commands[] = {
  129.   // Name of command user types, function that implements the command.
  130.   // TODO add other commands, some day
  131.   {"at+blekeyboardcode", sendHIDReport},
  132. };
  133.  
  134. void execute(char *myLine) {
  135.   if (myLine == NULL || *myLine == '\0') return;
  136.   char *cmd = strtok(myLine, "=");
  137.   if (cmd == NULL || *cmd == '\0') return;
  138.   toLower(cmd);
  139.   for (size_t i = 0; i < sizeof(commands)/sizeof(commands[0]); i++) {
  140.     if (strcmp(cmd, commands[i].command) == 0) {
  141.       commands[i].action(strtok(NULL, "="));
  142.       return;
  143.     }
  144.   }
  145.   // Command not found so just send OK. Should send ERROR at some point.
  146.   Serial.println("OK");
  147. }
  148.  
  149. void cli_loop()
  150. {
  151.   static uint8_t bytesIn;
  152.   static char myLine[80+1];
  153.  
  154.   while (Serial.available() > 0) {
  155.     int b = Serial.read();
  156.     if (b != -1) {
  157.       switch (b) {
  158.         case '\n':
  159.           break;
  160.         case '\r':
  161.           Serial.println();
  162.           myLine[bytesIn] = '\0';
  163.           execute(myLine);
  164.           bytesIn = 0;
  165.           break;
  166.         case '\b':  // backspace
  167.           if (bytesIn > 0) {
  168.             bytesIn--;
  169.             Serial.print((char)b); Serial.print(' '); Serial.print((char)b);
  170.           }
  171.           break;
  172.         default:
  173.           Serial.print((char)b);
  174.           myLine[bytesIn++] = (char)b;
  175.           if (bytesIn >= sizeof(myLine)-1) {
  176.             myLine[bytesIn] = '\0';
  177.             execute(myLine);
  178.             bytesIn = 0;
  179.           }
  180.           break;
  181.       }
  182.     }
  183.   }
  184. }
  185.  
  186. void loop()
  187. {
  188.   cli_loop();
  189.   // Request CPU to enter low-power mode until an event/interrupt occurs
  190.   waitForEvent();  
  191. }
  192.  
  193. /**
  194.  * Callback invoked when received Set LED from central.
  195.  * Must be set previously with setKeyboardLedCallback()
  196.  *
  197.  * The LED bit map is as follows: (also defined by KEYBOARD_LED_* )
  198.  *    Kana (4) | Compose (3) | ScrollLock (2) | CapsLock (1) | Numlock (0)
  199.  */
  200. void set_keyboard_led(uint8_t led_bitmap)
  201. {
  202.   // light up Red Led if any bits is set
  203.   if ( led_bitmap )
  204.   {
  205.     ledOn( LED_RED );
  206.   }
  207.   else
  208.   {
  209.     ledOff( LED_RED );
  210.   }
  211. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top