nrf52832 nkro

Hi Q&A 

At present, there is no routine found on the Internet about NRF52832 Bluetooth sending more than 6 characters(NKRO)

I used nRF5_SDK_17.1.0,The following is the modified report_map_data[] and BOOT_KB_INPUT_REPORT_MAX_SIZE,But never made It.

static uint8_t                     report_map_data[] =
    {  
			0x05, 0x01, // Usage Page (Generic Desktop)
			0x09, 0x06, // Usage (Keyboard)
			0xA1, 0x01, // Collection (Application)
			0x85, REPORT_ID_KEYBOARD,//REPORT_ID (0)
			0x05, 0x07, // Usage Page (Key Codes)
			0x19, 0xe0, // Usage Minimum (224)
			0x29, 0xe7, // Usage Maximum (231)
			0x15, 0x00, // Logical Minimum (0)
			0x25, 0x01, // Logical Maximum (1)
			0x75, 0x01, // Report Size (1)
			0x95, 0x08, // Report Count (8)
			0x81, 0x02, // Input (Data, Variable, Absolute)

			0x95, 0x01, // Report Count (1)
			0x75, 0x08, // Report Size (8)
			0x81, 0x01, // Input (Constant) reserved byte(1)

			0x95, 0x05, // Report Count (5)
			0x75, 0x01, // Report Size (1)
			0x05, 0x08, // Usage Page (Page# for LEDs)
			0x19, 0x01, // Usage Minimum (1)
			0x29, 0x05, // Usage Maximum (5)
			0x91, 0x02, // Output (Data, Variable, Absolute), Led report
			
			0x95, 0x01, // Report Count (1)
			0x75, 0x03, // Report Size (3)
			0x91, 0x03, // 1-Output (Data, Variable, Absolute), Led report padding
			#ifdef NKRO 
				0x95, 0x3d,
			#else
				0x95, 0x06,
			#endif
			0x75, 0x08, //08- Report Size (8)
			0x15, 0x00, //00- Logical Minimum (0)
			0x25, 0x01, //01- Logical Maximum (101)
			0x05, 0x07, // Usage Page (Key codes)
			0x19, 0x00, // Usage Minimum (0)
			0x29, 0x65, // Usage Maximum (101)
			0x81, 0x00, // Input (Data, Array) Key array(6 bytes)
		//----------------------------------------------------------------------		
			0x09, 0x05,       // Usage (Vendor Defined)
			0x15, 0x00,       // Logical Minimum (0)
			0x26, 0xFF, 0x00, // Logical Maximum (255)
			0x75, 0x08,       // Report Size (8 bit)
			0x95, 0x02,       // Report Count (2)
			0xB1, 0x02,       // Feature (Data, Variable, Absolute)
		//-----------------------------------------------------------------------
			0xC0,     // End Collection (Application)

			/* mouse */
			0x05, 0x01,      //USAGE_PAGE (Generic Desktop)
			0x09, 0x02,      //USAGE (Mouse)
			0xa1, 0x01,      //COLLECTION (Application)
			0x85, REPORT_ID_MOUSE, //REPORT_ID (1)
			0x09, 0x01,      //USAGE (Pointer)
			0xa1, 0x00,      //COLLECTION (Physical)
			// ----------------------------  Buttons
			0x05, 0x09, //     USAGE_PAGE (Button)   //1BYTE
			0x19, 0x01, //     USAGE_MINIMUM (Button 1)
			0x29, 0x05, //     USAGE_MAXIMUM (Button 5)
			0x15, 0x00, //     LOGICAL_MINIMUM (0)
			0x25, 0x01, //     LOGICAL_MAXIMUM (1)
			0x75, 0x01, //     REPORT_SIZE (1)
			0x95, 0x05, //     REPORT_COUNT (5)
			0x81, 0x02, //     INPUT (Data,Var,Abs)
			0x75, 0x03, //     REPORT_SIZE (3)
			0x95, 0x01, //     REPORT_COUNT (1)
			0x81, 0x03, //     INPUT (Cnst,Var,Abs)
			// ----------------------------  X,Y position
			0x05, 0x01, //     USAGE_PAGE (Generic Desktop)//2 BYTES
			0x09, 0x30, //     USAGE (X)
			0x09, 0x31, //     USAGE (Y)
			0x15, 0x81, //     LOGICAL_MINIMUM (-127)
			0x25, 0x7f, //     LOGICAL_MAXIMUM (127)
			0x75, 0x08, //     REPORT_SIZE (8)
			0x95, 0x02, //     REPORT_COUNT (2)
			0x81, 0x06, //     INPUT (Data,Var,Rel)
			// ----------------------------  Vertical wheel  //1 BYTE
			0x09, 0x38, //     USAGE (Wheel)
			0x15, 0x81, //     LOGICAL_MINIMUM (-127)
			0x25, 0x7f, //     LOGICAL_MAXIMUM (127)
			0x35, 0x00, //     PHYSICAL_MINIMUM (0)        - reset physical
			0x45, 0x00, //     PHYSICAL_MAXIMUM (0)
			0x75, 0x08, //     REPORT_SIZE (8)
			0x95, 0x01, //     REPORT_COUNT (1)
			0x81, 0x06, //     INPUT (Data,Var,Rel)
			// ----------------------------  Horizontal wheel
			0x05, 0x0c, //     USAGE_PAGE (Consumer Devices)  //1BYTE
			0x0a, 0x38, 0x02, //     USAGE (AC Pan)
			0x15, 0x81, //     LOGICAL_MINIMUM (-127)
			0x25, 0x7f, //     LOGICAL_MAXIMUM (127)
			0x75, 0x08, //     REPORT_SIZE (8)
			0x95, 0x01, //     REPORT_COUNT (1)
			0x81, 0x06, //     INPUT (Data,Var,Rel)
			0xc0,              //END_COLLECTION
			// system
			0x05, 0x01,      //USAGE_PAGE (Generic Desktop)
			0x09, 0x80,      //USAGE (System Control)
			0xa1, 0x01,      //COLLECTION (Application)
			0x85, REPORT_ID_SYSTEM, //REPORT_ID (2)
			0x15, 0x01,      //   LOGICAL_MINIMUM (0x1)
			0x26, 0xb7, 0x00, //  LOGICAL_MAXIMUM (0xb7)
			0x19, 0x01,     //   USAGE_MINIMUM (0x1)
			0x29, 0xb7,     //   USAGE_MAXIMUM (0xb7)
			0x75, 0x10,     //   REPORT_SIZE (16)
			0x95, 0x01,     //   REPORT_COUNT (1)
			0x81, 0x00,     //   INPUT (Data,Array,Abs)
			0xc0,           // END_COLLECTION
			0xc0,           // END_COLLECTION
     //consumer
			0x05, 0x0c,         // USAGE_PAGE (Consumer Devices)
			0x09, 0x01,         // USAGE (Consumer Control)
			0xa1, 0x01,         // COLLECTION (Application)
			0x85, REPORT_ID_CONSUMER, //REPORT_ID (3)
			0x15, 0x01,       //LOGICAL_MINIMUM (0x1)
			0x26, 0x9c, 0x02, //LOGICAL_MAXIMUM (0x29c)  
			0x19, 0x01,       //USAGE_MINIMUM (0x1)
			0x2a, 0x9c, 0x02, //USAGE_MAXIMUM (0x29c)    
			0x75, 0x10,       //REPORT_SIZE (16)
			0x95, 0x01,       //REPORT_COUNT (1)
			0x81, 0x00,       //INPUT (Data,Array,Abs)
			0xc0,             //END_COLLECTION
    };

  • Hi Zbxiong, 
    Could you let me know what exactly happen when you try to test ? 
    There is a related ticket you can find here: Encountered a problem sending more than 6 bytes of data using the hid service 

    The last reply pointed to this https://learn.adafruit.com/custom-hid-devices-in-circuitpython/n-key-rollover-nkro-hid-device

    Could you take a look at the page to see the report there and check if you can use that in your project ? 
    We have quite limited experience with NKRO here.

  •    I read the QMK NKRO generation rules.

       nkro is to split the code returned by the key by shifting it and then send it.

    #define NKRO_REPORT_BITS 30
    
    typedef struct {
        uint8_t report_id;
        uint8_t mods;
        uint8_t bits[NKRO_REPORT_BITS];
    }report_nkro_t;
    
    void add_key_bit(report_nkro_t* nkro_report, uint8_t code) {
        if ((code >> 3) < NKRO_REPORT_BITS) {
            nkro_report->bits[code >> 3] |= 1 << (code & 7);
        }
    }
    
    void add_key_to_report(uint8_t key) {
        if (keyboard_protocol && keymap_config.nkro) {
            add_key_bit(nkro_report, key);
            return;
        }
    }
    
    void host_nkro_send(report_nkro_t *report) {
        if (!driver) return;
        report->report_id = REPORT_ID_NKRO;
        (*driver->send_nkro)(report);
    }

    But I don't understand how the NRF52832 receiver sends this data.

            0x05, 0x01,                     // Usage Page (Generic Desktop),
            0x09, 0x06,                     // Usage (Keyboard),
            0xA1, 0x01,                     // Collection (Application),
            0x85, REPORT_ID_KEYBOARD,       //   Report ID
            // bitmap of modifiers
            0x75, 0x01,                     //   Report Size (1),
            0x95, 0x08,                     //   Report Count (8),
            0x05, 0x07,                     //   Usage Page (Key Codes),
            0x19, 0xE0,                     //   Usage Minimum (224),
            0x29, 0xE7,                     //   Usage Maximum (231),
            0x15, 0x00,                     //   Logical Minimum (0),
            0x25, 0x01,                     //   Logical Maximum (1),
            0x81, 0x02,                     //   Input (Data, Variable, Absolute), ;Modifier byte
            // LED output report
            0x95, 0x05,                     //   Report Count (5),
            0x75, 0x01,                     //   Report Size (1),
            0x05, 0x08,                     //   Usage Page (LEDs),
            0x19, 0x01,                     //   Usage Minimum (1),
            0x29, 0x05,                     //   Usage Maximum (5),
            0x91, 0x02,                     //   Output (Data, Variable, Absolute),
            0x95, 0x01,                     //   Report Count (1),
            0x75, 0x03,                     //   Report Size (3),
            0x91, 0x03,                     //   Output (Constant),
            // bitmap of keys
            0x95, (NKRO_REPORT_BITS-1)*8,   //   Report Count (),
            0x75, 0x01,                     //   Report Size (1),
            0x15, 0x00,                     //   Logical Minimum (0),
            0x25, 0x01,                     //   Logical Maximum(1),
            0x05, 0x07,                     //   Usage Page (Key Codes),
            0x19, 0x00,                     //   Usage Minimum (0),
            0x29, NKRO_REPORT_BITS * 8 - 1, //   Usage Maximum (),
            0x81, 3,                        //0x02,   //   Input (Data, Variable, Absolute),
            0xc0,                           // End Collection

  • Hi, 
    I'm afraid I couldn't help on this. We have very limited experience with NKRO. 
    Our suggestion is to take a look at this open source project: 
    https://zmk.dev/docs/config/bluetooth

    It's based on Zephyr and it has NKRO supported. 

Related