-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
I currently have two pico ws, one configured as a HOG Host, and one configured as a HOG Device, using code very similar to the hog keyboard hog host examples.
If i connect the device over bluetooth from a PC, i can get to poll rate around 850hz or so, which suggests that multiple packets are being sent per connection interval. However, if i instead connect to the HOG host running on a pico w, i end up with a poll rate of around 32hz, which lines up with the default 30ms connection interval.
If I then add the following line to the HOG host, I can lower the connection interval to the minimum 7.5ms, and I do end up seeing a poll rate of around 130hz or so, which also lines up with the 7.5ms connection interval.
gap_set_connection_parameters(0x0060, 0x0030, 0x06, 0x06, 0, 0x0048, 2, 0x0030);
I also ran BTStack locally on my PC using the libusb port, and found that that did get to around 850hz as well, so it does appear to just be an issue with the pico w port specifically.
My eventual goal is to use this to allow a user to create a usb adapter for a bluetooth controller i am working on that can then be plugged into a console, hence the need for a very low latency.
Activity
peterharperuk commentedon Apr 12, 2023
You'll have to provide more context about the code you're running. What method are you using polling, background or are you using an rtos? Do you have any code that demonstrates a problem. Note that we're not actually bluetooth experts here so your report is assuming lots of prior knowledge. I don't know what "interval" you're referring to for example. Unless you can clarify what you're reporting in a way I can investigate a problem you're unlikely to get any help.
sanjay900 commentedon Apr 12, 2023
Fair call, ill throw together a simplified repo that has an example for both sides of the pico. Ill admit I also don't really have much knowledge on the matter either, this was just what i gleamed after some experimentation with some of the btstack options, and some research.
From what i understand, BLE has a concept of a connection interval, which both sides of the connection agree on, and then the host will send out a packet each time the interval is hit. This can be configured but there is a lower limit of 7.5ms. It sounds like however you can sent multiple packets within this interval, which is how devices can update faster than 7.5ms.
I have essentially taken the hog_keyboard_demo and just have it sending data as often as possible, and with a PC (either using the linux bluetooth stack or btstack via libusb) it seems to be able to update at ~1ms or so, which suggests that this side of the equation is able to send out multiple packets per interval. I even left this side at the default connection interval of 30ms, so it is sending multiple packets per interval.
I then took the hog_host_demo and added a line to print out how often it receives data. It appears that
GATTSERVICE_SUBEVENT_HID_REPORT
is only ever fired once per connection interval here, so by default i only seem to get one report every 30ms. I can adjust the connection interval withgap_set_connection_parameters
and if i lower it to the minimum 7.5ms value, then i also noted that I would get reports every 7.5ms.I am using the background method, on both the device and the host.
peterharperuk commentedon Apr 12, 2023
Ok, thanks for adding some context. Examples (or modifications to existing examples) would be useful. In the background mode, we get an interrupt via a gpio to tell us there might be work to do (cyw43_gpio_irq_handler). This ends up in a call to cyw43_poll_func. We ask the chip if there's any work to do (cyw43_ll_bt_has_work) and call cyw43_bluetooth_hci_process which signals that a btstack data source has work to do. BTstack calls hci_transport_cyw43_process which keeps reading hci commands. So if the chip thinks there's nothing to do or there are no hci commands to read we won't try and "receive" anything. I would avoid debugging via logging as it's likely to affect timings. Probably best to use a logic analyser to work out what's going on.
mringwal commentedon Apr 12, 2023
@peterharperuk if there are more than one ACL packet stored in the cyw43 ring buffer, will all of them get processed in a row until it's empty? or does this require another interrrupt via the GPIO line?
peterharperuk commentedon Apr 12, 2023
@mringwal I think it should yes. hci_transport_cyw43_process keeps reading hci commands until there's no data (or an error). It's possible this loop is faulty somehow. It should perhaps keep going while cyw43_ll_bt_has_work is true. It might be worth debugging this area (without using printf).
sanjay900 commentedon Apr 12, 2023
https://gist.github.com/sanjay900/fe87afaad7474707459718d0945da759
Here is my gamepad implementation, i am currently testing by just sending a random value to an axis on each tick, which I can then use tools like
evhz
on linux to test with. For the pico receiver, the standard hog_host_demo is enough to demonstrate the problem, simply just printing the milliseconds since the last GATTSERVICE_SUBEVENT_HID_REPORT is enough to show the issue (I was actually testing this with a program that would redirect the inputs directly to USB hid and testing with evhz, so I was not dealing with printf delays on that front)You can listen to the LE_CONNECTION_COMPLETE event to get an idea of what the current interval is. I added this to the hog example locally just to work out what the current interval even was.
If you do just want to see the actual project i am testing with, it is at https://github.com/sanjay900/Ardwiino
mringwal commentedon Apr 12, 2023
@sanjay900 Could you run gatt_streamer_server on one pico and le_streamer_client on the other. le_streamer_client should be configured to use TEST_MODE_ENABLE_NOTIFICATIONS - so it's only receiving. As the demo prints the throughput, we can check how many packets are sent per interval.
I still don't see how only a single packet could get received in a connection interval. The sender in peripheral role will send as long as the central allows it to send and the central will keep the connection event open until it's buffers overflow. event with controller to host flow control, we should get a least a few packets per conn interval.
sanjay900 commentedon Apr 12, 2023
Let me just build both of those and i will give it a try
sanjay900 commentedon Apr 12, 2023
Hmm, doesn't seem to be working right, here are the logs from the le_streamer_client
And from the gatt_streamer_server:
mringwal commentedon Apr 12, 2023
@peterharperuk did anybody complain about all pico w using the same BD ADDR? In @sanjay900's logs, both have 43:43:A2:12:1F:AC - the first 6 hex digits indicate the used controller, a 4343A2.
I don't remember exactly, but BTstack avoids connections to devices with the same BD ADDR, as that allows for some sneaky security hacks.
@sanjay900 Thanks for trying. I can check myself tomorrow or Friday.
sanjay900 commentedon Apr 12, 2023
It does however seem like something is broken with updating the connection parameters, as commenting out
gap_request_connection_parameter_update(con_handle, 12, 12, 0, 0x0048);
is enough to make it run. I actually found this myself too when i was looking for ways to increase my connection interval, but just assumed i was doing something wrong when it hung.@peterharperuk
Do you want this raised as a separate issue, or just kept here? I have no idea where that problem lies as it is just something i have found by testing.
@mringwal here is the output with that line commented out
sanjay900 commentedon Apr 12, 2023
@mringwal
I know there are fixes for that in the develop branch, and I also had that thought myself but i ran my hid code with the develop branch and didn't really find it affected anything.
To run these examples I just pulled the pico-examples repo down for running these tests, which grabbed the currently released SDK which doesn't have the fix for BT addresses.
peterharperuk commentedon Apr 12, 2023
Yes 43:43:A2:12:1F:AC is the default btstack address (hardcoded in the infineon firmware to always be the same). I have a fix on develop that makes sure the btstack address is +1 the wifi mac address.
However I still haven't got to the bottom of why this issue is happening. I was unsure if it was because the OTP had not been set in the factory or if we had devices with duplicate addresses. @sanjay900 I would appreciate it if I could see the lines that say something like this for both the devices you have...
80 remaining items
ricardoquesada commentedon Jan 13, 2025
Any update on this bug ? is there an ETA ? ty!
mitchellcairns commentedon Feb 10, 2025
Also would appreciate an update on this
peterharperuk commentedon Feb 12, 2025
It requires firmware changes which I think means it's unlikely to happen.
ricardoquesada commentedon Feb 20, 2025
thanks @peterharperuk
IIRC, Infineon should fix it, correct ?
And also, without this fix, there is no possible workaround, correct ?
ty.
mringwal commentedon Feb 20, 2025
@ricardoquesada how does this affect your project?
From going through the comments, I'm not able to fully summarize the issue:
It would be nice to test what happens to e.g. 40 byte packets that have to get split into two almost full packets.
ricardoquesada commentedon Feb 20, 2025
@mringwal
TBH, I don't fully understand this bug.
Some Bluepad32 users reported that some packets are "delayed" (or "lost") when using Pico W. But this bug does not appear on ESP32.
By packets I mean HID reports from Gamepad controllers.... (not sure whether they were BLE or BR/EDR packets... I have to double-check it).
My understanding is that as soon as the packet arrives to HCI, it sends it to BTstack, and BTstack sends it to Bluepad32... and there is no "buffer manipulation": no copies of buffers, not a pool of buffers, etc...
So, Bluepad32 receives the packet "directly" from the "wire".
So, users were concerned with why some packets were "delayed".
A user did some investigation and found this bug. I looked at it and seems similar to what the users noticed.
ricardoquesada commentedon Feb 20, 2025
@mringwal what is DLE ? and how can I test it ?
(I don't have the test equipment with me ATM, but I can try it in about 2 weeks)
mringwal commentedon Feb 20, 2025
@ricardoquesada No Bluetooth HCI ACL packets (e.g. HID) have been harmed / lost!
This issue is about a significant drop in throughput, but no data is getting lost on the receiving side. You would "just" get less HID reports. There might be a question about what the game controller does if it cannot send as fast as it likes. In any case, this behaviour is 100% deterministic and not sporadic.
(DLE is Data Length Extension, which allows to send packets larger than 27 bytes (23 usable for ATT PDUs -> 20 bytes payload for notification)).
ricardoquesada commentedon Feb 20, 2025
@mringwal
got it. I"ll try to reproduce it locally with some BLE controllers, with some HCI dumps (in case it helps).
but IIUC, there nothing that we can do in BTstack/Pico SDK to mitigate the bug, correct?
(e.g: Tell the gamepad controller to not send packets bigger than 20 bytes, or similar)
For context: this seems to be an important bug for Bluepad32 users. Bluepad32 is used mostly to interface with robots and/or retro gaming consoles, and a 500ms in delay heavily affects the usability.
mringwal commentedon Feb 20, 2025
@ricardoquesada No, there's not much you could do. Please try to reproduce, I don't think this explains your delays. Even with this issue, the Controller can receive one ACL packet per connection interval of 7.5-15 ms, so that's way below 500 ms and no problem to control stuff.
ricardoquesada commentedon Feb 20, 2025
@mringwal ty. I"ll do that.
(TBH, I don't recall the delay the users reported... perhaps 500ms is too much... in any case, I'll do my own testings and report my findings here... in about two weeks once I got home)
ricardoquesada commentedon Apr 11, 2025
(better late than never...)
I think I figured it outWhen there is a connected device and Pico is in "scanning mode", then it will delivered the packets from the connected device with some delaysHowever, when I stop "scanning mode", the packets from the connected device don't have any kind of delayIndeed, disabling scanning mode seems to have more throughput, but the latency increases like ~0.5 when scanning is disabled (?)... But when I re-enable it it does not improve the latency.
I'll attach relevant logs later today.
update:
I have HCI dump working
oudated:
side question: how do I capture/print the HCI packets on Pico ?
Like this ? (it is in my notes, but I don't see any HCI packet on UART)
mringwal commentedon Apr 14, 2025
If the CYW4343 needs to scan for device it reduces the time it can use for the ACL connection, so it's recommended to turn of scanning once you're connected.
ricardoquesada commentedon Apr 14, 2025
@mringwal yes, thanks. At this point I'm sure what is triggering the bug.
Need to do more tests (had a very week last week, hopefully tomorrow I'll be able to continue with the tests)