This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

How to create a nRF8001 configuration for touch device with nRFgo

According to Microsoft's instruction on HID touch device, msdn.microsoft.com/.../dn672271(v=vs.85).aspx, a HID touch device should create a report (descriptor) as below,

0x05, 0x0d,                         // USAGE_PAGE (Digitizers)          
0x09, 0x04,                         // USAGE (Touch Screen)             
0xa1, 0x01,                         // COLLECTION (Application)         
0x85, 0x01,                        //   REPORT_ID (Touch)              
0x09, 0x22,                         //   USAGE (Finger)                 
0xa1, 0x02,                         //     COLLECTION (Logical)  
0x09, 0x42,                         //       USAGE (Tip Switch)           
0x15, 0x00,                         //       LOGICAL_MINIMUM (0)          
0x25, 0x01,                         //       LOGICAL_MAXIMUM (1)          
0x75, 0x01,                         //       REPORT_SIZE (1)              
0x95, 0x01,                         //       REPORT_COUNT (1)             
0x81, 0x02,                         //       INPUT (Data,Var,Abs) 
0x95, 0x07,                         //       REPORT_COUNT (7)  
0x81, 0x03,                         //       INPUT (Cnst,Ary,Abs)
0x75, 0x08,                         //       REPORT_SIZE (8)
0x09, 0x51,                         //       USAGE (Contact Identifier)
0x95, 0x01,                         //       REPORT_COUNT (1)             
0x81, 0x02,                         //       INPUT (Data,Var,Abs) 
0x05, 0x01,                         //       USAGE_PAGE (Generic Desk..
0x26, 0xff, 0x0f,                   //       LOGICAL_MAXIMUM (4095)         
0x75, 0x10,                         //       REPORT_SIZE (16)             
0x55, 0x0e,                         //       UNIT_EXPONENT (-2)           
0x65, 0x13,                         //       UNIT(Inch,EngLinear)                  
0x09, 0x30,                         //       USAGE (X)                    
0x35, 0x00,                         //       PHYSICAL_MINIMUM (0)         
0x46, 0xb5, 0x04,                   //       PHYSICAL_MAXIMUM (1205)
0x95, 0x02,                         //       REPORT_COUNT (2)         
0x81, 0x02,                         //       INPUT (Data,Var,Abs)         
0x46, 0x8a, 0x03,                   //       PHYSICAL_MAXIMUM (906)
0x09, 0x31,                         //       USAGE (Y)                    
0x81, 0x02,                         //       INPUT (Data,Var,Abs)
0x05, 0x0d,                         //       USAGE_PAGE (Digitizers)
0x09, 0x48,                         //       USAGE (Width)                
0x09, 0x49,                         //       USAGE (Height)               
0x81, 0x02,                         //       INPUT (Data,Var,Abs)
0x95, 0x01,                         //       REPORT_COUNT (1)
0x55, 0x0C,                         //       UNIT_EXPONENT (-4)           
0x65, 0x12,                         //       UNIT (Radians,SIROtation)        
0x35, 0x00,                         //       PHYSICAL_MINIMUM (0)         
0x47, 0x6f, 0xf5, 0x00, 0x00,        //      PHYSICAL_MAXIMUM (62831)      
0x15, 0x00,                         //       LOGICAL_MINIMUM (0)      
0x27, 0x6f, 0xf5, 0x00, 0x00,       //       LOGICAL_MAXIMUM (62831)        
0x09, 0x3f,                         //       USAGE (Azimuth[Orientation]) 
0x81, 0x02,                         //       INPUT (Data,Var,Abs)  
0xc0,                               //    END_COLLECTION
0x09, 0x22,                         //   USAGE (Finger)                 
0xa1, 0x02,                         //     COLLECTION (Logical)  
0x09, 0x42,                         //       USAGE (Tip Switch)           
0x15, 0x00,                         //       LOGICAL_MINIMUM (0)          
0x25, 0x01,                         //       LOGICAL_MAXIMUM (1)          
0x75, 0x01,                         //       REPORT_SIZE (1)              
0x95, 0x01,                         //       REPORT_COUNT (1)             
0x81, 0x02,                         //       INPUT (Data,Var,Abs) 
0x95, 0x07,                         //       REPORT_COUNT (7)  
0x81, 0x03,                         //       INPUT (Cnst,Ary,Abs)
0x75, 0x08,                         //       REPORT_SIZE (8)
0x09, 0x51,                         //       USAGE (Contact Identifier)
0x95, 0x01,                         //       REPORT_COUNT (1)             
0x81, 0x02,                         //       INPUT (Data,Var,Abs) 
0x05, 0x01,                         //       USAGE_PAGE (Generic Desk..
0x26, 0xff, 0x0f,                   //       LOGICAL_MAXIMUM (4095)         
0x75, 0x10,                         //       REPORT_SIZE (16)             
0x55, 0x0e,                         //       UNIT_EXPONENT (-2)           
0x65, 0x13,                         //       UNIT(Inch,EngLinear)                  
0x09, 0x30,                         //       USAGE (X)                    
0x35, 0x00,                         //       PHYSICAL_MINIMUM (0)         
0x46, 0xb5, 0x04,                   //       PHYSICAL_MAXIMUM (1205)
0x95, 0x02,                         //       REPORT_COUNT (2)         
0x81, 0x02,                         //       INPUT (Data,Var,Abs)         
0x46, 0x8a, 0x03,                   //       PHYSICAL_MAXIMUM (906)
0x09, 0x31,                         //       USAGE (Y)                    
0x81, 0x02,                         //       INPUT (Data,Var,Abs)
0x05, 0x0d,                         //       USAGE_PAGE (Digitizers)
0x09, 0x48,                         //       USAGE (Width)                
0x09, 0x49,                         //       USAGE (Height)               
0x81, 0x02,                         //       INPUT (Data,Var,Abs)
0x95, 0x01,                         //       REPORT_COUNT (1)
0x55, 0x0C,                         //       UNIT_EXPONENT (-4)           
0x65, 0x12,                         //       UNIT (Radians,SIROtation)        
0x35, 0x00,                         //       PHYSICAL_MINIMUM (0)         
0x47, 0x6f, 0xf5, 0x00, 0x00,        //      PHYSICAL_MAXIMUM (62831)      
0x15, 0x00,                         //       LOGICAL_MINIMUM (0)      
0x27, 0x6f, 0xf5, 0x00, 0x00,       //       LOGICAL_MAXIMUM (62831)        
0x09, 0x3f,                         //       USAGE (Azimuth[Orientation]) 
0x81, 0x02,                         //       INPUT (Data,Var,Abs)  
0xc0,                               //    END_COLLECTION
0x05, 0x0d,                         //    USAGE_PAGE (Digitizers)
0x55, 0x0C,                         //     UNIT_EXPONENT (-4)           
0x66, 0x01, 0x10,                   //     UNIT (Seconds)        
0x47, 0xff, 0xff, 0x00, 0x00,      //       PHYSICAL_MAXIMUM (65535)
0x27, 0xff, 0xff, 0x00, 0x00,         //   LOGICAL_MAXIMUM (65535) 
0x75, 0x10,                           //   REPORT_SIZE (16)             
0x95, 0x01,                           //   REPORT_COUNT (1) 
0x09, 0x56,                         //   USAGE (Scan Time)    
0x81, 0x02,                           //   INPUT (Data,Var,Abs)         
0x09, 0x54,                         //   USAGE (Contact count)
0x25, 0x7f,                           //   LOGICAL_MAXIMUM (127) 
0x95, 0x01,                         //   REPORT_COUNT (1)
0x75, 0x08,                         //   REPORT_SIZE (8)    
0x81, 0x02,                         //   INPUT (Data,Var,Abs)
0x85, REPORTID_MAX_COUNT,            //   REPORT_ID (Feature)              
0x09, 0x55,                         //   USAGE(Contact Count Maximum)
0x95, 0x01,                         //   REPORT_COUNT (1)
0x25, 0x02,                         //   LOGICAL_MAXIMUM (2)
0xb1, 0x02,                         //   FEATURE (Data,Var,Abs)
0x85, 0x44,                      //   REPORT_ID (Feature)
0x06, 0x00, 0xff,                   //   USAGE_PAGE (Vendor Defined)  
0x09, 0xC5,                         //   USAGE (Vendor Usage 0xC5)    
0x15, 0x00,                         //   LOGICAL_MINIMUM (0)          
0x26, 0xff, 0x00,                   //   LOGICAL_MAXIMUM (0xff) 
0x75, 0x08,                         //   REPORT_SIZE (8)             
0x96, 0x00,  0x01,                  //   REPORT_COUNT (0x100 (256))             
0xb1, 0x02,                         //   FEATURE (Data,Var,Abs) 
0xc0,                               // END_COLLECTIONÂ  Â Â 

