1 #include <optional>
2 #include <string_view>
3 #include <vector>
4
5 #include "NxpUwbChip.h"
6 #include "phNxpConfig.h"
7 #include "phNxpUciHal.h"
8 #include "phNxpUciHal_ext.h"
9 #include "phNxpUciHal_utils.h"
10 #include "phUwbStatus.h"
11 #include "phUwbTypes.h"
12 #include "phNxpUwbCalib.h"
13 #include "uci_defs.h"
14
15 #define UCI_MSG_UWB_ESE_BINDING_LEN 11
16 #define UCI_MSG_UWB_ESE_BINDING_OFFSET_COUNT 5
17 #define UCI_MSG_UWB_ESE_BINDING_OFFSET_BINDING_STATE 6
18
19 extern phNxpUciHal_Control_t nxpucihal_ctrl;
20
report_binding_status(uint8_t binding_status)21 static void report_binding_status(uint8_t binding_status)
22 {
23 // BINDING_STATUS_NTF
24 uint8_t data_len = 5;
25 uint8_t buffer[5];
26 buffer[0] = 0x6E;
27 buffer[1] = 0x06;
28 buffer[2] = 0x00;
29 buffer[3] = 0x01;
30 buffer[4] = binding_status;
31 if (nxpucihal_ctrl.p_uwb_stack_data_cback != NULL) {
32 (*nxpucihal_ctrl.p_uwb_stack_data_cback)(data_len, buffer);
33 }
34 }
35
36 /******************************************************************************
37 * Function otp_read_data
38 *
39 * Description Read OTP calibration data
40 *
41 * Returns true on success
42 *
43 ******************************************************************************/
otp_read_data(const uint8_t channel,const uint8_t param_id,uint8_t * buffer,size_t len)44 static bool otp_read_data(const uint8_t channel, const uint8_t param_id, uint8_t *buffer, size_t len)
45 {
46 phNxpUciHal_Sem_t calib_data_ntf_wait;
47 phNxpUciHal_init_cb_data(&calib_data_ntf_wait);
48
49 // NXP_READ_CALIB_DATA_NTF
50 bool received = false;
51 auto read_calib_ntf_cb =
52 [&] (size_t packet_len, const uint8_t *packet) mutable -> bool
53 {
54 // READ_CALIB_DATA_NTF: status(1), length-of-payload(1), payload(N)
55 const uint8_t plen = packet[3]; // payload-length
56 const uint8_t *p = &packet[4]; // payload
57
58 if (plen < 2) {
59 NXPLOG_UCIHAL_E("Otp read: bad payload length %u", plen);
60 } else if (p[0] != UCI_STATUS_OK) {
61 NXPLOG_UCIHAL_E("Otp read: bad status=0x%x", packet[4]);
62 } else if (p[1] != len) {
63 NXPLOG_UCIHAL_E("Otp read: size mismatch %u (expected %zu for param 0x%x)",
64 p[1], len, param_id);
65 } else {
66 memcpy(buffer, &p[2], len);
67 received = true;
68 SEM_POST(&calib_data_ntf_wait);
69 }
70 return true;
71 };
72 auto handler = phNxpUciHal_rx_handler_add(
73 UCI_MT_NTF, UCI_GID_PROPRIETARY_0X0A, UCI_MSG_READ_CALIB_DATA,
74 true, read_calib_ntf_cb);
75
76
77 // READ_CALIB_DATA_CMD
78 std::vector<uint8_t> packet{(UCI_MT_CMD << UCI_MT_SHIFT) | UCI_GID_PROPRIETARY_0X0A, UCI_MSG_READ_CALIB_DATA, 0x00, 0x03};
79 packet.push_back(channel);
80 packet.push_back(0x01); // OTP read option
81 packet.push_back(param_id);
82
83 tHAL_UWB_STATUS status = phNxpUciHal_send_ext_cmd(packet.size(), packet.data());
84 if (status != UWBSTATUS_SUCCESS) {
85 goto fail_otp_read_data;
86 }
87
88 phNxpUciHal_sem_timed_wait_sec(&calib_data_ntf_wait, 3);
89 if (!received) {
90 goto fail_otp_read_data;
91 }
92
93 phNxpUciHal_cleanup_cb_data(&calib_data_ntf_wait);
94 return true;
95
96 fail_otp_read_data:
97 phNxpUciHal_cleanup_cb_data(&calib_data_ntf_wait);
98 NXPLOG_UCIHAL_E("Failed to read OTP data id=%u", param_id);
99 return false;
100 }
101
sr1xx_read_otp(extcal_param_id_t id,uint8_t * data,size_t data_len,size_t * retlen)102 static tHAL_UWB_STATUS sr1xx_read_otp(extcal_param_id_t id, uint8_t *data, size_t data_len, size_t *retlen)
103 {
104 switch(id) {
105 case EXTCAL_PARAM_CLK_ACCURACY:
106 {
107 const size_t param_len = 6;
108 uint8_t otp_xtal_data[3];
109
110 if (data_len < param_len) {
111 NXPLOG_UCIHAL_E("Requested RF_CLK_ACCURACY_CALIB with %zu bytes (expected >= %zu)", data_len, param_len);
112 return UWBSTATUS_FAILED;
113 }
114 if (!otp_read_data(0x09, OTP_ID_XTAL_CAP_GM_CTRL, otp_xtal_data, sizeof(otp_xtal_data))) {
115 NXPLOG_UCIHAL_E("Failed to read OTP XTAL_CAP_GM_CTRL");
116 return UWBSTATUS_FAILED;
117 }
118 memset(data, 0, param_len);
119 // convert OTP_ID_XTAL_CAP_GM_CTRL to EXTCAL_PARAM_RX_ANT_DELAY
120 data[0] = otp_xtal_data[0]; // cap1
121 data[2] = otp_xtal_data[1]; // cap2
122 data[4] = otp_xtal_data[2]; // gm_current_control (default: 0x30)
123 *retlen = param_len;
124 return UWBSTATUS_SUCCESS;
125 }
126 break;
127 default:
128 NXPLOG_UCIHAL_E("Unsupported otp parameter %d", id);
129 return UWBSTATUS_FAILED;
130 }
131 }
132
133 //
134 // SR1XX Error handlers (Thermal Runaway, LOW VBATT)
135 //
136
sr1xx_handle_device_error()137 static void sr1xx_handle_device_error()
138 {
139 /* Send FW crash NTF to upper layer for triggering MW recovery */
140 phNxpUciHal_send_dev_error_status_ntf();
141 }
142
sr1xx_clear_device_error()143 static void sr1xx_clear_device_error()
144 {
145 }
146
147 //
148 // SE binding
149 //
150
151 // Temporarily disable DPD for binding, vendor config should re-enable it
sr1xx_disable_dpd()152 static tHAL_UWB_STATUS sr1xx_disable_dpd()
153 {
154 uint8_t buffer[] = {0x20, 0x04, 0x00, 0x04, 0x01, 0x01, 0x01, 0x00};
155 return phNxpUciHal_send_ext_cmd(sizeof(buffer), buffer);
156 }
157
158 /******************************************************************************
159 * Function sr1xx_do_bind
160 *
161 * Description Sends UWB_ESE_BINDING_CMD and returns
162 * updated binding status and remaining UWBS binding count
163 *
164 * Returns status
165 *
166 ******************************************************************************/
sr1xx_do_bind(uint8_t * binding_status,uint8_t * remain_count)167 static tHAL_UWB_STATUS sr1xx_do_bind(uint8_t *binding_status, uint8_t *remain_count)
168 {
169 tHAL_UWB_STATUS status;
170
171 // register rx handler for UWB_ESE_BINDING_NTF
172 phNxpUciHal_Sem_t binding_ntf_wait;
173 phNxpUciHal_init_cb_data(&binding_ntf_wait);
174
175 auto binding_ntf_cb =
176 [&](size_t packet_len, const uint8_t *packet) mutable -> bool
177 {
178 if (packet_len == UCI_MSG_UWB_ESE_BINDING_LEN) {
179 uint8_t status = packet[UCI_RESPONSE_STATUS_OFFSET];
180 if (status != UWBSTATUS_SUCCESS) {
181 NXPLOG_UCIHAL_E("UWB_ESE_BINDING_NTF: Binding failed, status=0x%x", status);
182 }
183 *binding_status = packet[UCI_MSG_UWB_ESE_BINDING_OFFSET_BINDING_STATE];
184 *remain_count = packet[UCI_MSG_UWB_ESE_BINDING_OFFSET_COUNT];
185 NXPLOG_UCIHAL_D("Received UWB_ESE_BINDING_NTF, status=0x%x, binding_state=0x%x, count=%u",
186 status, *binding_status, *remain_count);
187 SEM_POST(&binding_ntf_wait);
188 } else {
189 NXPLOG_UCIHAL_E("UWB_ESE_BINDING_NTF: packet length mismatched %zu", packet_len);
190 }
191 return true;
192 };
193 auto handler = phNxpUciHal_rx_handler_add(
194 UCI_MT_NTF, UCI_GID_PROPRIETARY_0X0F, UCI_MSG_UWB_ESE_BINDING,
195 true, binding_ntf_cb);
196
197 // UWB_ESE_BINDING_CMD
198 uint8_t buffer[] = {0x2F, 0x31, 0x00, 0x00};
199 status = phNxpUciHal_send_ext_cmd(sizeof(buffer), buffer);
200 if (status != UWBSTATUS_SUCCESS) {
201 NXPLOG_UCIHAL_E("Failed to send UWB_ESE_BINDING_CMD");
202 goto exit_do_bind;
203 }
204
205 if (phNxpUciHal_sem_timed_wait(&binding_ntf_wait) ||
206 binding_ntf_wait.status != UWBSTATUS_SUCCESS) {
207 NXPLOG_UCIHAL_E("Failed to retrieve UWB_ESE_BINDING_NTF");
208 goto exit_do_bind;
209 }
210
211 status = UWBSTATUS_SUCCESS;
212
213 exit_do_bind:
214 phNxpUciHal_rx_handler_del(handler);
215 phNxpUciHal_cleanup_cb_data(&binding_ntf_wait);
216 return status;
217 }
218
219 /******************************************************************************
220 * Function sr1xx_check_binding_status
221 *
222 * Description Send UWB_ESE_BINDING_CHECK_CMD and returns updated binding status
223 *
224 * Returns status
225 *
226 ******************************************************************************/
sr1xx_check_binding_status(uint8_t * binding_status)227 static tHAL_UWB_STATUS sr1xx_check_binding_status(uint8_t *binding_status)
228 {
229 tHAL_UWB_STATUS status;
230 *binding_status = UWB_DEVICE_UNKNOWN;
231
232 // register rx handler for UWB_ESE_BINDING_CHECK_NTF
233 uint8_t binding_status_got = UWB_DEVICE_UNKNOWN;
234 phNxpUciHal_Sem_t binding_check_ntf_wait;
235 phNxpUciHal_init_cb_data(&binding_check_ntf_wait);
236 auto binding_check_ntf_cb = [&](size_t packet_len, const uint8_t *packet) mutable -> bool {
237 if (packet_len >= UCI_RESPONSE_STATUS_OFFSET) {
238 binding_status_got = packet[UCI_RESPONSE_STATUS_OFFSET];
239 NXPLOG_UCIHAL_D("Received UWB_ESE_BINDING_CHECK_NTF, binding_status=0x%x", binding_status_got);
240 SEM_POST(&binding_check_ntf_wait);
241 }
242 return true;
243 };
244 auto handler = phNxpUciHal_rx_handler_add(
245 UCI_MT_NTF, UCI_GID_PROPRIETARY_0X0F, UCI_MSG_UWB_ESE_BINDING_CHECK,
246 true, binding_check_ntf_cb);
247
248 // UWB_ESE_BINDING_CHECK_CMD
249 uint8_t lock_cmd[] = {0x2F, 0x32, 0x00, 0x00};
250 status = phNxpUciHal_send_ext_cmd(sizeof(lock_cmd), lock_cmd);
251 if (status != UWBSTATUS_SUCCESS) {
252 goto exit_check_binding_status;
253 }
254
255 if (phNxpUciHal_sem_timed_wait(&binding_check_ntf_wait) ||
256 binding_check_ntf_wait.status != UWBSTATUS_SUCCESS) {
257 NXPLOG_UCIHAL_E("Failed to retrieve UWB_ESE_BINDING_CHECK_NTF");
258 goto exit_check_binding_status;
259 }
260
261 *binding_status = binding_status_got;
262 status = UWBSTATUS_SUCCESS;
263
264 exit_check_binding_status:
265 phNxpUciHal_rx_handler_del(handler);
266 phNxpUciHal_cleanup_cb_data(&binding_check_ntf_wait);
267 return status;
268 }
269
270 // Group Delay Compensation, if any
271 // SR1XX needs this, because it has
272 // different handling during calibration with D48/D49 vs D50
sr1xx_extra_group_delay(const uint8_t ch)273 static int16_t sr1xx_extra_group_delay(const uint8_t ch)
274 {
275 int16_t required_compensation = 0;
276
277 /* Calibrated with D4X and we are on D5X or later */
278 bool is_calibrated_with_d4x = false;
279
280 std::optional<std::string_view> res = NxpConfig_GetStr("cal.fw_version");
281
282 if (res.has_value()) {
283 std::string_view fw_version = *res;
284 // Conf file has entry of `cal.fw_version`
285 is_calibrated_with_d4x =
286 fw_version.starts_with("48.") || fw_version.starts_with("49.");
287 }
288 else
289 {
290 NXPLOG_UCIHAL_W("Could not get cal.fw_version. Assuming D48 used for calibration.");
291 is_calibrated_with_d4x = true;
292 }
293
294 if (is_calibrated_with_d4x) {
295 if (nxpucihal_ctrl.fw_version.major_version >= 0x50) {
296 required_compensation += (7*4); /*< 7 CM offset required... */
297 }
298 else
299 {
300 /* Running with D49. For testing purpose. +7cm Not needed */
301 }
302
303 // Calibrated with D49
304 // Required extra negative offset, Channel specific, but antenna agnostic.
305 char key[32];
306 std::snprintf(key, sizeof(key), "cal.ch%u.extra_d49_offset_n", ch);
307 uint16_t cal_chx_extra_d49_offset_n = NxpConfig_GetNum<uint16_t>(key).value_or(0);
308 required_compensation -= cal_chx_extra_d49_offset_n;
309 }
310 else
311 {
312 // calibrated with D50 or later.
313 // No compensation.
314 }
315
316 /* Its Q14.2 format, Actual CM impact is //4 */
317 return required_compensation;
318 }
319
320 class NxpUwbChipHbciModule final : public NxpUwbChip {
321 public:
322 NxpUwbChipHbciModule();
323 virtual ~NxpUwbChipHbciModule();
324
325 tHAL_UWB_STATUS chip_init();
326 tHAL_UWB_STATUS core_init();
327 device_type_t get_device_type(const uint8_t *param, size_t param_len);
328 tHAL_UWB_STATUS read_otp(extcal_param_id_t id, uint8_t *data, size_t data_len, size_t *retlen);
329 tHAL_UWB_STATUS apply_calibration(extcal_param_id_t id, const uint8_t ch, const uint8_t *data, size_t data_len);
330 tHAL_UWB_STATUS get_supported_channels(const uint8_t **cal_channels, uint8_t *nr);
331
332 void suspend() override;
333 void resume() override;
334
335 private:
336 tHAL_UWB_STATUS check_binding();
337 bool onDeviceStatusNtf(size_t packet_len, const uint8_t* packet);
338 bool onGenericErrorNtf(size_t packet_len, const uint8_t* packet);
339 bool onBindingStatusNtf(size_t packet_len, const uint8_t* packet);
340
341 private:
342 UciHalRxHandler deviceStatusNtfHandler_;
343 UciHalRxHandler genericErrorNtfHandler_;
344 UciHalRxHandler bindingStatusNtfHandler_;
345 UciHalSemaphore bindingStatusNtfWait_;
346 uint8_t bindingStatus_;
347 };
348
NxpUwbChipHbciModule()349 NxpUwbChipHbciModule::NxpUwbChipHbciModule() :
350 bindingStatus_(UWB_DEVICE_UNKNOWN)
351 {
352 }
353
~NxpUwbChipHbciModule()354 NxpUwbChipHbciModule::~NxpUwbChipHbciModule()
355 {
356 }
357
onDeviceStatusNtf(size_t packet_len,const uint8_t * packet)358 bool NxpUwbChipHbciModule::onDeviceStatusNtf(size_t packet_len, const uint8_t* packet)
359 {
360 if(packet_len > UCI_RESPONSE_STATUS_OFFSET) {
361 uint8_t status = packet[UCI_RESPONSE_STATUS_OFFSET];
362 if (status == UCI_STATUS_HW_RESET) {
363 sr1xx_clear_device_error();
364 }
365 }
366 return false;
367 }
368
onGenericErrorNtf(size_t packet_len,const uint8_t * packet)369 bool NxpUwbChipHbciModule::onGenericErrorNtf(size_t packet_len, const uint8_t* packet)
370 {
371 if(packet_len > UCI_RESPONSE_STATUS_OFFSET) {
372 uint8_t status = packet[UCI_RESPONSE_STATUS_OFFSET];
373 if ( status == UCI_STATUS_THERMAL_RUNAWAY || status == UCI_STATUS_LOW_VBAT) {
374 sr1xx_handle_device_error();
375 return true;
376 }
377 }
378 return false;
379 }
380
onBindingStatusNtf(size_t packet_len,const uint8_t * packet)381 bool NxpUwbChipHbciModule::onBindingStatusNtf(size_t packet_len, const uint8_t* packet)
382 {
383 if (packet_len > UCI_RESPONSE_STATUS_OFFSET) {
384 bindingStatus_ = packet[UCI_RESPONSE_STATUS_OFFSET];
385 NXPLOG_UCIHAL_D("BINDING_STATUS_NTF: 0x%x", bindingStatus_);
386 bindingStatusNtfWait_.post(UWBSTATUS_SUCCESS);
387 }
388 return true;
389 }
390
check_binding()391 tHAL_UWB_STATUS NxpUwbChipHbciModule::check_binding()
392 {
393 // Wait for Binding status notification
394 if (bindingStatusNtfWait_.getStatus() != UWBSTATUS_SUCCESS) {
395 bindingStatusNtfWait_.wait_timeout_msec(3000);
396 }
397 if (bindingStatusNtfWait_.getStatus() != UWBSTATUS_SUCCESS) {
398 NXPLOG_UCIHAL_E("Binding status notification timeout");
399
400 // Stop HAL init when it didn't receive the binding notification.
401 // or if it's not user mode fw, just continue
402 if (nxpucihal_ctrl.fw_boot_mode == USER_FW_BOOT_MODE)
403 return UWBSTATUS_FAILED;
404 else
405 return UWBSTATUS_SUCCESS;
406 }
407
408 bool isBindingLockingAllowed =
409 NxpConfig_GetBool(NAME_UWB_BINDING_LOCKING_ALLOWED).value_or(false);
410 if (!isBindingLockingAllowed) {
411 return UWBSTATUS_SUCCESS;
412 }
413
414 NXPLOG_UCIHAL_E("Current binding status: 0x%x", bindingStatus_);
415
416 switch (bindingStatus_) {
417 case UWB_DEVICE_UNKNOWN:
418 // Treat 'UNKNOWN' state as 'NOT_BOUND'
419 NXPLOG_UCIHAL_E("Unknown binding status, proceed binding.");
420 [[fallthrough]];
421 case UWB_DEVICE_NOT_BOUND:
422 {
423 sr1xx_disable_dpd();
424
425 // perform bind
426 uint8_t remaining_count = 0;
427 tHAL_UWB_STATUS status = sr1xx_do_bind(&bindingStatus_, &remaining_count);
428 if (status != UWBSTATUS_SUCCESS) {
429 return status;
430 }
431
432 // perform lock
433 if (bindingStatus_ == UWB_DEVICE_BOUND_UNLOCKED && remaining_count < 3) {
434 status = sr1xx_check_binding_status(&bindingStatus_);
435 if (status != UWBSTATUS_SUCCESS) {
436 return status;
437 }
438 }
439 }
440 break;
441 case UWB_DEVICE_BOUND_UNLOCKED:
442 {
443 sr1xx_disable_dpd();
444
445 // perform lock
446 tHAL_UWB_STATUS status = sr1xx_check_binding_status(&bindingStatus_);
447 if (status != UWBSTATUS_SUCCESS) {
448 // Sending originial binding status notification to upper layer
449 // XXX: Why?
450 report_binding_status(bindingStatus_);
451 }
452 }
453 break;
454
455 case UWB_DEVICE_BOUND_LOCKED:
456 // do nothing
457 break;
458
459 default:
460 NXPLOG_UCIHAL_E("Unknown binding status: 0x%x", bindingStatus_);
461 return UWBSTATUS_FAILED;
462 }
463
464 return UWBSTATUS_SUCCESS;
465 }
466
467 extern int phNxpUciHal_fw_download();
468
chip_init()469 tHAL_UWB_STATUS NxpUwbChipHbciModule::chip_init()
470 {
471 tHAL_UWB_STATUS status;
472
473 // system in FW download mode
474 // This will be cleared on first Device Status NTF
475 nxpucihal_ctrl.fw_dwnld_mode = true;
476
477 NXPLOG_UCIHAL_D("Start SR1XX FW download");
478
479 for (int i = 0; i < 5; i++) {
480 phTmlUwb_Chip_Reset();
481
482 status = phNxpUciHal_fw_download();
483
484 if (status == UWBSTATUS_SUCCESS) {
485 NXPLOG_UCIHAL_D("Complete SR1XX FW download");
486 break;
487 } else if(status == UWBSTATUS_FILE_NOT_FOUND) {
488 NXPLOG_UCIHAL_E("FW file Not found.");
489 break;
490 } else {
491 NXPLOG_UCIHAL_E("FW download failed, status= 0x%x, retry.", status);
492 }
493 }
494
495 // register device status ntf handler
496 deviceStatusNtfHandler_ = UciHalRxHandler(
497 UCI_MT_NTF, UCI_GID_CORE, UCI_MSG_CORE_DEVICE_STATUS_NTF,
498 std::bind(&NxpUwbChipHbciModule::onDeviceStatusNtf, this, std::placeholders::_1, std::placeholders::_2)
499 );
500
501 // register device error ntf handler
502 genericErrorNtfHandler_ = UciHalRxHandler(
503 UCI_MT_NTF, UCI_GID_CORE, UCI_MSG_CORE_GENERIC_ERROR_NTF,
504 std::bind(&NxpUwbChipHbciModule::onGenericErrorNtf, this, std::placeholders::_1, std::placeholders::_2)
505 );
506
507 // register binding status ntf handler
508 bindingStatusNtfHandler_ = UciHalRxHandler(
509 UCI_MT_NTF, UCI_GID_PROPRIETARY, UCI_MSG_BINDING_STATUS_NTF,
510 std::bind(&NxpUwbChipHbciModule::onBindingStatusNtf, this, std::placeholders::_1, std::placeholders::_2)
511 );
512
513 return status;
514 }
515
core_init()516 tHAL_UWB_STATUS NxpUwbChipHbciModule::core_init()
517 {
518 return check_binding();
519 }
520
get_device_type(const uint8_t * param,size_t param_len)521 device_type_t NxpUwbChipHbciModule::get_device_type(const uint8_t *param, size_t param_len)
522 {
523 // 'SR100S' or 'SR1..T'
524 if (param_len >= 6) {
525 const uint8_t marker = param[5];
526 if (marker == 'S')
527 return DEVICE_TYPE_SR1xxS;
528 else if (marker == 'T')
529 return DEVICE_TYPE_SR1xxT;
530 }
531 return DEVICE_TYPE_UNKNOWN;
532 }
533
read_otp(extcal_param_id_t id,uint8_t * data,size_t data_len,size_t * retlen)534 tHAL_UWB_STATUS NxpUwbChipHbciModule::read_otp(extcal_param_id_t id, uint8_t *data, size_t data_len, size_t *retlen)
535 {
536 return sr1xx_read_otp(id, data, data_len, retlen);
537 }
538
sr1xx_apply_calibration_ant_delay(extcal_param_id_t id,const uint8_t ch,const uint8_t * data,size_t data_len)539 tHAL_UWB_STATUS sr1xx_apply_calibration_ant_delay(extcal_param_id_t id, const uint8_t ch, const uint8_t *data, size_t data_len) {
540
541 std::vector<uint8_t> patched_data;
542 std::copy(&data[0], &data[data_len], std::back_inserter(patched_data));
543
544 const int16_t delay_compensation = sr1xx_extra_group_delay(ch);
545 const uint8_t nr_entries = patched_data[0];
546 for (uint8_t i = 0; i < nr_entries; i++) {
547 // Android ABI & UCI both are Little endian
548 int32_t rx_delay32 = patched_data[2 + i * 3] | (patched_data[3 + i * 3] << 8);
549 if ( 0 != delay_compensation ) {
550 NXPLOG_UCIHAL_D("RX_ANT_DELAY_CALIB: Extra compensation '%d'", delay_compensation);
551 rx_delay32 += delay_compensation;
552 }
553
554 // clamp to 0 ~ 0xffff
555 if (rx_delay32 >= 0xFFFF) {
556 rx_delay32 = 0xFFFF;
557 } else if (rx_delay32 < 0) {
558 rx_delay32 = 0;
559 }
560
561 const uint16_t rx_delay = rx_delay32;
562 patched_data[2 + i * 3] = rx_delay & 0xff;
563 patched_data[3 + i * 3] = rx_delay >> 8;
564 }
565 return sr1xx_apply_calibration(id, ch, patched_data.data(), data_len);
566 }
567
apply_calibration(extcal_param_id_t id,const uint8_t ch,const uint8_t * data,size_t data_len)568 tHAL_UWB_STATUS NxpUwbChipHbciModule::apply_calibration(extcal_param_id_t id, const uint8_t ch, const uint8_t *data, size_t data_len)
569 {
570 if (id == EXTCAL_PARAM_RX_ANT_DELAY) {
571 return sr1xx_apply_calibration_ant_delay(id, ch, data, data_len);
572 }
573 else
574 {
575 return sr1xx_apply_calibration(id, ch, data, data_len);
576 }
577 }
578
579 tHAL_UWB_STATUS
get_supported_channels(const uint8_t ** cal_channels,uint8_t * nr)580 NxpUwbChipHbciModule::get_supported_channels(const uint8_t **cal_channels, uint8_t *nr)
581 {
582 static const uint8_t sr100_cal_channels[] = {5, 6, 8, 9};
583 *cal_channels = sr100_cal_channels;
584 *nr = std::size(sr100_cal_channels);
585 return UWBSTATUS_SUCCESS;
586 }
587
suspend()588 void NxpUwbChipHbciModule::suspend()
589 {
590 phTmlUwb_Suspend();
591 }
592
resume()593 void NxpUwbChipHbciModule::resume()
594 {
595 phTmlUwb_Resume();
596 }
597
GetUwbChip()598 std::unique_ptr<NxpUwbChip> GetUwbChip()
599 {
600 return std::make_unique<NxpUwbChipHbciModule>();
601 }
602