Related
I am trying to use and STM32F0-disco as a keyboard for a Windows PC. I'm having a problem with the characters that are being printed.
The code below waits until the onboard button is pressed then should print the three characters once.
/* USER CODE BEGIN 2 */
USBDelay = USBD_HID_GetPollingInterval(&hUsbDeviceFS);
while (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 0);
if (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 1) {
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
buff[0] = 0x00;
buff[2] = 0x04;
buff[3] = 0x05;
buff[4] = 0x06;
USBD_HID_SendReport(&hUsbDeviceFS, buff, 8);
HAL_Delay(USBDelay);
buff[0] = 0x00;
buff[2] = 0x00;
buff[3] = 0x00;
buff[4] = 0x00;
USBD_HID_SendReport(&hUsbDeviceFS, buff, 8);
HAL_GPIO_TogglePin(LD4_GPIO_Port, LD4_Pin);
HAL_Delay(1000);
}
while (HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 1);
/* USER CODE END 2 */
The problem I'm having is that the only the characters in the first two key positions of the buffer (which would be the third and fourth elements of the array since element one is the modifier and the second element is reserved). Also, instead of printing once, the characters print continuously without stopping.
Based on the LED's I've added for testing purposes, the characters that I want to print don't print until the second USB_SendReport, which should be sending blank characters to stop the printing.
I've made the necessary changes to usbd_hid.c and usbd_hid.h, as well as the Clock configuration and enabling USB and such. I've put my keyboard descriptor below.
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
Any ideas?
The USB HID protocol works differently than you assume. If the input report contains multiple pressed keys, the host (your Windows PC) assumes that they have been pressed at the same time. So they can be inserted in any order. And it might also be the reason the third key is not inserted.
So you need to send a separate output report for each key. And after the last report you need to send another empty one (with all 0s) to indicate the keys have been released (as you are already doing). Such an additional report is also needed between two presses of the same key.
The reason the keys are inserted continuously indicates the empty report was not received. Even though the function uses the term send (USBD_HID_SendReport()), the USB protocol works such that the host needs to pick up the input report. And since it is an USB interrupt endpoint, this only happens ever so often. If a report hasn't been picked up yet, USBD_HID_SendReport() does nothing. It not even returns an error.
While querying to polling interval (USBD_HID_GetPollingInterval()) looks ok at first, it's the polling interval declared in the USB endpoint descriptor. However, Windows only supports a few interval values and rounds up to the next supported value. So you have to increase the value.
How to read and write the data in the BNO085 sensor through I2C.
I2C interface is available sensor but no register data are available in datasheet.
It has something called a 'sensor-hub' and you can use SH2 specific commands, which are written through the I2C to configure BNO and get data. For instance, writing the following through I2C will configure BNO to stream orientation as 'ARVR-Stabilized Rotation Vector (0x28)' at 50
Hz (20us = 0x4e20).
CARGO_NO++;
START_BNO_ALGO[21] = {0x15, 0x00, 0x02, CARGO_NO, 0xFD, 0x28, 0x00, 0x00, 0x00, 0x20, 0x4e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
I2C_Write(BNO085_ADDRESS, START_BNO_ALGO, 21);
Then you can simply I2C_Read the BNO at 50Hz (ideally at BNO interrupt) to get orientation. Hope this will help you to get started.
Please check the 'SH-2 Reference Manual' and the 'Sensor Hub Transport Protocol' for more details.
I'm trying to decode some Unicode strings from a binary file. I know that they are encoded as UTF-16, and they have a 'big endian' BOM (0xFFFE). But when I try to turn them into a string I end up with a bunch of Chinese characters.
var bytes:[UInt8] = [0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x0E, 0xFE]
let text = NSString(bytes: &bytes, length: bytes.count, encoding:NSUTF16BigEndianStringEncoding)
print(text)
This prints Chinese ideograms and a [?] rather than "ABC‼︎", which is what (I believe) it should.
I've tried different encodings but nothing works correctly. Can anyone help?
The data sample you provide is coded little endian.
I don't know if it is you sample data or not.
Well, there's probably something wrong with your input.
First, BOM should be placed as a first sequence in the input. Second, the order of bytes you provided are reversed.
This example shows correct parsing:
var bytes:[UInt8] = [0xFF, 0xFE, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00]
var text = NSString(bytes: &bytes, length: bytes.count, encoding:NSUTF16LittleEndianStringEncoding)!
print(text) // prints "ABC\n"
bytes = [0xFE, 0xFF, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43]
text = NSString(bytes: &bytes, length: bytes.count, encoding:NSUTF16BigEndianStringEncoding)!
print(text) // "ABC\n"
I want to convert 'unsigned char' 'uchar16'. At first, I Direct convert it, but it run error.
uchar16* out;
unsigned char ciphertext[16];
/*
*
*/
out[0] = (uchar16)(ciphertext[0], ciphertext[1], ciphertext[2], ciphertext[3],
ciphertext[4], ciphertext[5], ciphertext[6], ciphertext[7],
ciphertext[8], ciphertext[9], ciphertext[10], ciphertext[11],
ciphertext[12], ciphertext[13], ciphertext[14], ciphertext[15]);
When I use real value instead of the variable, it runs.
out[0] = (uchar16)(0x2B, 0x7E, 0x15, 0x16,
0x28, 0xAE, 0xD2, 0xA6,
0xAB, 0xF7, 0x15, 0x88,
0x09, 0xCF, 0x4F, 0x3C);
I searched in Google and Stackoverflow, and I did not find the answer.
For vector conversion in OpenCL there is the suite of functions:
convert_destType(sourceType)
See point 6.2.3 of the standard (v1.2). So in your case it would be:
uchar16 out = convert_uchar16(ciphertext);
What is the error you get?
It is simpler and generally more efficient to call vload16 in this case:
uchar16 u = vload16(0,ciphertext);
I developing a network application and using socket APIs.
I want to set sin6_addr byte order of sockaddr_in6 structure.
For 16 bits or 32 bits variables, it is simple: Using htons or htonl:
// IPv4
sockaddr_in addr;
addr.sin_port = htons(123);
addr.sin_addr.s_addr = htonl(123456);
But for 128 bits variables, I dont know how to set byte order to network byte order:
// IPv6
sockaddr_in6 addr;
addr.sin6_port = htons(123);
addr.sin6_addr.s6_addr = ??? // 16 bytes with network byte order but how to set?
Some answers may be using htons for 8 times (2 * 8 = 16 bytes), or using htonl for 4 times (4 * 4 = 16 bytes), but I don't know which way is correct.
Thanks.
The s6_addr member of struct in6_addr is defined as:
uint8_t s6_addr[16];
Since it is an array of uint8_t, rather than being a single 128-bit integer type, the issue of endianness does not arise: you simply copy from your source uint8_t [16] array to the destination. For example, to copy in the address 2001:888:0:2:0:0:0:2 you would use:
static const uint8_t myaddr[16] = { 0x20, 0x01, 0x08, 0x88, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02 };
memcpy(addr.sin6_addr.s6_addr, myaddr, sizeof myaddr);
The usual thing would be to use one of the hostname lookup routines and use the result of that, which is already in network byte order. How come you're dealing with hardcoded numeric IP addresses at all?