How can I create a nRF8001 configuration with nRFgo which meets the above requirements? I tried days but still could not get it right. Please help! Thanks!

  • Further to this question, in hid_keyboard_template, the HID_Report data size is set to 8 bytes, however, if I count the total bytes in the descriptor it should be 11 bytes, so it means the last 3 bytes is not used? And please kindly help me to understand how to interpret the data format in the report (as in below example). Is the data segmented by Usage Page? (Please see my notes in the example) If my understanding was wrong, please kindly correct me. Thank you very much!

    0xA1, 0x01,                         // Collection (Application)
    0x05, 0x07,                         //     Usage Page (Key Codes)  <== first data starts here?
    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)    <== first data ends here? what are the 5 bits means?
    0x05, 0x08,                         //     Usage Page (Page# for LEDs) <== second data starts here?
    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, 0x01,                         //     Output (Data, Variable, Absolute), Led report padding
    
  • I haven't used nRF8001 for quite some time. I will need to find our expert to help you when it come to deeper questions.

  • OK, thank you, Hung. If there is someone who can help, please kindly add more comments.

  • I have figured it out. Take the hid_template Joystick example for comparison.

    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x04,                    // USAGE (Joystick)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x85, 0x01,                    //   REPORT_ID (1)
    0xa1, 0x02,                    //   COLLECTION (Logical)
    0x09, 0x32,                    //     USAGE (Z)
    0x09, 0x31,                    //     USAGE (Y)
    0x09, 0x30,                    //     USAGE (X)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //     LOGICAL_MAXIMUM (255)
    0x35, 0x00,                    //     PHYSICAL_MINIMUM (0)
    0x46, 0xff, 0x00,              //     PHYSICAL_MAXIMUM (255)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x03,                    //     REPORT_COUNT (3)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0xc0,                          //   END_COLLECTION
    
    0x85, 0x02,                    // REPORT_ID (2)
    
    0xa1, 0x02,                    //   COLLECTION (Logical)
    0x05, 0x09,                    //     USAGE_PAGE (Button)
    0x29, 0x02,                    //     USAGE_MAXIMUM (Button 2)
    0x19, 0x01,                    //     USAGE_MINIMUM (Button 1)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x75, 0x01,                    //     REPORT_SIZE (1)
    0x25, 0x01,                    //     LOGICAL_MAXIMUM (1)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x81, 0x02,                    //     Input (Data, Variable, Absolute)
    0x95, 0x01,                    //     Report Count (1)
    0x75, 0x06,                    //     Report Size (6)
    0x81, 0x01,                    //     Input (Constant) for padding    
    0xc0,                          //   END_COLLECTION
    0xc0                           // END_COLLECTION
    

    There is a REPORT_ID (1) & (2), so the reference ID is 0101 (01 - Report ID, 01 - Type = Input). And in the hid_keyboard template, there is no Report ID, so the reference ID is 0001.

    Regarding the corresponding data, the hid_template for Joystick looks more clear. The first report (ID1) contains 3 bytes data, described in the Usagez as Z, Y, X, each for one byte with physical range 0~255 and mapping to logical range 0~255. The second report (ID2) contains 2 bits data for button 1 & 2 which represents the button on/off state. And there are 6 bits padding bits.

    I think I can now construct the digitizer configuration as listed in my question.

    Thanks for all the help!

Related