1 /*
2 * Copyright 2021-2023 NXP
3 * Copyright 2024 Google
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
19 #include "phNxpUwbCalib.h"
20 #include "phUwbStatus.h"
21 #include "phNxpUciHal_ext.h"
22
23 /* SR1XX is same as SR2XX */
24 static tHAL_UWB_STATUS sr1xx_apply_calibration(extcal_param_id_t id, const uint8_t ch, const uint8_t *data, size_t data_len);
25 static tHAL_UWB_STATUS sr1xx_set_conf(const std::vector<uint8_t> &tlv);
26 static tHAL_UWB_STATUS sr1xx_set_calibration(uint8_t channel, const std::vector<uint8_t> &tlv);
27
28
phNxpUwbCalib_apply_calibration(extcal_param_id_t id,const uint8_t ch,const uint8_t * data,size_t data_len)29 tHAL_UWB_STATUS phNxpUwbCalib_apply_calibration(extcal_param_id_t id, const uint8_t ch, const uint8_t *data, size_t data_len) {
30 return sr1xx_apply_calibration(id, ch, data, data_len);
31 }
32
33 //
34 // SR1XX Device Calibrations:
35 //
36 // Based on NXP SR1xx UCI v2.0.5
37 // current HAL impl only supports "xtal" read from otp
38 // others should be existed in .conf files
39
sr1xx_set_calibration(uint8_t channel,const std::vector<uint8_t> & tlv)40 static tHAL_UWB_STATUS sr1xx_set_calibration(uint8_t channel, const std::vector<uint8_t> &tlv)
41 {
42 // SET_CALIBRATION_CMD header: GID=0xF OID=0x21
43 std::vector<uint8_t> packet({ (0x20 | UCI_GID_PROPRIETARY_0X0F), UCI_MSG_SET_DEVICE_CALIBRATION, 0x00, 0x00});
44
45 // use 9 for channel-independent parameters
46 if (!channel) {
47 channel = 9;
48 }
49 packet.push_back(channel);
50 packet.insert(packet.end(), tlv.begin(), tlv.end());
51 packet[3] = packet.size() - 4;
52 return phNxpUciHal_send_ext_cmd(packet.size(), packet.data());
53 }
54
sr1xx_set_conf(const std::vector<uint8_t> & tlv)55 static tHAL_UWB_STATUS sr1xx_set_conf(const std::vector<uint8_t> &tlv)
56 {
57 // SET_CALIBRATION_CMD header: GID=0xF OID=0x21
58 std::vector<uint8_t> packet({ (0x20 | UCI_GID_CORE), UCI_MSG_CORE_SET_CONFIG, 0x00, 0x00});
59 packet.push_back(1); // number of parameters
60 packet.insert(packet.end(), tlv.begin(), tlv.end());
61 packet[3] = packet.size() - 4;
62 return phNxpUciHal_send_ext_cmd(packet.size(), packet.data());
63 }
64
sr1xx_apply_calibration(extcal_param_id_t id,const uint8_t ch,const uint8_t * data,size_t data_len)65 static tHAL_UWB_STATUS sr1xx_apply_calibration(extcal_param_id_t id, const uint8_t ch, const uint8_t *data, size_t data_len)
66 {
67 // Device Calibration
68 const uint8_t UCI_PARAM_ID_RF_CLK_ACCURACY_CALIB = 0x01;
69 const uint8_t UCI_PARAM_ID_RX_ANT_DELAY_CALIB = 0x02;
70 const uint8_t UCI_PARAM_ID_TX_POWER_PER_ANTENNA = 0x04;
71
72 // Device Configurations
73 const uint16_t UCI_PARAM_ID_TX_BASE_BAND_CONFIG = 0xe426;
74 const uint16_t UCI_PARAM_ID_DDFS_TONE_CONFIG = 0xe427;
75 const uint16_t UCI_PARAM_ID_TX_PULSE_SHAPE_CONFIG = 0xe428;
76
77 switch (id) {
78 case EXTCAL_PARAM_CLK_ACCURACY:
79 {
80 if (data_len != 6) {
81 return UWBSTATUS_FAILED;
82 }
83
84 std::vector<uint8_t> tlv;
85 // Tag
86 tlv.push_back(UCI_PARAM_ID_RF_CLK_ACCURACY_CALIB);
87 // Length
88 tlv.push_back((uint8_t)data_len + 1);
89 // Value
90 tlv.push_back(3); // number of register (must be 0x03)
91 tlv.insert(tlv.end(), data, data + data_len);
92
93 return sr1xx_set_calibration(ch, tlv);
94 }
95 case EXTCAL_PARAM_RX_ANT_DELAY:
96 {
97 if (!ch || data_len < 1 || !data[0] || (data[0] * 3) != (data_len - 1)) {
98 return UWBSTATUS_FAILED;
99 }
100
101 std::vector<uint8_t> tlv;
102 // Tag
103 tlv.push_back(UCI_PARAM_ID_RX_ANT_DELAY_CALIB);
104 // Length
105 tlv.push_back((uint8_t)data_len);
106 // Value
107 tlv.insert(tlv.end(), data, data + data_len);
108
109 return sr1xx_set_calibration(ch, tlv);
110 }
111 case EXTCAL_PARAM_TX_POWER:
112 {
113 if (!ch || data_len < 1 || !data[0] || (data[0] * 5) != (data_len - 1)) {
114 return UWBSTATUS_FAILED;
115 }
116
117 std::vector<uint8_t> tlv;
118 // Tag
119 tlv.push_back(UCI_PARAM_ID_TX_POWER_PER_ANTENNA);
120 // Length
121 tlv.push_back((uint8_t)data_len);
122 // Value
123 tlv.insert(tlv.end(), data, data + data_len);
124
125 return sr1xx_set_calibration(ch, tlv);
126 }
127 case EXTCAL_PARAM_TX_BASE_BAND_CONTROL:
128 {
129 if (data_len != 1) {
130 return UWBSTATUS_FAILED;
131 }
132
133 std::vector<uint8_t> tlv;
134 // Tag
135 tlv.push_back(UCI_PARAM_ID_TX_BASE_BAND_CONFIG >> 8);
136 tlv.push_back(UCI_PARAM_ID_TX_BASE_BAND_CONFIG & 0xff);
137 // Length
138 tlv.push_back(1);
139 // Value
140 tlv.push_back(data[0]);
141
142 return sr1xx_set_conf(tlv);
143 }
144 case EXTCAL_PARAM_DDFS_TONE_CONFIG:
145 {
146 if (!data_len) {
147 return UWBSTATUS_FAILED;
148 }
149
150 std::vector<uint8_t> tlv;
151 // Tag
152 tlv.push_back(UCI_PARAM_ID_DDFS_TONE_CONFIG >> 8);
153 tlv.push_back(UCI_PARAM_ID_DDFS_TONE_CONFIG & 0xff);
154 // Length
155 tlv.push_back(data_len);
156 // Value
157 tlv.insert(tlv.end(), data, data + data_len);
158
159 return sr1xx_set_conf(tlv);
160 }
161 case EXTCAL_PARAM_TX_PULSE_SHAPE:
162 {
163 if (!data_len) {
164 return UWBSTATUS_FAILED;
165 }
166
167 std::vector<uint8_t> tlv;
168 // Tag
169 tlv.push_back(UCI_PARAM_ID_TX_PULSE_SHAPE_CONFIG >> 8);
170 tlv.push_back(UCI_PARAM_ID_TX_PULSE_SHAPE_CONFIG & 0xff);
171 // Length
172 tlv.push_back(data_len);
173 // Value
174 tlv.insert(tlv.end(), data, data + data_len);
175
176 return sr1xx_set_conf(tlv);
177 }
178 default:
179 NXPLOG_UCIHAL_E("Unsupported parameter: 0x%x", id);
180 return UWBSTATUS_FAILED;
181 }
182 }
183