Closed expresspotato closed 1 year ago
So nearly 3 weeks without comment, the best I can do is attach an example of this and note that I have also see the following line missing on iPhone, but present on Android:
W (248283) BT_HCI: hcif mode change: hdl 0x80, mode 0, intv 0, status 0x0
Seems like something is preventing the bt controller from returning to sniff mode.
The attached source is from a much larger project, with the majority taken out. It should be run on the LyraT v4.3 board and has IO22 (green LED) set to display when in / out of light sleep.
pipeline_a2dp_sink_and_hfp.zip
Light sleep is really important with our mass production project here as it is battery powered and plays audio from a device often.
@expresspotato Please test again with following menuconfig:
Component config -> FreeRTOS -> Tick rate (100 -> 1000)
Change the tick rate from 100 to 1000.
Hi @BetterJincheng thanks for the suggestion but it didn't make a difference...
Anyone from @espressif?
@expresspotato Please test again with following menuconfig:
Component config -> FreeRTOS -> Tick rate (100 -> 1000)
Change the tick rate from 100 to 1000.
@BetterJincheng What's the point of this change?
Hello anyone from Espressif (@espressif-bot),
This functionality is pretty critical for our application, and iPhone is a huge user base that's easy to target bug fixes for (since the OS behaves nearly identically across all generations of device).
The above example demonstrates the easy to reproduce problem. Is anyone able to take a look / comment?
@expresspotato We have tested the example examples/bluetooth/bluedroid/classic_bt/a2dp_sink at latest master branch using an ESP32. Nothing wrong with IOS devices on light sleep. You can have a try. Please let me know the test result and we will provide you with some support if needed.
Modify this in bt_app_av.c
:
/* when audio stream transmission state changed, this event comes */
case ESP_A2D_AUDIO_STATE_EVT: {
a2d = (esp_a2d_cb_param_t *)(p_param);
ESP_LOGI(BT_AV_TAG, "A2DP audio state: %s", s_a2d_audio_state_str[a2d->audio_stat.state]);
s_audio_state = a2d->audio_stat.state;
if (ESP_A2D_AUDIO_STATE_STARTED == a2d->audio_stat.state) {
s_pkt_cnt = 0;
} else if (ESP_A2D_AUDIO_STATE_REMOTE_SUSPEND == a2d->audio_stat.state) {
bt_i2s_driver_uninstall();
}
break;
}
PS: ADD THIS: Component config -> FreeRTOS -> Tick rate (100 -> 1000)
Hello @BetterJincheng,
So using v4.4.3 there was no difference using the code above, as in my example zip attached above in this thread, the audio control (via pipline stop / terminate, audio_hal_ctrl_codec(..., AUDIO_HAL_CTRL_STOP), is already stopped when ESP_A2D_AUDIO_STATE_REMOTE_SUSPEND
event comes.
Using v4.4.3 with the tick change, I can see that light sleep is possible, but it's not the same as on Android, the duty cycle is 9/10 vs Android's 1/10. This is unlikely to net any power savings when compared to Android. Something is preventing it from having a shorter duty cycle even though the ESP32 requests SNIFF mode.
The ESP32 receives the mode change:
Android: W (116346) BT_HCI: hci cmd send: sniff: hdl 0x81, intv(30 54) W (116375) BT_HCI: hcif mode change: hdl 0x81, mode 2, intv 54, status 0x0
The key is the HCI SSR (Sniff Sub-Rating) event takes place. After this command the duty cycle returns to 10/100 on Android. W (116529) BT_HCI: hcif ssr evt: st 0x0, hdl 0x81, tx_lat 54 rx_lat 1188
Which is not seen on iOS: W (43321) BT_HCI: hci cmd send: sniff: hdl 0x80, intv(30 54) W (43337) BT_HCI: hcif mode change: hdl 0x80, mode 2, intv 54, status 0x0 ...
Even though the mode change comes, no ssr event comes, and the duty cycle remains 9/10. I couldn't get this to compile on master, it seems ADF is not yet compatible with it yet, so the only version tested is v4.4.3.
Included is a video of this behaviour. 1) Board is reset, Android is connected. 2) Audio is played, audio is paused. 3) Light sleep resumes, connection remains.
4) Board is reset, iPhone is connected (doesn't seem to matter which, X, 11, 12, 5S) 5) Audio is played, audio is paused. 3) Light sleep is possible, but the duty cycle is very high, there is no HCI SSR event.
@expresspotato ESP32 has requeseted for a sniff subrating of 22, but iPhone responded with a sniff subrating of 1. So ESP32 should wake to RX every 1*sniff_interval. It seems that the problem is not on the ESP32 side.
ESP32 lmp_sniff_subrating_req
iPhone lmp_sniff_subrating_res
Maybe you can increase the sniff interval to save power. However it will increase the latency. In file bta_api.h
:
#define BTA_DM_PM_SNIFF4_MAX 54
#define BTA_DM_PM_SNIFF4_MIN 30
Maybe you can have a try.
#define BTA_DM_PM_SNIFF4_MAX 540
#define BTA_DM_PM_SNIFF4_MIN 300
Thanks for reporting, will close due to short of feedback, feel free to reopen with more updates. Thanks.
Thank you @BetterJincheng, @Alvin1Zhang, the change you suggested worked perfectly 👍
Answers checklist.
IDF version.
v4.4.3
Operating System used.
macOS
How did you build your project?
Command line with idf.py
If you are using Windows, please specify command line type.
No response
Development Kit.
LyraT v4.3
Power Supply used.
USB
What is the expected behavior?
The CPU should return to light sleep, after the audio is paused. It does this with a Galaxy S22+, but not with an iPhone 5s, SE or X.
What is the actual behavior?
The CPU remains active, by virtue of:
// Dev board green LED will show when in light sleep or not gpio_set_direction(GPIO_NUM_22, GPIO_MODE_OUTPUT); gpio_set_level(GPIO_NUM_22, 1); gpio_sleep_sel_en(GPIO_NUM_22);
Steps to reproduce.
Debug Logs.
More Information.
It appears that the connection does in fact go into SNIFF mode, but the following even is missing on iPhone, but is present on my S22+
W (33027) BT_HCI: hcif ssr evt: st 0x0, hdl 0x81, tx_lat 54 rx_lat 1188