1 /**
2 *\file mykonos.c
3 *
4 *\brief Contains Mykonos APIs for transceiver configuration and control
5 *
6 * Mykonos API version: 1.5.1.3565
7 */
8
9 /**
10 * \mainpage Overview
11 *
12 * This document is intended for use by software engineering professionals and
13 * includes detailed information regarding the data types and function calls
14 * which comprise the Mykonos ANSI C API.
15 * References to "Mykonos" in the API refer to the Analog Devices development name for the AD9371 family of devices.
16 *
17 */
18
19 /**
20 * \page Use Suggested Use
21 * The purpose of this API library is to add abstraction for the low level
22 * SPI control and calculations necessary to control the Mykonos family of transceiver devices
23 *
24 * Add the included source code as required to your baseband processor software build. Please reference the integration document
25 * as well for further instructions.
26 */
27
28 /**
29 * \page Disclaimer Legal Disclaimer
30 * Copyright 2015-2017 Analog Devices Inc.
31 * Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file.
32 *
33 */
34
35 #include <stdint.h>
36 #include <stddef.h>
37 #include "common.h"
38 #include "mykonos.h"
39 #include "mykonos_gpio.h"
40 #include "mykonos_macros.h"
41 #include "mykonos_user.h"
42
43 /* Private helper functions local to this file */
44 static mykonosErr_t MYKONOS_calculateScaledDeviceClk_kHz(mykonosDevice_t *device, uint32_t *scaledRefClk_kHz, uint8_t *deviceClkDiv);
45 static mykonosErr_t MYKONOS_calculateDigitalClocks(mykonosDevice_t *device, uint32_t *hsDigClk_kHz, uint32_t *hsDigClkDiv4or5_kHz);
46 static mykonosErr_t enableDpdTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable);
47 static mykonosErr_t enableClgcTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable);
48
49 /**
50 * \brief Verifies the Tx profile members are valid (in range) in the init structure
51 *
52 * If the Tx profile IQ data rate = 0, it is assumed that the Tx profile is
53 * not used. If Tx IQ data rate > 0, and Tx profile members are out of range,
54 *
55 * \pre This function is private and is not called directly by the user.
56 *
57 * <B>Dependencies</B>
58 * - device->tx->txProfile
59 *
60 * \param device Structure pointer to Mykonos device data structure
61 * \param txProfile txProfile settings to be verified
62 * \param txHsDigClk_kHz Return value of the calculated HS Dig Clock required by the Tx profile
63 *
64 * \retval MYKONOS_ERR_TXPROFILE_IQRATE Profile IQ rate out of range
65 * \retval MYKONOS_ERR_TXPROFILE_RFBW Tx Profile RF bandwidth out of range
66 * \retval MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION Filter interpolation not valid
67 * \retval MYKONOS_ERR_TXPROFILE_FIR_INT FIR filter not valid
68 * \retval MYKONOS_ERR_OK All profile members are valid
69 */
mykVerifyTxProfile(mykonosDevice_t * device,mykonosTxProfile_t * txProfile,uint32_t * txHsDigClk_kHz)70 static mykonosErr_t mykVerifyTxProfile(mykonosDevice_t *device, mykonosTxProfile_t *txProfile, uint32_t *txHsDigClk_kHz)
71 {
72 mykonosErr_t retVal = MYKONOS_ERR_OK;
73
74 *txHsDigClk_kHz = 0;
75
76 /********************************/
77 /* Check for a valid Tx profile */
78 /********************************/
79
80 if ((txProfile->iqRate_kHz < MIN_TX_IQRATE_KHZ) || (txProfile->iqRate_kHz > MAX_TX_IQRATE_KHZ))
81 {
82 return MYKONOS_ERR_TXPROFILE_IQRATE;
83 }
84
85 if ((txProfile->rfBandwidth_Hz < MIN_TX_RFBW_HZ) || (txProfile->rfBandwidth_Hz > MAX_TX_RFBW_HZ))
86 {
87 return MYKONOS_ERR_TXPROFILE_RFBW;
88 }
89
90 if ((txProfile->thb1Interpolation != 1) && (txProfile->thb1Interpolation != 2))
91 {
92 return MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION;
93 }
94
95 if ((txProfile->thb2Interpolation != 1) && (txProfile->thb2Interpolation != 2))
96 {
97 return MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION;
98 }
99
100 if ((txProfile->txFirInterpolation != 1) && (txProfile->txFirInterpolation != 2) && (txProfile->txFirInterpolation != 4))
101 {
102 return MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION;
103 }
104
105 if ((txProfile->txFir->coefs == NULL) && (txProfile->txFirInterpolation != 1))
106 {
107 return MYKONOS_ERR_TXPROFILE_FIR_COEFS;
108 }
109
110 if ((txProfile->dacDiv != DACDIV_2) && (txProfile->dacDiv != DACDIV_2p5) && (txProfile->dacDiv != DACDIV_4))
111 {
112 return MYKONOS_ERR_TXPROFILE_DACDIV;
113 }
114
115 *txHsDigClk_kHz = (txProfile->iqRate_kHz * txProfile->txFirInterpolation * txProfile->thb1Interpolation * txProfile->thb2Interpolation * (uint32_t)txProfile->dacDiv);
116
117 device->profilesValid |= TX_PROFILE_VALID;
118
119 return retVal;
120 }
121
122 /**
123 * \brief Verifies the Rx profile members are valid (in range) and calculates HS Dig Clock require for the Rx Profile
124 *
125 * Private helper function to verify the Rx profile members are valid (in range)
126 * and calculates HS Dig Clock require for the Rx Profile
127 * If the Rx profile IQ data rate = 0, it is assumed that the Rx profile is
128 * not used. If Rx IQ data rate > 0, and Rx profile members are out of range.
129 *
130 * \pre This function is private and is not called directly by the user.
131 *
132 * <B>Dependencies</B>
133 * - device->rx->rxProfile
134 *
135 * \param device Structure pointer to Talise device data structure
136 * \param rxChannel receiver channel to be checked
137 * \param rxProfile rxProfile settings to be verified
138 * \param rxHsDigClk_kHz Return value of the calculated HS Dig Clock required by the Rx profile
139 *
140 * \retval MYKONOS_ERR_RXPROFILE_RXCHANNEL Rx channel is not valid.
141 * \retval MYKONOS_ERR_RXPROFILE_IQRATE out of range IQ rate
142 * \retval MYKONOS_ERR_RXPROFILE_RFBW out of range RF bandwidth
143 * \retval MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION not valid filter decimation setting
144 * \retval MYKONOS_ERR_RXPROFILE_FIR_COEFS FIR filter not valid
145 * \retval MYKONOS_ERR_RXPROFILE_ADCDIV not valid ADC divider
146 * \retval MYKONOS_ERR_OK all profile members are valid
147 */
mykVerifyRxProfile(mykonosDevice_t * device,mykonosRxProfType_t rxChannel,mykonosRxProfile_t * rxProfile,uint32_t * rxHsDigClk_kHz)148 static mykonosErr_t mykVerifyRxProfile(mykonosDevice_t *device, mykonosRxProfType_t rxChannel, mykonosRxProfile_t *rxProfile, uint32_t *rxHsDigClk_kHz)
149 {
150 mykonosErr_t retVal = MYKONOS_ERR_OK;
151 uint32_t minBwHz = 0;
152 uint32_t maxBwHz = 0;
153
154 *rxHsDigClk_kHz = 0;
155
156 switch (rxChannel)
157 {
158 case MYK_RX_PROFILE:
159 minBwHz = MIN_RX_RFBW_HZ;
160 maxBwHz = MAX_RX_RFBW_HZ;
161 break;
162 case MYK_OBS_PROFILE:
163 minBwHz = MIN_ORX_RFBW_HZ;
164 maxBwHz = MAX_ORX_RFBW_HZ;
165 break;
166 case MYK_SNIFFER_PROFILE:
167 minBwHz = MIN_SNIFFER_RFBW_HZ;
168 maxBwHz = MAX_SNIFFER_RFBW_HZ;
169 break;
170
171 default:
172 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXPROFILE_RXCHANNEL,
173 getMykonosErrorMessage(MYKONOS_ERR_RXPROFILE_RXCHANNEL));
174 return MYKONOS_ERR_RXPROFILE_RXCHANNEL;
175 }
176
177 /********************************/
178 /* Check for a valid Rx profile */
179 /********************************/
180 if ((rxProfile->iqRate_kHz < MIN_RX_IQRATE_KHZ) || (rxProfile->iqRate_kHz > MAX_RX_IQRATE_KHZ))
181 {
182 return MYKONOS_ERR_RXPROFILE_IQRATE;
183 }
184
185 /* check for Rx/Obs or Sniffer BW */
186 if ((rxProfile->rfBandwidth_Hz < minBwHz) || (rxProfile->rfBandwidth_Hz > maxBwHz))
187 {
188 return MYKONOS_ERR_RXPROFILE_RFBW;
189 }
190
191 if ((rxProfile->rhb1Decimation != 1) && (rxProfile->rhb1Decimation != 2))
192 {
193 return MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION;
194 }
195
196 if ((rxProfile->rxDec5Decimation != 4) && (rxProfile->rxDec5Decimation != 5))
197 {
198 return MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION;
199 }
200
201 if ((rxProfile->rxFirDecimation != 1) && (rxProfile->rxFirDecimation != 2) && (rxProfile->rxFirDecimation != 4))
202 {
203 return MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION;
204 }
205
206 if ((rxProfile->rxFir->coefs == NULL) && (rxProfile->rxFirDecimation != 1))
207 {
208 return MYKONOS_ERR_RXPROFILE_FIR_COEFS;
209 }
210
211 if ((rxProfile->adcDiv != 1) && (rxProfile->adcDiv != 2))
212 {
213 return MYKONOS_ERR_RXPROFILE_ADCDIV;
214 }
215
216 *rxHsDigClk_kHz = (rxProfile->iqRate_kHz * rxProfile->rxFirDecimation * rxProfile->rhb1Decimation * rxProfile->rxDec5Decimation * rxProfile->adcDiv);
217
218 switch (rxChannel)
219 {
220 case MYK_RX_PROFILE:
221 device->profilesValid |= RX_PROFILE_VALID;
222 break;
223 case MYK_OBS_PROFILE:
224 device->profilesValid |= ORX_PROFILE_VALID;
225 break;
226 /*case MYK_SNIFFER_PROFILE:*/
227 default:
228 device->profilesValid |= SNIFF_PROFILE_VALID;
229 break;
230 }
231
232 return retVal;
233 }
234
235 /**
236 * \brief Performs a hard reset on the MYKONOS DUT (Toggles RESETB pin on device)
237 *
238 * Toggles the Mykonos devices RESETB pin. Only resets the device with
239 * the SPI chip select indicated in the device->spiSettings structure.
240 *
241 * <B>Dependencies</B>
242 * - device->spiSettings->chipSelectIndex
243 *
244 * \param device Pointer to Mykonos device data structure containing settings
245 *
246 * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
247 */
MYKONOS_resetDevice(mykonosDevice_t * device)248 mykonosErr_t MYKONOS_resetDevice(mykonosDevice_t *device)
249 {
250
251 #if (MYKONOS_VERBOSE == 1)
252 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetDevice()\n");
253 #endif
254
255 /* toggle RESETB on device with matching spi chip select index */
256 CMB_hardReset(device->spiSettings->chipSelectIndex);
257 return MYKONOS_ERR_OK;
258 }
259
260 /**
261 * \brief Reads back the silicon revision for the Mykonos Device
262 *
263 * <B>Dependencies</B>
264 * - device->spiSettings->chipSelectIndex
265 *
266 * \param device Pointer to Mykonos device data structure containing settings
267 * \param revision Return value of the Mykonos silicon revision
268 *
269 * \retval MYKONOS_ERR_OK Function completed successfully
270 */
MYKONOS_getDeviceRev(mykonosDevice_t * device,uint8_t * revision)271 mykonosErr_t MYKONOS_getDeviceRev(mykonosDevice_t *device, uint8_t *revision)
272 {
273 #if (MYKONOS_VERBOSE == 1)
274 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDeviceRev()\n");
275 #endif
276
277 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_PRODUCT_ID, revision, 0x07, 0);
278
279 return MYKONOS_ERR_OK;
280 }
281
282 /**
283 * \brief Reads back the Product ID for the Mykonos Device
284 *
285 * <B>Dependencies</B>
286 * - device->spiSettings->chipSelectIndex
287 *
288 * \param device Pointer to Mykonos device data structure containing settings
289 * \param productId Return value of the Mykonos product Id
290 *
291 * \retval MYKONOS_ERR_GETPRODUCTID__NULL_PARAM recovery action for bad parameter check
292 * \retval MYKONOS_ERR_OK Function completed successfully
293 */
MYKONOS_getProductId(mykonosDevice_t * device,uint8_t * productId)294 mykonosErr_t MYKONOS_getProductId(mykonosDevice_t *device, uint8_t *productId)
295 {
296 mykonosErr_t retVal = MYKONOS_ERR_OK;
297
298 #if (MYKONOS_VERBOSE == 1)
299 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getProductId()\n");
300 #endif
301
302 if (productId == NULL)
303 {
304 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETPRODUCTID_NULL_PARAM,
305 getMykonosErrorMessage(MYKONOS_ERR_GETPRODUCTID_NULL_PARAM));
306 return MYKONOS_ERR_GETPRODUCTID_NULL_PARAM;
307 }
308
309 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_PRODUCT_ID, productId, 0xF8, 3);
310
311 return retVal;
312 }
313
314 /**
315 * \brief Get API version number
316 *
317 * This function reads back the version number of the API
318 *
319 * \param device Pointer to the Mykonos data structure
320 * \param siVer A pointer to the current silicon version number.
321 * \param majorVer A pointer to the current major version number.
322 * \param minorVer A pointer to the current minor version number.
323 * \param buildVer A pointer to the current build version number.
324 *
325 * \retval MYKONOS_ERR_GET_API_VERSION_NULL_PARAM Null parameter passed to the function.
326 * \retval MYKONOS_ERR_OK Function completed successfully
327 */
MYKONOS_getApiVersion(mykonosDevice_t * device,uint32_t * siVer,uint32_t * majorVer,uint32_t * minorVer,uint32_t * buildVer)328 mykonosErr_t MYKONOS_getApiVersion(mykonosDevice_t *device, uint32_t *siVer, uint32_t *majorVer, uint32_t *minorVer, uint32_t *buildVer)
329 {
330 mykonosErr_t retVal = MYKONOS_ERR_OK;
331
332 #if (MYKONOS_VERBOSE == 1)
333 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getApiVersion()\n");
334 #endif
335
336 if ((siVer == NULL) || (majorVer == NULL) || (minorVer == NULL) || (buildVer == NULL))
337 {
338 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_API_VERSION_NULL_PARAM,
339 getMykonosErrorMessage(MYKONOS_ERR_GET_API_VERSION_NULL_PARAM));
340 return MYKONOS_ERR_GET_API_VERSION_NULL_PARAM;
341 }
342
343 *siVer = (uint32_t)MYKONOS_CURRENT_SI_VERSION;
344 *majorVer = (uint32_t)MYKONOS_CURRENT_MAJOR_VERSION;
345 *minorVer = (uint32_t)MYKONOS_CURRENT_MINOR_VERSION;
346 *buildVer = (uint32_t)MYKONOS_CURRENT_BUILD_VERSION;
347 return retVal;
348 }
349
350 /**
351 * \brief Sets the Mykonos device SPI settings (3wire/4wire, MSBFirst, etc).
352 *
353 * This function will use the settings in the device->spiSettings structure
354 * to set SPI stream mode, address auto increment direction, MSBFirst/LSBfirst,
355 * and 3wire/4wire mode. The Mykonos device always uses SPI MODE 0 (CPHA=0, CPOL=0).
356 * This function will update your device->spiSettings to set CHPA=0 and CPOL=0 and
357 * longInstructionWord =1 to use a 16bit instruction word.
358 *
359 * <B>Dependencies</B>
360 * - writes device->spiSettings->CPHA = 0
361 * - writes device->spiSettings->CPOL = 0
362 * - writes device->spiSettings->longInstructionWord = 1
363 *
364 * - device->spiSettings->MSBFirst
365 * - device->spiSettings->enSpiStreaming
366 * - device->spiSettings->autoIncAddrUp
367 * - device->spiSettings->fourWireMode
368 *
369 * \param device Pointer to Mykonos device data structure containing settings
370 *
371 * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
372 */
MYKONOS_setSpiSettings(mykonosDevice_t * device)373 mykonosErr_t MYKONOS_setSpiSettings(mykonosDevice_t *device)
374 {
375 //device->spiSettings->enSpiStreaming
376 uint8_t spiReg = 0;
377
378 #if (MYKONOS_VERBOSE == 1)
379 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setSpiSettings()\n");
380 #endif
381
382 device->spiSettings->CPHA = 0;
383 device->spiSettings->CPOL = 0;
384 device->spiSettings->longInstructionWord = 1;
385
386 if (device->spiSettings->MSBFirst == 0)
387 {
388 spiReg |= 0x42; /* SPI bit is 1=LSB first */
389 }
390
391 if (device->spiSettings->autoIncAddrUp > 0)
392 {
393 spiReg |= 0x24;
394 }
395
396 if (device->spiSettings->fourWireMode > 0)
397 {
398 spiReg |= 0x18;
399 }
400
401 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_0, spiReg);
402
403 if (device->spiSettings->enSpiStreaming > 0)
404 {
405 /* Allow SPI streaming mode: SPI message ends when chip select deasserts */
406 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SPI_CONFIGURATION_CONTROL_1, 0x00);
407 }
408 else
409 {
410 /* Force single instruction mode */
411 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SPI_CONFIGURATION_CONTROL_1, 0x80);
412 }
413
414 return MYKONOS_ERR_OK;
415 }
416
417 /**
418 * \brief Verifies the integrity of the Mykonos device data structure.
419 *
420 * The Mykonos device data structure has many pointers to other structures. The
421 * main purpose of this function to verify that the necessary pointers within the
422 * device data structure have non zero pointers. The focus is on the Rx/Tx/ObsRx
423 * profiles and FIR filters where if a channel is disabled, it may be valid for
424 * some pointers to be NULL. This function updates device->profileValid to remember
425 * which profile pointers are valid.
426 * profileValid[3:0] = {SnifferProfileValid, ObsRxProfileValid, RxProfileValid, TxProfileValid};
427 *
428 * <B>Dependencies</B>
429 * - device (all variables)
430 *
431 * \param device Pointer to Mykonos device data structure containing settings
432 *
433 * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
434 */
MYKONOS_verifyDeviceDataStructure(mykonosDevice_t * device)435 mykonosErr_t MYKONOS_verifyDeviceDataStructure(mykonosDevice_t *device)
436 {
437 if (device == NULL)
438 {
439 CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER));
440 return MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER;
441 }
442
443 device->profilesValid = 0; /* Reset */
444
445 if (device->spiSettings == NULL)
446 {
447 CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_CHECKDEVSTRUCT_SPI, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_SPI));
448 return MYKONOS_ERR_CHECKDEVSTRUCT_SPI;
449 }
450
451 /* place this writeToLog after verifying the spiSettings structure is not NULL */
452 #if (MYKONOS_VERBOSE == 1)
453 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_verifyDeviceDataStructure()\n");
454 #endif
455
456 /**************************************************************************
457 * Check Rx stucture pointers
458 **************************************************************************
459 */
460 if (device->rx == NULL)
461 {
462 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_RX, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_RX));
463 return MYKONOS_ERR_CHECKDEVSTRUCT_RX;
464 }
465 else
466 {
467 if (device->rx->rxChannels == RXOFF)
468 {/* If no Rx channel enabled, ok to have null pointers for rx gain control, framer, and Rx profile/Rx FIR Filter */
469 }
470 else
471 {
472 if ((device->rx->framer == NULL) || (device->rx->rxGainCtrl == NULL) || (device->rx->rxProfile == NULL))
473 {
474 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB,
475 getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB));
476 return MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB;
477 }
478
479 if ((device->rx->rxProfile->rxFir == NULL) && (device->rx->rxProfile->rxFirDecimation != 1))
480 {
481 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR,
482 getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR));
483 return MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR;
484 }
485 }
486 }
487
488 /**************************************************************************
489 * Check Tx stucture pointers
490 **************************************************************************
491 */
492 if (device->tx == NULL)
493 {
494 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_TX, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_TX));
495 return MYKONOS_ERR_CHECKDEVSTRUCT_TX;
496 }
497 else
498 {
499 if (device->tx->txChannels == TXOFF)
500 {/* If no Tx channel enabled, ok to have null pointers for deframer, and Tx profile/Tx FIR filter */
501 }
502 else
503 {
504 if ((device->tx->deframer == NULL) || (device->tx->txProfile == NULL))
505 {
506 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB,
507 getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB));
508 return MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB;
509 }
510
511 if ((device->tx->txProfile->txFir == NULL) && (device->tx->txProfile->txFirInterpolation != 1))
512 {
513 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR,
514 getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR));
515 return MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR;
516 }
517 }
518 }
519
520 /**************************************************************************
521 * Check ObsRx stucture pointers
522 **************************************************************************
523 */
524 if (device->obsRx == NULL)
525 {
526 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX,
527 getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX));
528 return MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX;
529 }
530 else
531 {
532 if (device->obsRx->obsRxChannelsEnable == MYK_OBS_RXOFF)
533 {/* If no ObsRx channel enabled, ok to have null pointers for ObsRx gain control, framer, and ObsRx profile/FIR Filter */
534 }
535 else
536 {
537 if ((device->obsRx->framer == NULL))
538 {
539 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER,
540 getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER));
541 return MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER;
542 }
543
544 if (device->obsRx->snifferProfile != NULL)
545 {
546 if (device->obsRx->snifferGainCtrl == NULL)
547 {
548 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL,
549 getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL));
550 return MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL;
551 }
552
553 if ((device->obsRx->snifferProfile->rxFir == NULL) && (device->obsRx->snifferProfile->rxFirDecimation != 1))
554 {
555 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR,
556 getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR));
557 return MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR;
558 }
559 }
560
561 if (device->obsRx->orxProfile != NULL)
562 {
563 if (device->obsRx->orxGainCtrl == NULL)
564 {
565 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL,
566 getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL));
567 return MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL;
568 }
569
570 if ((device->obsRx->orxProfile->rxFir == NULL) && (device->obsRx->orxProfile->rxFirDecimation != 1))
571 {
572 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR,
573 getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR));
574 return MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR;
575 }
576 }
577 }
578 }
579
580 return MYKONOS_ERR_OK;
581 }
582
583 /**
584 * \brief Initializes the Mykonos device based on the desired device settings.
585 *
586 * This function initializes the mykonos device, setting up the CLKPLL, digital clocks,
587 * JESD204b settings, FIR Filters, digital filtering. It does not load the ARM
588 * or perform any of the ARM init calibrations. It also sets the Rx Manual gain indexes and
589 * TxAttenuation settings to the initial values found in the device data structure. It leaves the
590 * Mykonos in a state ready for multichip sync (which can bring up the JESD204 links), the
591 * ARM to be loaded, and the init calibartions run.
592 *
593 * <B>Dependencies</B>
594 * - device (all variables)
595 *
596 * \param device Pointer to Mykonos device data structure containing settings
597 *
598 * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
599 */
MYKONOS_initialize(mykonosDevice_t * device)600 mykonosErr_t MYKONOS_initialize(mykonosDevice_t *device)
601 {
602 uint8_t txChannelSettings = 0;
603 uint8_t rxChannelSettings = 0;
604 uint8_t orxChannelSettings = 0;
605 uint8_t sniffChannelSettings = 0;
606 uint8_t adcDacClockRateSelect = 0;
607 uint8_t enableDpd = 0;
608 uint8_t obsRxRealIf = 0;
609 uint8_t enRxHighRejDec5 = 0;
610 uint8_t rxRealIfData = 0;
611 uint8_t txSyncb = 0x00;
612 uint8_t rxSyncb = 0x00;
613 uint8_t orxSyncb = 0x00;
614 mykonosErr_t retVal = MYKONOS_ERR_OK;
615
616 #if (MYKONOS_VERBOSE == 1)
617 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_initialize()\n");
618 #endif
619
620 retVal = MYKONOS_verifyDeviceDataStructure(device);
621 if (retVal != MYKONOS_ERR_OK)
622 {
623 return retVal;
624 }
625
626 /* Verify Rx/Tx and ObsRx profiles are valid combinations */
627 retVal = MYKONOS_verifyProfiles(device);
628 if (retVal != MYKONOS_ERR_OK)
629 {
630 return retVal;
631 }
632
633 /* Set 3 or 4-wire SPI mode, MSBFirst/LSBfirst in device, pushes CPOL=0, CPHA=0, longInstWord=1 into device->spiSettings */
634 retVal = MYKONOS_setSpiSettings(device);
635 if (retVal != MYKONOS_ERR_OK)
636 {
637 return retVal;
638 }
639
640 /* Increase SPI_DO drive strength */
641 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_IO_CONTROL, 0x10);
642
643 /* Enable Reference clock - Set REFCLK pad common mode voltage */
644 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_REF_PAD_CONFIG2, 0x07);
645
646 /* Set Mykonos IO pin settings, GPIO direction, enable relevant LVDS pads */
647 /* Enable SYSREF LVDS input pad + 100ohm internal termination */
648 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SYSREF_PAD_CONFIG, 0x12); //Enable SYSREF input buffer
649
650 if ((device->tx > 0) && (device->tx->txProfile > 0))
651 {
652 /* Check for LVDS/CMOS mode */
653 if (device->tx->deframer->txSyncbMode > 0)
654 {
655 txSyncb = 0xF0;
656 }
657 else
658 {
659 txSyncb = 0x02;
660 }
661
662 /* Enable SYNCOUTB output buffer */
663 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_SYNC_PAD_CONFIG, txSyncb);
664 }
665
666 /* Look at each framer and enable the RXSYNCB used for each framer.
667 * It is possible that they use the same RXSYNCB pin */
668 if ((device->rx > 0) && (device->rx->framer > 0))
669 {
670 /* Check for LVDS/CMOS mode */
671 if (device->rx->framer->rxSyncbMode > 0)
672 {
673 rxSyncb = 0x00;
674 }
675 else
676 {
677 rxSyncb = 0x12;
678 }
679
680 if (device->rx->framer->obsRxSyncbSelect == 0)
681 {
682 /* Enable SYNCINB0 LVDS/CMOS input buffer */
683 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX1_SYNC_CONFIG, rxSyncb);
684 }
685 else
686 {
687 /* Enable SYNCINB1 LVDS/CMOS input buffer */
688 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX2_SYNC_CONFIG, rxSyncb);
689 }
690 }
691 if ((device->obsRx > 0) && (device->obsRx->framer > 0))
692 {
693 /* Check for LVDS/CMOS mode */
694 if (device->obsRx->framer->rxSyncbMode > 0)
695 {
696 orxSyncb = 0x00;
697 }
698 else
699 {
700 orxSyncb = 0x12;
701 }
702
703 if (device->obsRx->framer->obsRxSyncbSelect == 0)
704 {
705 /* Check for rxSyncb and orxSyncb when using the same RXSYNCB */
706 if ((orxSyncb != rxSyncb) && (device->rx->framer->obsRxSyncbSelect == 0))
707 {
708 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE,
709 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE));
710 return MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE;
711 }
712
713 /* Enable SYNCINB0 LVDS input buffer */
714 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX1_SYNC_CONFIG, orxSyncb);
715 }
716 else
717 {
718 /* Check for rxSyncb and orxSyncb when using the same ORXSYNCB */
719 if ((orxSyncb != rxSyncb) && (device->rx->framer->obsRxSyncbSelect == 1))
720 {
721 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE,
722 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE));
723 return MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE;
724 }
725
726 /* Enable SYNCINB1 LVDS input buffer */
727 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX2_SYNC_CONFIG, orxSyncb);
728 }
729 }
730
731 /* Set number of device clock cycles per microsecond [round(freq/2) - 1] */
732 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_REFERENCE_CLOCK_CYCLES, (uint8_t)((((device->clocks->deviceClock_kHz / 1000) + 1) >> 1) - 1));
733
734 /* Set profile specific digital clock dividers */
735 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_1, 0x04); /* Negate Rx2 so phase matches Rx1 */
736
737 if (device->profilesValid & TX_PROFILE_VALID)
738 {
739 txChannelSettings = (((uint8_t)device->tx->txChannels & 0x3) << 6);
740 switch (device->tx->txProfile->thb2Interpolation)
741 {
742 case 1:
743 break; /* keep bit as 0 in bitfield */
744 case 2:
745 txChannelSettings |= 0x20;
746 break;
747 default:
748 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION,
749 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION));
750 return MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION;
751 }
752
753 switch (device->tx->txProfile->thb1Interpolation)
754 {
755 case 1:
756 break; /* keep bit as 0 in bitfield */
757 case 2:
758 txChannelSettings |= 0x10;
759 break;
760 default:
761 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION,
762 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION));
763 return MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION;
764 }
765
766 if (device->tx->txProfile->txFir == NULL)
767 {
768 /* If invalid pointer to FIR filter, Bypass programmable FIR, keep txChannelSettings[1:0] == 0 */
769 }
770 else
771 {
772 switch (device->tx->txProfile->txFirInterpolation)
773 {
774 case 1:
775 txChannelSettings |= 0x01;
776 break;
777 case 2:
778 txChannelSettings |= 0x02;
779 break;
780 case 4:
781 txChannelSettings |= 0x03;
782 break;
783 default:
784 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION,
785 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION));
786 return MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION;
787 }
788 }
789
790 switch (device->tx->txProfile->dacDiv)
791 {
792 case DACDIV_2:
793 break; /* Keep bit [1]=0 */
794 case DACDIV_2p5:
795 break; /* Keep bit [1]=0, div 2.5 is set when Rx DEC5 filter enabled*/
796 case DACDIV_4:
797 adcDacClockRateSelect |= 2;
798 break;
799 default:
800 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_DACDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_DACDIV));
801 return MYKONOS_ERR_INIT_INV_DACDIV;
802 }
803 }
804
805 if (device->profilesValid & RX_PROFILE_VALID)
806 {
807 rxChannelSettings = (((uint8_t)device->rx->rxChannels & 0x3) << 6);
808 switch (device->rx->rxProfile->rxDec5Decimation)
809 {
810 case 4:
811 break; /* keep bit as 0 in bitfield */
812 case 5:
813 rxChannelSettings |= 0x04;
814 break;
815 default:
816 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION,
817 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION));
818 return MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION;
819 }
820
821 switch (device->rx->rxProfile->rhb1Decimation)
822 {
823 case 1:
824 break; /* keep bit as 0 in bitfield */
825 case 2:
826 rxChannelSettings |= 0x10;
827 break;
828 default:
829 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION,
830 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION));
831 return MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION;
832 }
833
834 if (device->rx->rxProfile->rxFir == NULL)
835 {
836 /* If invalid pointer to FIR filter, Bypass programmable FIR, keep rxChannelSettings[1:0] == 0 */
837 }
838 else
839 {
840 switch (device->rx->rxProfile->rxFirDecimation)
841 {
842 case 1:
843 rxChannelSettings |= 0x01;
844 break;
845 case 2:
846 rxChannelSettings |= 0x02;
847 break;
848 case 4:
849 rxChannelSettings |= 0x03;
850 break;
851 default:
852 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION,
853 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION));
854 return MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION;
855 }
856 }
857
858 switch (device->rx->rxProfile->adcDiv)
859 {
860 case 1:
861 adcDacClockRateSelect |= 0;
862 break;
863 case 2:
864 adcDacClockRateSelect |= 1;
865 break;
866 default:
867 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ADCDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ADCDIV));
868 return MYKONOS_ERR_INIT_INV_ADCDIV;
869 }
870
871 rxRealIfData = (device->rx->realIfData > 0) ? 1 : 0;
872 enRxHighRejDec5 = (device->rx->rxProfile->enHighRejDec5 > 0) ? 1 : 0;
873 }
874 else if (device->profilesValid & ORX_PROFILE_VALID)
875 {
876 /* if Rx profile not valid, but ORX profile valid, set RX ADC divider and dec5 to match orx profile setting */
877 /* ARM clock is derived from Rx clocking, so Rx ADC div needs to be set */
878 switch (device->obsRx->orxProfile->rxDec5Decimation)
879 {
880 case 4:
881 break; /* keep bit as 0 in bitfield */
882 case 5:
883 rxChannelSettings |= 0x04;
884 break;
885 default:
886 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION,
887 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION));
888 return MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION;
889 }
890
891 switch (device->obsRx->orxProfile->adcDiv)
892 {
893 case 1:
894 adcDacClockRateSelect |= 0;
895 break;
896 case 2:
897 adcDacClockRateSelect |= 1;
898 break;
899 default:
900 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ADCDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ADCDIV));
901 return MYKONOS_ERR_INIT_INV_ADCDIV;
902 }
903 }
904 else if (device->profilesValid & SNIFF_PROFILE_VALID)
905 {
906 /* if Rx profile not valid, and ORX profile not valid, set RX ADC divider and dec5 to match sniffer profile setting */
907 /* ARM clock is derived from Rx clocking, so Rx ADC div needs to be set */
908 switch (device->obsRx->snifferProfile->rxDec5Decimation)
909 {
910 case 4:
911 break; /* keep bit as 0 in bitfield */
912 case 5:
913 rxChannelSettings |= 0x04;
914 break;
915 default:
916 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION,
917 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION));
918 return MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION;
919 }
920
921 switch (device->obsRx->snifferProfile->adcDiv)
922 {
923 case 1:
924 adcDacClockRateSelect |= 0;
925 break;
926 case 2:
927 adcDacClockRateSelect |= 1;
928 break;
929 default:
930 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ADCDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ADCDIV));
931 return MYKONOS_ERR_INIT_INV_ADCDIV;
932 }
933 }
934
935 /* determine ObsRx ADC Div setting */
936 if (device->profilesValid & ORX_PROFILE_VALID)
937 {
938 switch (device->obsRx->orxProfile->adcDiv)
939 {
940 case 1:
941 break; /* Keep bit[4]=0 */
942 case 2:
943 adcDacClockRateSelect |= 0x10;
944 break; /* Set bit[4]=1 */
945 default:
946 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV,
947 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV));
948 return MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV;
949 }
950 }
951 else if (device->profilesValid & SNIFF_PROFILE_VALID)
952 {
953 switch (device->obsRx->snifferProfile->adcDiv)
954 {
955 case 1:
956 break; /* Keep bit[4]=0 */
957 case 2:
958 adcDacClockRateSelect |= 0x10;
959 break; /* Set bit[4]=1 */
960 default:
961 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV,
962 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV));
963 return MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV;
964 }
965 }
966 else if (device->profilesValid & RX_PROFILE_VALID)
967 { /* if OBSRX profiles are not valid, set obsRx ADC div to match Rx ADC divider */
968 switch (device->rx->rxProfile->adcDiv)
969 {
970 case 1:
971 break; /* Keep bit[4]=0 */
972 case 2:
973 adcDacClockRateSelect |= 0x10;
974 break; /* Set bit[4]=1 */
975 default:
976 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV,
977 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV));
978 return MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV;
979 }
980 }
981
982 /* Determine ORx and Sniffer channel settings */
983 if (device->obsRx != NULL)
984 {
985 /* verify pointers in data structure are valid (non-zero) */
986 if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))
987 {
988 if (device->obsRx->realIfData > 0)
989 {
990 obsRxRealIf = 1;
991 }
992 }
993
994 /* TODO: verify that the decimation matches the given IQ rate in the data structure */
995
996 /* Set Sniffer profile (digital filter enables) if sniffer profile enabled (valid pointer) */
997 if (device->profilesValid & SNIFF_PROFILE_VALID)
998 {
999 sniffChannelSettings = 0;
1000 switch (device->obsRx->snifferProfile->rhb1Decimation)
1001 {
1002 case 1:
1003 break;
1004 case 2:
1005 sniffChannelSettings |= 0x10;
1006 break;
1007 default:
1008 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_SNIFFER_RHB1,
1009 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_SNIFFER_RHB1));
1010 return MYKONOS_ERR_INIT_INV_SNIFFER_RHB1;
1011 }
1012
1013 if (device->obsRx->snifferProfile->rxFir != NULL)
1014 {
1015
1016 switch (device->obsRx->snifferProfile->rxFirDecimation)
1017 {
1018 case 1:
1019 sniffChannelSettings |= 0x01;
1020 break;
1021 case 2:
1022 sniffChannelSettings |= 0x02;
1023 break;
1024 case 4:
1025 sniffChannelSettings |= 0x03;
1026 break;
1027 default:
1028 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC,
1029 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC));
1030 return MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC;
1031 }
1032 }
1033 }
1034
1035 /* Set ORx profile (digital filter enables) if ORx profile enabled (valid pointer) */
1036 if (device->profilesValid & ORX_PROFILE_VALID)
1037 {
1038 orxChannelSettings = 0;
1039 switch (device->obsRx->orxProfile->rhb1Decimation)
1040 {
1041 case 1:
1042 break;
1043 case 2:
1044 orxChannelSettings |= 0x10;
1045 break;
1046 default:
1047 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ORX_RHB1,
1048 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ORX_RHB1));
1049 return MYKONOS_ERR_INIT_INV_ORX_RHB1;
1050 }
1051
1052 if (device->obsRx->orxProfile->rxFir != NULL)
1053 {/* if pointer to orx rxFIR is valid */
1054
1055 switch (device->obsRx->orxProfile->rxFirDecimation)
1056 {
1057 case 1:
1058 orxChannelSettings |= 0x01;
1059 break;
1060 case 2:
1061 orxChannelSettings |= 0x02;
1062 break;
1063 case 4:
1064 orxChannelSettings |= 0x03;
1065 break;
1066 default:
1067 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC,
1068 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC));
1069 return MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC;
1070 }
1071 }
1072 }
1073 }
1074
1075 /************************************************************************
1076 * Set channel config settings for Rx/Tx/oRx and Sniffer channels
1077 ***********************************************************************
1078 */
1079 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_2, txChannelSettings);
1080 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_4, rxChannelSettings);
1081
1082 /* Set option to use new high rejection DEC5 filters in main Rx1/Rx2 path. */
1083 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_5, ((uint8_t)(rxRealIfData << 2) | (enRxHighRejDec5 ? 3 : 0)));
1084
1085 if (rxRealIfData > 0)
1086 {
1087 /* Set Rx1 NCO frequency */
1088 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_3, 0x40);
1089 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_2, 0x00);
1090 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_1, 0x01);
1091
1092 /* Set Rx2 NCO frequency */
1093 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_3, 0x40);
1094 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_2, 0x00);
1095 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_1, 0x01);
1096
1097 /* Enable NCO for Rx1 and Rx2 to shift data from zero IF to real IF */
1098 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_NCO_CONTROL, 3, 0x03, 0);
1099 }
1100
1101 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_CONFIGURATION_CONTROL_2, obsRxRealIf, 0x40, 6);
1102
1103 /* if sniffer profile disabled, Sniffer config reg is set to default = 0x80 */
1104 sniffChannelSettings |= 0x80; /* use PFIR coef set B = bit[7]=1*/
1105 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SNIFFER_CONFIGURATION_CONTROL, sniffChannelSettings);
1106
1107 /* if orx profile not valid, SPI reg for orx config is set to default = 0x00 */
1108 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_CONFIGURATION_CONTROL, orxChannelSettings);
1109 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_LOOPBACK_CONFIGURATION_CONTROL, orxChannelSettings);
1110
1111 /* Set ADC divider, DAC divider, and ObsRx/sniffer dividers */
1112 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_1, adcDacClockRateSelect, 0x13, 0);
1113
1114 /* Disable ORx digital DC offset - bad default SPI setting for ObsRx DC offset */
1115 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_DC_OFFSET_CH3_DPD_M_SHIFT, 0x60);
1116
1117 /* Necessary write for ARM init cals to work */
1118 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SNIFF_RXLOGEN_BYTE1, 0x0E);
1119
1120 /* Increase Sniffer LNA gain */
1121 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SNRX_LNA_BIAS_C, 0x0F);
1122
1123 /* Set the CLKPLL with the frequency from the device data structure */
1124 retVal = MYKONOS_initDigitalClocks(device);
1125 if (retVal != MYKONOS_ERR_OK)
1126 {
1127 return retVal;
1128 }
1129
1130 /* Wait for CLKPLL CP Cal done and CLKPLL Lock or throw error message */
1131 CMB_wait_ms(500);
1132 retVal = MYKONOS_waitForEvent(device, CLKPLLCP, 1000000);
1133 if (retVal != MYKONOS_ERR_OK)
1134 {
1135 return retVal;
1136 }
1137
1138 retVal = MYKONOS_waitForEvent(device, CLKPLL_LOCK, 1000000);
1139 if (retVal != MYKONOS_ERR_OK)
1140 {
1141 return retVal;
1142 }
1143
1144 /* Enable digital clocks - this is gated by the CLKPLL being locked */
1145 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_0, 0x14);
1146
1147 /* Set the Tx PFIR synchronization clock */
1148 retVal = MYKONOS_setTxPfirSyncClk(device);
1149 if (retVal != MYKONOS_ERR_OK)
1150 {
1151 return retVal;
1152 }
1153
1154 /* Set the Rx PFIR synchronization clock */
1155 retVal = MYKONOS_setRxPfirSyncClk(device);
1156 if (retVal != MYKONOS_ERR_OK)
1157 {
1158 return retVal;
1159 }
1160
1161 if (device->profilesValid & TX_PROFILE_VALID)
1162 {
1163 /* Set pre TxPFIR Half band filter interpolation */
1164 if (device->tx->txProfile->txInputHbInterpolation == 1)
1165 {
1166 /* disable TX input half band ([3:2]=00) - but allow DPD to still be enabled for tx profiles with wide BW [1] */
1167 enableDpd = (device->tx->txProfile->enableDpdDataPath > 0) ? 1 : 0;
1168 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, enableDpd, 0x0E, 1);
1169 }
1170 else if (device->tx->txProfile->txInputHbInterpolation == 2)
1171 {
1172 if (device->tx->txProfile->iqRate_kHz > 160000)
1173 {
1174 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE,
1175 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE));
1176 return MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE;
1177 }
1178
1179 /* enable TX input half band[2]=1, and Enable DPD[1]=1*/
1180 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, 3, 0x0E, 1);
1181 }
1182 else if (device->tx->txProfile->txInputHbInterpolation == 4)
1183 {
1184 if (device->tx->txProfile->iqRate_kHz > 80000)
1185 {
1186 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE,
1187 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE));
1188 return MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE;
1189 }
1190
1191 /* enable TX input HB0[3]=1 and Tx input HB[2]=1, and Enable DPD[1]=1*/
1192 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, 7, 0x0E, 1);
1193 }
1194 else
1195 {
1196 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM,
1197 getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM));
1198 return MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM;
1199 }
1200
1201 /* Enable SPI Tx Atten mode */
1202 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x01, 0x03, 0);
1203 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x01, 0x0C, 2);
1204
1205 /* Set Tx1 Atten step size */
1206 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_INCR_DECR_WORD, device->tx->txAttenStepSize, 0x60, 5);
1207
1208 /* Set Tx2 Atten step size */
1209 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, device->tx->txAttenStepSize, 0x60, 5);
1210 }
1211 else
1212 {
1213 /* Power down DACs */
1214 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_PD_OVERIDE_7_0, 3, 0x0C, 2);
1215 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_PD_OVERRIDE_CONTROL_7_0, 3, 0x0C, 2);
1216 }
1217
1218 /* Set RxFE LO Common mode */
1219 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXFE1_LOCM, 0xF0);
1220 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXFE2_LOCM, 0xF0);
1221
1222 /* Set Rxloopback LO Common mode */
1223 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXLOOPBACK1_CNTRL_1, 0xFF);
1224 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXLOOPBACK2_CNTRL_1, 0xFF);
1225
1226 /* Setup MGC or AGC Rx gain control */
1227 if ((retVal = MYKONOS_setupRxAgc(device)) != MYKONOS_ERR_OK)
1228 {
1229 return retVal;
1230 }
1231
1232 /* Default Rx to use manual gain control until AGC enabled by user */
1233 if ((retVal = MYKONOS_setRxGainControlMode(device, MGC)) != MYKONOS_ERR_OK)
1234 {
1235 return retVal;
1236 }
1237
1238
1239 if ((retVal = MYKONOS_setupObsRxAgc(device)) != MYKONOS_ERR_OK)
1240 {
1241 return retVal;
1242 }
1243
1244 /* Default ObsRx to use manual gain control until AGC enabled by user */
1245 if ((retVal = MYKONOS_setObsRxGainControlMode(device, MGC)) != MYKONOS_ERR_OK)
1246 {
1247 return retVal;
1248 }
1249
1250 /* Disable GPIO select bits by setting to b11 */
1251 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_1, 3, 0x30, 4);
1252
1253 /* Extra settings for ARM calibrations */
1254 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_DC_OFFSET_SHIFT, 0x11);
1255 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_LOOPBACK1_CNTRL_4, 0x04);
1256 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_LOOPBACK2_CNTRL_4, 0x04);
1257 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_CFG_2, 0x20, 0x20, 0);
1258
1259 /* Extra settings for ADC initialisation */
1260 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_ADC_FLASH_DELAY, 0x28);
1261 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_ADC_FLASH_CTRL, 0x0E);
1262 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_ADC_FLASH_DELAY, 0x28);
1263 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_ADC_FLASH_CTRL, 0x0E);
1264
1265 /* Move to Alert ENSM state */
1266 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ENSM_CONFIG_7_0, 0x05);
1267
1268 return MYKONOS_ERR_OK;
1269 }
1270
1271 /**
1272 * \brief Verifies the init structure profiles are valid combinations
1273 *
1274 * This function checks that the Rx/Tx/ORx/Sniffer profiles have valid clock rates in
1275 * order to operate together. Rx/Tx and ORx/Sniffer share a common high speed digital
1276 * clock. If an invalid combination of profiles is detected, an error will be
1277 * returned. If a profile in the init structure is unused, the user should zero
1278 * out all members of that particular profile structure. If a Rx/Tx/ORx/Sniffer profile
1279 * has an IQ rate = 0, it is assumed that the profile is disabled.
1280 *
1281 * \pre This function is private and is not called directly by the user.
1282 *
1283 * This function uses mykVerifyTxProfile() and mykVerifyRxProfile() as helper functions.
1284 *
1285 * <B>Dependencies</B>
1286 * - device->spiSettings
1287 * - device->spiSettings->chipSelectIndex
1288 *
1289 * \param device Structure pointer to Mykonos device data structure
1290 *
1291 * \retval MYKONOS_ERR_PROFILES_HSDIGCLK profiles loaded are not valid
1292 * \retval MYKONOS_ERR_OK Function completed successfully
1293 */
MYKONOS_verifyProfiles(mykonosDevice_t * device)1294 mykonosErr_t MYKONOS_verifyProfiles(mykonosDevice_t *device)
1295 {
1296 mykonosErr_t retVal = MYKONOS_ERR_OK;
1297
1298 uint32_t rxHsDigClk_kHz = 0;
1299 uint32_t orxHsDigClk_kHz = 0;
1300 uint32_t snifferHsDigClk_kHz = 0;
1301 uint32_t txHsDigClk_kHz = 0;
1302
1303 mykonosRxProfile_t *rxProfile = NULL;
1304 mykonosTxProfile_t *txProfile = NULL;
1305 mykonosRxProfile_t *orxProfile = NULL;
1306 mykonosRxProfile_t *snifferProfile = NULL;
1307
1308 #if (MYKONOS_VERBOSE == 1)
1309 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_verifyProfiles()\n");
1310 #endif
1311
1312 device->profilesValid = 0;
1313
1314 /* Check all loaded profiles */
1315 if (device->tx->txChannels != TXOFF)
1316 {
1317 txProfile = device->tx->txProfile;
1318 retVal = mykVerifyTxProfile(device, txProfile, &txHsDigClk_kHz);
1319 if (retVal != MYKONOS_ERR_OK)
1320 {
1321 return retVal;
1322 }
1323 }
1324
1325 if (device->rx->rxChannels != RXOFF)
1326 {
1327 rxProfile = device->rx->rxProfile;
1328 retVal = mykVerifyRxProfile(device, MYK_RX_PROFILE, rxProfile, &rxHsDigClk_kHz);
1329 if (retVal != MYKONOS_ERR_OK)
1330 {
1331 return retVal;
1332 }
1333 }
1334
1335 if (device->obsRx->obsRxChannelsEnable != MYK_OBS_RXOFF)
1336 {
1337 if ((uint32_t)device->obsRx->obsRxChannelsEnable & (uint32_t)MYK_ORX1_ORX2)
1338 {
1339 orxProfile = device->obsRx->orxProfile;
1340 retVal = mykVerifyRxProfile(device, MYK_OBS_PROFILE, orxProfile, &orxHsDigClk_kHz);
1341 if (retVal != MYKONOS_ERR_OK)
1342 {
1343 return retVal;
1344 }
1345 }
1346
1347 if ((uint32_t)device->obsRx->obsRxChannelsEnable & (uint32_t)MYK_SNRXA_B_C)
1348 {
1349 snifferProfile = device->obsRx->snifferProfile;
1350 retVal = mykVerifyRxProfile(device, MYK_SNIFFER_PROFILE, snifferProfile, &snifferHsDigClk_kHz);
1351 if (retVal != MYKONOS_ERR_OK)
1352 {
1353 return retVal;
1354 }
1355 }
1356 }
1357
1358 return retVal;
1359 }
1360
1361 /**
1362 * \brief Write indirect registers (Programmable FIRs, Rx gain tables, JESD204B settings). Must be done after Multi Chip Sync
1363 *
1364 * The BBP should never need to call this function. It is called automatically by the initArm function.
1365 * This function is a continuation of the MYKONOS_initialize() function. This part of initialization must be done after
1366 * the BBP has completed Multi chip Sync. These registers include FIR filters, Rx gain tables, and JESD204B framer/deframer
1367 * config registers.
1368 *
1369 * <B>Dependencies</B>
1370 * - device->spiSettings
1371 * - device->spiSettings->chipSelectIndex
1372 *
1373 * \param device Pointer to the Mykonos device data structure containing settings
1374 * an error.
1375 * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
1376 */
MYKONOS_initSubRegisterTables(mykonosDevice_t * device)1377 mykonosErr_t MYKONOS_initSubRegisterTables(mykonosDevice_t *device)
1378 {
1379 mykonosErr_t retVal = MYKONOS_ERR_OK;
1380
1381 /* ------------------------------------------------------------------------------------------- */
1382 /* Program submap register tables after digital clocks are up and running and Multi Chip Sync */
1383 /* has been completed by BBP */
1384 if (device->profilesValid & TX_PROFILE_VALID)
1385 {
1386 if (device->tx->txProfile->txFir != NULL)
1387 {
1388 retVal = MYKONOS_programFir(device, TX1TX2_FIR, device->tx->txProfile->txFir);
1389 if (retVal != MYKONOS_ERR_OK)
1390 {
1391 return retVal;
1392 }
1393 }
1394 }
1395
1396 if (device->profilesValid & RX_PROFILE_VALID)
1397 {
1398 if (device->rx->rxProfile->rxFir != NULL)
1399 {
1400 retVal = MYKONOS_programFir(device, RX1RX2_FIR, device->rx->rxProfile->rxFir);
1401 if (retVal != MYKONOS_ERR_OK)
1402 {
1403 return retVal;
1404 }
1405
1406 /* Load Rx gain table */
1407 retVal = MYKONOS_programRxGainTable(device, &RxGainTable[0][0], (sizeof(RxGainTable) >> 2), RX1_RX2_GT);
1408 if (retVal != MYKONOS_ERR_OK)
1409 {
1410 return retVal;
1411 }
1412
1413 retVal = MYKONOS_setRx1ManualGain(device, device->rx->rxGainCtrl->rx1GainIndex);
1414 if (retVal != MYKONOS_ERR_OK)
1415 {
1416 return retVal;
1417 }
1418
1419 retVal = MYKONOS_setRx2ManualGain(device, device->rx->rxGainCtrl->rx2GainIndex);
1420 if (retVal != MYKONOS_ERR_OK)
1421 {
1422 return retVal;
1423 }
1424
1425 /* Enable Digital gain for Rx and ObsRx gain tables */
1426 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_GAIN_CONFIG, 0x80);
1427 }
1428 }
1429
1430 if (device->profilesValid & SNIFF_PROFILE_VALID)
1431 {
1432 if (device->obsRx->snifferProfile->rxFir != NULL)
1433 {
1434 retVal = MYKONOS_programFir(device, OBSRX_B_FIR, device->obsRx->snifferProfile->rxFir);
1435 if (retVal != MYKONOS_ERR_OK)
1436 {
1437 return retVal;
1438 }
1439
1440 /* Load Sniffer Rx gain table */
1441 retVal = MYKONOS_programRxGainTable(device, &SnRxGainTable[0][0], (sizeof(SnRxGainTable) >> 2), SNRX_GT);
1442 if (retVal != MYKONOS_ERR_OK)
1443 {
1444 return retVal;
1445 }
1446
1447 retVal = MYKONOS_setObsRxManualGain(device, OBS_SNIFFER_A, device->obsRx->snifferGainCtrl->gainIndex);
1448 if (retVal != MYKONOS_ERR_OK)
1449 {
1450 return retVal;
1451 }
1452 }
1453 }
1454
1455 if (device->profilesValid & ORX_PROFILE_VALID)
1456 {
1457 if (device->obsRx->orxProfile->rxFir != NULL)
1458 {/* if pointer to orx rxFIR is valid */
1459 retVal = MYKONOS_programFir(device, OBSRX_A_FIR, device->obsRx->orxProfile->rxFir);
1460 if (retVal != MYKONOS_ERR_OK)
1461 {
1462 return retVal;
1463 }
1464
1465 /* Load ORx gain table */
1466 retVal = MYKONOS_programRxGainTable(device, &ORxGainTable[0][0], (sizeof(ORxGainTable) >> 2), ORX_GT);
1467 if (retVal != MYKONOS_ERR_OK)
1468 {
1469 return retVal;
1470 }
1471
1472 retVal = MYKONOS_setObsRxManualGain(device, OBS_RX1_TXLO, device->obsRx->orxGainCtrl->orx1GainIndex);
1473 if (retVal != MYKONOS_ERR_OK)
1474 {
1475 return retVal;
1476 }
1477
1478 retVal = MYKONOS_setObsRxManualGain(device, OBS_RX2_TXLO, device->obsRx->orxGainCtrl->orx2GainIndex);
1479 if (retVal != MYKONOS_ERR_OK)
1480 {
1481 return retVal;
1482 }
1483 }
1484 }
1485
1486 /* Load Loopback Gain Table for ARM calibrations */
1487 {
1488 uint8_t loopBackGainTable[6][4] = {
1489 /* Order: {FE table, External Ctl, Digital Gain/Atten, Enable Atten} */
1490 {0, 0, 0, 0}, /* Gain index 255 */
1491 {7, 0, 0, 0}, /* Gain index 254 */
1492 {13, 0, 1, 1}, /* Gain index 253 */
1493 {18, 0, 3, 1}, /* Gain index 252 */
1494 {23, 0, 3, 1}, /* Gain index 251 */
1495 {28, 0, 0, 0} /* Gain index 250 */
1496 };
1497 retVal = MYKONOS_programRxGainTable(device, &loopBackGainTable[0][0], (sizeof(loopBackGainTable) >> 2), LOOPBACK_GT);
1498 }
1499
1500 /* Enable Digital gain for ORx/Sniffer/Loopback gain table */
1501 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_DIGITAL_GAIN_CONFIG, 0x80);
1502
1503 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RCAL_CONTROL, 0x07);/* Set RCAL code to nominal */
1504
1505 /* If Valid Rx Profile or valid ObsRx profile, setup serializers */
1506 if ((device->profilesValid & RX_PROFILE_VALID) || (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)))
1507 {
1508 retVal = MYKONOS_setupSerializers(device);
1509 if (retVal != MYKONOS_ERR_OK)
1510 {
1511 return retVal;
1512 }
1513 }
1514
1515 if ((device->rx->rxChannels != RXOFF) && (device->profilesValid & RX_PROFILE_VALID))
1516 {
1517 retVal = MYKONOS_setupJesd204bFramer(device);
1518 if (retVal != MYKONOS_ERR_OK)
1519 {
1520 return retVal;
1521 }
1522 }
1523
1524 if ((device->obsRx->obsRxChannelsEnable != MYK_OBS_RXOFF) && (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)))
1525 {
1526 retVal = MYKONOS_setupJesd204bObsRxFramer(device);
1527 if (retVal != MYKONOS_ERR_OK)
1528 {
1529 return retVal;
1530 }
1531 }
1532
1533 if ((device->tx->txChannels != TXOFF) && (device->profilesValid & TX_PROFILE_VALID))
1534 {
1535 retVal = MYKONOS_setupDeserializers(device);
1536 if (retVal != MYKONOS_ERR_OK)
1537 {
1538 return retVal;
1539 }
1540
1541 retVal = MYKONOS_setupJesd204bDeframer(device);
1542 if (retVal != MYKONOS_ERR_OK)
1543 {
1544 return retVal;
1545 }
1546
1547 retVal = MYKONOS_setTx1Attenuation(device, device->tx->tx1Atten_mdB);
1548 if (retVal != MYKONOS_ERR_OK)
1549 {
1550 return retVal;
1551 }
1552
1553 retVal = MYKONOS_setTx2Attenuation(device, device->tx->tx2Atten_mdB);
1554 if (retVal != MYKONOS_ERR_OK)
1555 {
1556 return retVal;
1557 }
1558 }
1559
1560 return MYKONOS_ERR_OK;
1561 }
1562
1563 /**
1564 * \brief Performs a blocking wait for a Mykonos calibration or Pll Lock
1565 *
1566 * <B>Dependencies</B>
1567 * - device->spiSettings
1568 * - device->spiSettings->chipSelectIndex
1569 *
1570 * \param device Pointer to the Mykonos device data structure containing settings
1571 * \param waitEvent the enum value of the event to wait for
1572 * \param timeout_us If timeout_us time has passed, function will return with
1573 * an error.
1574 * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
1575 */
MYKONOS_waitForEvent(mykonosDevice_t * device,waitEvent_t waitEvent,uint32_t timeout_us)1576 mykonosErr_t MYKONOS_waitForEvent(mykonosDevice_t *device, waitEvent_t waitEvent, uint32_t timeout_us)
1577 {
1578 uint16_t spiAddr = 0;
1579 uint8_t spiBit = 0;
1580 uint8_t doneBitLevel = 0;
1581 uint8_t data = 0;
1582 mykonosErr_t errCode = MYKONOS_ERR_OK;
1583
1584 #if (MYKONOS_VERBOSE == 1)
1585 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_waitForEvent()\n");
1586 #endif
1587
1588 switch (waitEvent)
1589 {
1590 case CALPLL_LOCK:/* wait for x17F[7]=1 */
1591 spiAddr = MYKONOS_ADDR_CALPLL_SDM_CONTROL;
1592 spiBit = 7;
1593 doneBitLevel = 1;
1594 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CALPLL_LOCK;
1595 break;
1596 case CLKPLLCP: /* wait for x154[5]=1 */
1597 spiAddr = MYKONOS_ADDR_CLK_SYNTH_CAL_STAT;
1598 spiBit = 5;
1599 doneBitLevel = 1;
1600 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLLCP;
1601 break;
1602 case CLKPLL_LOCK: /* wait for x157[0]=1 */
1603 spiAddr = MYKONOS_ADDR_CLK_SYNTH_VCO_BAND_BYTE1;
1604 spiBit = 0;
1605 doneBitLevel = 1;
1606 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLL_LOCK;
1607 break;
1608 case RF_RXPLLCP:/* wait for x254[5]=1 */
1609 spiAddr = MYKONOS_ADDR_RXSYNTH_CP_CAL_STAT;
1610 spiBit = 5;
1611 doneBitLevel = 1;
1612 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLLCP;
1613 break;
1614 case RF_RXPLL_LOCK: /* wait for x257[0]=1 */
1615 spiAddr = MYKONOS_ADDR_RXSYNTH_VCO_BAND_BYTE1;
1616 spiBit = 0;
1617 doneBitLevel = 1;
1618 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLL_LOCK;
1619 break;
1620 case RF_TXPLLCP: /* wait for x2C4[5]=1 */
1621 spiAddr = MYKONOS_ADDR_TXSYNTH_CP_CAL_STAT;
1622 spiBit = 5;
1623 doneBitLevel = 1;
1624 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLLCP;
1625 break;
1626 case RF_TXPLL_LOCK: /* wait for x2C7[0]=1 */
1627 spiAddr = MYKONOS_ADDR_TXSYNTH_VCO_BAND_BYTE1;
1628 spiBit = 0;
1629 doneBitLevel = 1;
1630 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLL_LOCK;
1631 break;
1632 case RF_SNIFFERPLLCP: /* wait for x354[7]=1 */
1633 spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_CP_CAL_STAT;
1634 spiBit = 5;
1635 doneBitLevel = 1;
1636 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLLCP;
1637 break;
1638 case RF_SNIFFERPLL_LOCK: /* wait for x357[0]=1 */
1639 spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_VCO_BAND_BYTE1;
1640 spiBit = 0;
1641 doneBitLevel = 1;
1642 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLL_LOCK;
1643 break;
1644 case RXBBF_CALDONE: /* wait for x1B2[5]=0 */
1645 spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL;
1646 spiBit = 5;
1647 doneBitLevel = 0;
1648 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXBBFCALDONE;
1649 break;
1650 case TXBBF_CALDONE:/* wait for x1B2[0]=0 */
1651 spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL;
1652 spiBit = 0;
1653 doneBitLevel = 0;
1654 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXBBFCALDONE;
1655 break;
1656 case RX_RFDC_CALDONE: /* wait for x1B2[1]=0 */
1657 spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL;
1658 spiBit = 1;
1659 doneBitLevel = 0;
1660 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RFDCCALDONE;
1661 break;
1662 case RX_ADCTUNER_CALDONE:/* wait for x1B2[7]=0 */
1663 spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL;
1664 spiBit = 7;
1665 doneBitLevel = 0;
1666 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ADCTUNECALDONE;
1667 break;
1668 case RX1_ADCPROFILE:/* wait for x5DD[5]=0 */
1669 spiAddr = MYKONOS_ADDR_RX_ADC1_PRFL;
1670 spiBit = 5;
1671 doneBitLevel = 0;
1672 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX1ADCPROFILE;
1673 break;
1674 case RX2_ADCPROFILE:/* wait for x5DE[5]=0 */
1675 spiAddr = MYKONOS_ADDR_RX_ADC2_PRFL;
1676 spiBit = 5;
1677 doneBitLevel = 0;
1678 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX2ADCPROFILE;
1679 break;
1680 case ORX_ADCPROFILE:/* wait for x5DF[5]=0 */
1681 spiAddr = MYKONOS_ADDR_ORX_ADC_PRFL;
1682 spiBit = 5;
1683 doneBitLevel = 0;
1684 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ORXADCPROFILE;
1685 break;
1686 case RCAL_CALDONE: /* wait for x1B2[6]=0 */
1687 spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL;
1688 spiBit = 6;
1689 doneBitLevel = 0;
1690 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RCALDONE;
1691 break;
1692 case ARMBUSY:/* wait for xD30[7]=0 */
1693 spiAddr = MYKONOS_ADDR_ARM_CMD;
1694 spiBit = 7;
1695 doneBitLevel = 0;
1696 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ARMBUSY;
1697 break;
1698 case INITARM_DONE:
1699 spiAddr = MYKONOS_ADDR_ARM_CMD;
1700 spiBit = 7;
1701 doneBitLevel = 0;
1702 errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_INITARMDONE;
1703 break;
1704 default:
1705 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAITFOREVENT_INV_PARM,
1706 getMykonosErrorMessage(MYKONOS_ERR_WAITFOREVENT_INV_PARM));
1707 return MYKONOS_ERR_WAITFOREVENT_INV_PARM;
1708 }
1709
1710 CMB_setTimeout_us(device->spiSettings, timeout_us); /* timeout after desired time */
1711
1712 do
1713 {
1714 CMB_SPIReadByte(device->spiSettings, spiAddr, &data);
1715
1716 /* For SW verification tests, allow API to think all cals are complete*/
1717 #ifdef MYK_CALS_DONE_SWDEBUG
1718 if (doneBitLevel == 0)
1719 {
1720 data = 0x00;
1721 }
1722 else
1723 {
1724 data = 0xFF;
1725 }
1726 #endif
1727
1728 if ((uint32_t)CMB_hasTimeoutExpired(device->spiSettings) > 0)
1729 {
1730 CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, errCode, getMykonosErrorMessage(errCode));
1731 return errCode;
1732 }
1733 } while (((data >> spiBit) & 0x01) != doneBitLevel);
1734
1735 return MYKONOS_ERR_OK;
1736 }
1737
1738 /**
1739 * \brief Performs a readback with no wait for a Mykonos calibration or Pll Lock
1740 *
1741 * <B>Dependencies</B>
1742 * - device->spiSettings
1743 * - device->spiSettings->chipSelectIndex
1744 *
1745 * \param device Pointer to the Mykonos device data structure containing settings
1746 * \param waitEvent the enum value of the event to wait for
1747 * \param eventDone Return value: 1= calibration event is complete. 0 = Event is still pending
1748 * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
1749 */
MYKONOS_readEventStatus(mykonosDevice_t * device,waitEvent_t waitEvent,uint8_t * eventDone)1750 mykonosErr_t MYKONOS_readEventStatus(mykonosDevice_t *device, waitEvent_t waitEvent, uint8_t *eventDone)
1751 {
1752 uint16_t spiAddr = 0;
1753 uint8_t data = 0;
1754 uint8_t spiBit = 0;
1755 uint8_t doneBitLevel = 0;
1756
1757 switch (waitEvent)
1758 {
1759 case CALPLL_LOCK:/* wait for x17F[7]=1 */
1760 spiAddr = MYKONOS_ADDR_CALPLL_SDM_CONTROL;
1761 spiBit = 7;
1762 doneBitLevel = 1;
1763 break;
1764 case CLKPLLCP: /* wait for x154[5]=1 */
1765 spiAddr = MYKONOS_ADDR_CLK_SYNTH_CAL_STAT;
1766 spiBit = 5;
1767 doneBitLevel = 1;
1768 break;
1769 case CLKPLL_LOCK: /* wait for x157[0]=1 */
1770 spiAddr = MYKONOS_ADDR_CLK_SYNTH_VCO_BAND_BYTE1;
1771 spiBit = 0;
1772 doneBitLevel = 1;
1773 break;
1774 case RF_RXPLLCP:/* wait for x254[5]=1 */
1775 spiAddr = MYKONOS_ADDR_RXSYNTH_CP_CAL_STAT;
1776 spiBit = 5;
1777 doneBitLevel = 1;
1778 break;
1779 case RF_RXPLL_LOCK: /* wait for x257[0]=1 */
1780 spiAddr = MYKONOS_ADDR_RXSYNTH_VCO_BAND_BYTE1;
1781 spiBit = 0;
1782 doneBitLevel = 1;
1783 break;
1784 case RF_TXPLLCP: /* wait for x2C4[5]=1 */
1785 spiAddr = MYKONOS_ADDR_TXSYNTH_CP_CAL_STAT;
1786 spiBit = 5;
1787 doneBitLevel = 1;
1788 break;
1789 case RF_TXPLL_LOCK: /* wait for x2C7[0]=1 */
1790 spiAddr = MYKONOS_ADDR_TXSYNTH_VCO_BAND_BYTE1;
1791 spiBit = 0;
1792 doneBitLevel = 1;
1793 break;
1794 case RF_SNIFFERPLLCP: /* wait for x354[7]=1 */
1795 spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_CP_CAL_STAT;
1796 spiBit = 5;
1797 doneBitLevel = 1;
1798 break;
1799 case RF_SNIFFERPLL_LOCK: /* wait for x357[0]=1 */
1800 spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_VCO_BAND_BYTE1;
1801 spiBit = 0;
1802 doneBitLevel = 1;
1803 break;
1804 case RXBBF_CALDONE: /* wait for x1B2[5]=0 */
1805 spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL;
1806 spiBit = 5;
1807 doneBitLevel = 0;
1808 break;
1809 case TXBBF_CALDONE:/* wait for x1B2[0]=0 */
1810 spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL;
1811 spiBit = 0;
1812 doneBitLevel = 0;
1813 break;
1814 case RX_RFDC_CALDONE: /* wait for x1B2[1]=0 */
1815 spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL;
1816 spiBit = 1;
1817 doneBitLevel = 0;
1818 break;
1819 case RX_ADCTUNER_CALDONE:/* wait for x1B2[7]=0 */
1820 spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL;
1821 spiBit = 7;
1822 doneBitLevel = 0;
1823 break;
1824 case RX1_ADCPROFILE:/* wait for x5DD[5]=0 */
1825 spiAddr = MYKONOS_ADDR_RX_ADC1_PRFL;
1826 spiBit = 5;
1827 doneBitLevel = 0;
1828 break;
1829 case RX2_ADCPROFILE:/* wait for x5DE[5]=0 */
1830 spiAddr = MYKONOS_ADDR_RX_ADC2_PRFL;
1831 spiBit = 5;
1832 doneBitLevel = 0;
1833 break;
1834 case ORX_ADCPROFILE:/* wait for x5DF[5]=0 */
1835 spiAddr = MYKONOS_ADDR_ORX_ADC_PRFL;
1836 spiBit = 5;
1837 doneBitLevel = 0;
1838 break;
1839 case RCAL_CALDONE: /* wait for x1B2[6]=0 */
1840 spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL;
1841 spiBit = 6;
1842 doneBitLevel = 0;
1843 break;
1844 case ARMBUSY:/* wait for xD30[7]=0 */
1845 spiAddr = MYKONOS_ADDR_ARM_CMD;
1846 spiBit = 7;
1847 doneBitLevel = 0;
1848 break;
1849 default:
1850 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAITFOREVENT_INV_PARM,
1851 getMykonosErrorMessage(MYKONOS_ERR_WAITFOREVENT_INV_PARM));
1852 return MYKONOS_ERR_WAITFOREVENT_INV_PARM;
1853 }
1854
1855 CMB_SPIReadByte(device->spiSettings, spiAddr, &data);
1856
1857 if (doneBitLevel)
1858 {
1859 *eventDone = (data >> spiBit) & 0x01;
1860 }
1861 else
1862 {
1863 *eventDone = (~(data >> spiBit) & 0x01);
1864 }
1865
1866 return MYKONOS_ERR_OK;
1867 }
1868
1869 /**
1870 * \brief Sets the CLKPLL output frequency.
1871 *
1872 * This code updates the Synth and Loop filter settings based on a VCO
1873 * frequency LUT. The VCO frequency break points for the Synth LUT can be
1874 * found in an array called vcoFreqArrayMhz.
1875 *
1876 * <B>Dependencies</B>
1877 * - device->spiSettings->chipSelectIndex
1878 * - device->spiSettings
1879 * - device->deviceClock_kHz
1880 * - device->rxSettings->rxProfile->vcoFreq_kHz
1881 * - device->rxSettings->rxProfile->clkPllHsDiv
1882 * - device->rxSettings->rxProfile->clkPllVcoDiv
1883 *
1884 * \param device is structure pointer to the MYKONOS data structure containing settings
1885 *
1886 * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
1887 */
MYKONOS_initDigitalClocks(mykonosDevice_t * device)1888 mykonosErr_t MYKONOS_initDigitalClocks(mykonosDevice_t *device)
1889 {
1890 /* RF Synth variables */
1891 /* pull Synth and Loop filter values from a Look Up Table */
1892 uint8_t vcoOutLvl;
1893 uint8_t vcoVaractor; /* [3:0] */
1894 uint8_t vcoBiasRef; /* [2:0] */
1895 uint8_t vcoBiasTcf; /* [1:0] */
1896 uint8_t vcoCalOffset; /* [3:0] */
1897 uint8_t vcoVaractorRef; /* [3:0] */
1898 uint8_t loopFilterIcp; /* Icp[5:0] */
1899 uint8_t loopFilterC2C1; /* C2[3:0],C1[3:0] */
1900 uint8_t loopFilterR1C3; /* R1[3:0],C3[3:0] */
1901 uint8_t loopFilterR3; /* R3[3:0] */
1902 uint8_t vcoIndex;
1903 uint8_t i;
1904
1905 /* RF PLL variables */
1906 uint16_t integerWord;
1907 uint32_t fractionalWord;
1908 uint32_t fractionalRemainder;
1909 uint32_t scaledRefClk_Hz;
1910
1911 /* common */
1912 uint64_t hsDigClk_Hz = 0;
1913 uint32_t scaledRefClk_kHz = 0;
1914 uint8_t deviceClkDiv = 0;
1915 mykonosErr_t retVal = MYKONOS_ERR_OK;
1916
1917 uint8_t clockControl2 = 0;
1918 uint8_t sdmSettings = 0;
1919 uint8_t hsDiv = 4;
1920 uint8_t vcoDiv = 0;
1921 uint8_t vcoDivTimes10 = 10;
1922
1923 /******************RF Synth Section************************/
1924 static const uint8_t icp_46p08[53] = {15, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 27, 27, 28, 29, 30, 31, 32, 33, 32, 33, 32, 33, 33, 34, 27, 28, 29,
1925 29, 30, 39, 29, 30, 31, 31, 30, 31, 31, 32, 30, 31, 31, 32, 32, 31, 31, 32, 32, 33};
1926
1927 static const uint8_t icp_61p44[53] = {13, 13, 13, 14, 15, 16, 16, 17, 18, 19, 20, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 28, 29, 28, 29, 28, 29, 29, 30, 24, 25, 25,
1928 26, 26, 35, 33, 34, 35, 35, 26, 27, 27, 28, 27, 27, 27, 28, 28, 27, 27, 28, 28, 29};
1929
1930 static const uint8_t icp_76p8[53] = {7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 16, 15, 16, 15, 16, 16, 17, 13, 14, 14, 14, 15,
1931 19, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 15, 15, 15, 16, 16};
1932
1933 static const uint32_t vcoFreqArray_kHz[53] = {12605000UL, 12245000UL, 11906000UL, 11588000UL, 11288000UL, 11007000UL, 10742000UL, 10492000UL, 10258000UL, 10036000UL,
1934 9827800UL, 9631100UL, 9445300UL, 9269800UL, 9103600UL, 8946300UL, 8797000UL, 8655300UL, 8520600UL, 8392300UL, 8269900UL, 8153100UL, 8041400UL, 7934400UL,
1935 7831800UL, 7733200UL, 7638400UL, 7547100UL, 7459000UL, 7374000UL, 7291900UL, 7212400UL, 7135500UL, 7061000UL, 6988700UL, 6918600UL, 6850600UL, 6784600UL,
1936 6720500UL, 6658200UL, 6597800UL, 6539200UL, 6482300UL, 6427000UL, 6373400UL, 6321400UL, 6270900UL, 6222000UL, 6174500UL, 6128400UL, 6083600UL, 6040100UL,
1937 5997700UL};
1938
1939 #if (MYKONOS_VERBOSE == 1)
1940 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_initDigitalClocks()\n");
1941 #endif
1942
1943 retVal = MYKONOS_calculateScaledDeviceClk_kHz(device, &scaledRefClk_kHz, &deviceClkDiv);
1944 if (retVal != MYKONOS_ERR_OK)
1945 {
1946 return retVal;
1947 }
1948
1949 hsDiv = device->clocks->clkPllHsDiv;
1950 vcoDiv = device->clocks->clkPllVcoDiv;
1951
1952 switch (hsDiv)
1953 {
1954 case 4:
1955 hsDiv = 4; /* clockControl2[3:2] = 00 */
1956 break;
1957 case 5:
1958 hsDiv = 5;
1959 clockControl2 |= 0x04; /* Set bit[2]=1 */
1960 break;
1961 default:
1962 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_HSDIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_HSDIV));
1963 return MYKONOS_ERR_CLKPLL_INV_HSDIV;
1964 }
1965
1966 switch (vcoDiv)
1967 {
1968 case VCODIV_1:
1969 vcoDivTimes10 = 10; /* clockControl2[1:0] = 00 */
1970 break;
1971 case VCODIV_1p5:
1972 vcoDivTimes10 = 15;
1973 clockControl2 |= 0x01;
1974 break;
1975 case VCODIV_2:
1976 vcoDivTimes10 = 20;
1977 clockControl2 |= 0x02;
1978 break;
1979 case VCODIV_3:
1980 vcoDivTimes10 = 30;
1981 clockControl2 |= 0x03;
1982 break;
1983 default:
1984 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_VCODIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_VCODIV));
1985 return MYKONOS_ERR_CLKPLL_INV_VCODIV;
1986 }
1987
1988 clockControl2 |= ((deviceClkDiv & 3) << 4);
1989
1990 /* find vco table index based on vco frequency */
1991 for (i = 0; device->clocks->clkPllVcoFreq_kHz < vcoFreqArray_kHz[i]; i++)
1992 {
1993 /* Intentionally blank, for loop exits when condition met, index i used below */
1994 }
1995 vcoIndex = i + 1;
1996
1997 if (vcoIndex < 1 || vcoIndex > 53)
1998 {
1999 /* vco index out of range */
2000 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX,
2001 getMykonosErrorMessage(MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX));
2002 return MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX;
2003 }
2004
2005 /* valid for all refclk frequencies */
2006 vcoOutLvl = (vcoIndex <= 16) ? 13 : (vcoIndex <= 23) ? 12 : (vcoIndex <= 25) ?
2007 11 : (vcoIndex <= 35) ? 10 : (vcoIndex <= 39) ? 9 : (vcoIndex <= 43) ?
2008 8 : (vcoIndex <= 48) ? 7 : 6;
2009 vcoVaractor = (vcoIndex <= 29 || vcoIndex == 35) ? 1 : 2;
2010 vcoBiasRef = (vcoIndex <= 7 ) ? 4 : (vcoIndex <= 16) ? 6 : 7;
2011 vcoBiasTcf = (vcoIndex <= 25 || (vcoIndex > 26 && vcoIndex <= 29) ||
2012 (vcoIndex > 37 && vcoIndex <= 39)) || (vcoIndex > 40 && vcoIndex <= 43) ?
2013 2 : 3;
2014
2015 vcoVaractorRef = (vcoIndex <= 29) ? 12 : (vcoIndex == 35) ? 14 : 13;
2016
2017 if ((scaledRefClk_kHz >= 40000) && (scaledRefClk_kHz < 53760))
2018 { /* Settings designed for 46.08 MHz PLL REFCLK */
2019 vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 35 && vcoIndex <= 37) || (vcoIndex > 29 && vcoIndex <= 34)|| vcoIndex == 40 || vcoIndex == 44) ?
2020 14 :(vcoIndex <= 10 || vcoIndex > 44) ?
2021 15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 23) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 23 && vcoIndex <= 25) || vcoIndex == 35) ?
2022 12 : 13;
2023
2024 loopFilterIcp = icp_46p08[vcoIndex - 1];
2025 loopFilterC2C1 = 0xF9; /* C2=0xF0 */
2026 loopFilterR1C3 = 0xD5;
2027 loopFilterR3 = 0x0E;
2028 }
2029 else if ((scaledRefClk_kHz >= 53760) && (scaledRefClk_kHz < 69120))
2030 { /* Settings designed for 61.44 MHz PLL REFCLK */
2031 vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 29 && vcoIndex <= 34) || vcoIndex == 40 || vcoIndex == 44) ?
2032 14 :(vcoIndex <= 10 || vcoIndex > 44) ?
2033 15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 25) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 34 && vcoIndex <= 37)) ?
2034 12 : (vcoIndex > 37 && vcoIndex <= 39) ? 11 : 13;
2035
2036 vcoVaractor = (vcoIndex > 35 && vcoIndex <= 39) ? 1 : vcoVaractor;
2037 vcoBiasRef = (vcoIndex > 4 && vcoIndex <= 7) ? 5 : vcoBiasRef;
2038 vcoVaractorRef = (vcoIndex > 35 && vcoIndex <= 39) ? 14 : vcoVaractorRef;
2039 loopFilterIcp = icp_61p44[vcoIndex-1];
2040 loopFilterC2C1 = ((vcoIndex > 2 && vcoIndex <= 6) || (vcoIndex > 8 && vcoIndex <= 13) || (vcoIndex > 14)) ? 0xFD : 0xFC; /* C2=0xF0 */
2041 loopFilterR1C3 = 0xC5;
2042 loopFilterR3 = (vcoIndex <= 2 || (vcoIndex > 6 && vcoIndex <= 8) || vcoIndex == 14) ? 14 : 13 ;
2043 }
2044 else if ((scaledRefClk_kHz >= 69120) && (scaledRefClk_kHz <= 80000))
2045 { /* Settings designed for 76.8 MHz PLL REFCLK */
2046 vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 35 && vcoIndex <= 37) || (vcoIndex > 29 && vcoIndex <= 34)|| vcoIndex == 40 || vcoIndex == 44) ?
2047 14 :(vcoIndex <= 10 || vcoIndex > 44) ?
2048 15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 23) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 23 && vcoIndex <= 25) || vcoIndex == 35) ?
2049 12 : 13;
2050
2051 loopFilterIcp = icp_76p8[vcoIndex-1];
2052 loopFilterC2C1 = (vcoIndex == 20 ) ? 0xF7 : (vcoIndex == 4 || vcoIndex == 6 || vcoIndex == 8 ) ? 0xE6: 0xF6; /*C2=0xF0, C1=6 or 7 */
2053 loopFilterR1C3 = (vcoIndex == 4 ) ? 0xE4 : 0xD5;
2054 loopFilterR3 = 0x0E;
2055 }
2056 else
2057 {
2058 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_INV_REFCLK, getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_INV_REFCLK));
2059 return MYKONOS_ERR_SETRFPLL_INV_REFCLK; /* invalid ref clk */
2060 }
2061
2062 /* Hold CLKPLL digital logic in reset */
2063 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_4, 0x00);
2064
2065 /* Set reference clock scaler + HSdiv + VCOdiv */
2066 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, clockControl2);
2067
2068 /*Set VCO cal time */
2069 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_CAL_CONTROL, 0x02);
2070
2071 /* Write Synth Setting regs */
2072 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_F_VCOTN_BYTE1, ((vcoCalOffset & 0x0F) << 3)); /* Set VCO Cal offset[3:0] */
2073 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE1, (0xC0 | (vcoVaractor & 0x0F))); /* Init ALC[3:0], VCO varactor[3:0] */
2074 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE2, (0x40 | (vcoOutLvl & 0x0F))); /* VCO output level */
2075 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE9, (((vcoBiasTcf & 0x03) << 3) | (vcoBiasRef & 0x07))); /* Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] */
2076 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_CAL_REF, 0x30); /* Set VCO cal time (compare length) + Set VCO Cal Ref Tcf[2:0]=0 */
2077 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_VAR_CTL1, 0x70); /* Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] */
2078 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_VAR_CTL2, (vcoVaractorRef & 0x0F)); /* Set VCO Varactor Reference[3:0] */
2079
2080 /* Write Loop filter */
2081 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE3, (0x80 | (loopFilterIcp & 0x03F))); /* Set Loop Filter Icp[5:0] */
2082 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE6, loopFilterC2C1); /* Set Loop Filter C2[3:0] and C1[3:0] */
2083 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE7, loopFilterR1C3); /* Set Loop Filter R1[3:0] and C3[3:0] */
2084 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_LF_R3, (loopFilterR3 & 0x0F)); /*Set Loop Filter R3[3:0] */
2085
2086 /* Calculate PLL integer and fractional words with integer math */
2087 scaledRefClk_Hz = scaledRefClk_kHz * 1000;
2088 hsDigClk_Hz = (((uint64_t)(device->clocks->clkPllVcoFreq_kHz) * 10000) / vcoDivTimes10) / hsDiv;
2089 integerWord = (uint16_t)(hsDigClk_Hz / scaledRefClk_Hz);
2090 fractionalRemainder = hsDigClk_Hz % scaledRefClk_Hz;
2091
2092 /* +1 >> 1 is rounding (add .5) */
2093 fractionalWord = ((uint32_t)((((uint64_t)fractionalRemainder * 4177920) / (uint64_t)scaledRefClk_Hz) + 1) >> 1);
2094
2095 /* if fractionalWord rounded up and == PLL modulus, fix it */
2096 if (fractionalWord == 2088960)
2097 {
2098 fractionalWord = 0;
2099 integerWord = integerWord + 1;
2100 }
2101
2102 if (fractionalWord > 0)
2103 { /* in normal case, the fractional word should be zero and SDM bypassed */
2104 CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLKPLL_INV_FRACWORD,
2105 getMykonosErrorMessage(MYKONOS_ERR_SETCLKPLL_INV_FRACWORD));
2106 /* down graded to warning, do not return error code */
2107 //return MYKONOS_ERR_SETCLKPLL_INV_FRACWORD;
2108 sdmSettings = 0x20;
2109 }
2110 else
2111 {
2112 /* Bypass SDM */
2113 sdmSettings = 0xE0;
2114 }
2115
2116 /* Set PLL fractional word[22:0] */
2117 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE0, (fractionalWord & 0xFF));
2118 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE1, ((fractionalWord >> 8) & 0xFF));
2119 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE2, ((fractionalWord >> 16) & 0x7F));
2120
2121 /* Write PLL integer word [7:0] */
2122 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1, (sdmSettings | ((integerWord >> 8) & 0x7)));
2123 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE0, (integerWord & 0xFF));
2124
2125 /* Release PLL from reset, and set start VCO cal bit to 0 */
2126 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_4, 0x80);
2127
2128 /* Power up CLKPLL */
2129 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_0, 0x00);
2130 CMB_wait_ms(200); /* Allow PLL time to power up */
2131
2132 /* Enable Charge pump cal after Charge Pump current set (Icp[5:0]) */
2133 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE5, 0x84);
2134
2135 /* Start VCO Cal */
2136 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_4, 0x81);
2137
2138 return MYKONOS_ERR_OK;
2139 }
2140
2141 /**
2142 * \brief Sets the RF PLL local oscillator frequency (RF carrier frequency).
2143 *
2144 * <B>Dependencies</B>
2145 * - device->spiSettings->chipSelectIndex
2146 * - device->spiSettings
2147 *
2148 * \param device is structure pointer to the MYKONOS data structure containing settings
2149 * \param pllName Name of the PLL to configure
2150 * \param rfPllLoFrequency_Hz Desired RF LO frequency
2151 *
2152 * \return MYKONOS_ERR_OK Function completed successfully
2153 * \return MYKONOS_ERR_SETRFPLL_ARMERROR ARM Command to set RF PLL frequency failed
2154 */
MYKONOS_setRfPllFrequency(mykonosDevice_t * device,mykonosRfPllName_t pllName,uint64_t rfPllLoFrequency_Hz)2155 mykonosErr_t MYKONOS_setRfPllFrequency(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint64_t rfPllLoFrequency_Hz)
2156 {
2157 const uint8_t SETCMD_OPCODE = 0x0A;
2158 const uint8_t SET_PLL_FREQUENCY = 0x63;
2159
2160 mykonosErr_t retVal = MYKONOS_ERR_OK;
2161 uint8_t armData[8] = {0};
2162 uint8_t extData[2] = {0};
2163 uint32_t timeoutMs = 0;
2164 uint8_t cmdStatusByte = 0;
2165
2166 armData[0] = (uint8_t)(rfPllLoFrequency_Hz & 0xFF);
2167 armData[1] = (uint8_t)((rfPllLoFrequency_Hz >> 8) & 0xFF);
2168 armData[2] = (uint8_t)((rfPllLoFrequency_Hz >> 16) & 0xFF);
2169 armData[3] = (uint8_t)((rfPllLoFrequency_Hz >> 24) & 0xFF);
2170 armData[4] = (uint8_t)((rfPllLoFrequency_Hz >> 32) & 0xFF);
2171 armData[5] = (uint8_t)((rfPllLoFrequency_Hz >> 40) & 0xFF);
2172 armData[6] = (uint8_t)((rfPllLoFrequency_Hz >> 48) & 0xFF);
2173 armData[7] = (uint8_t)((rfPllLoFrequency_Hz >> 56) & 0xFF);
2174
2175 /* write 64-bit frequency to ARM memory */
2176 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 8);
2177 if (retVal != MYKONOS_ERR_OK)
2178 {
2179 return retVal;
2180 }
2181
2182 extData[0] = SET_PLL_FREQUENCY;
2183
2184 switch (pllName)
2185 {
2186 case RX_PLL:
2187 extData[1] = 0x00;
2188 break;
2189 case TX_PLL:
2190 extData[1] = 0x01;
2191 break;
2192 case SNIFFER_PLL:
2193 extData[1] = 0x02;
2194 break;
2195 default:
2196 {
2197 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_INV_PLLNAME,
2198 getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_INV_PLLNAME));
2199 return MYKONOS_ERR_SETRFPLL_INV_PLLNAME;
2200 }
2201 }
2202
2203 retVal = MYKONOS_sendArmCommand(device, SETCMD_OPCODE, &extData[0], sizeof(extData));
2204 if (retVal != MYKONOS_ERR_OK)
2205 {
2206 return retVal;
2207 }
2208
2209 timeoutMs = 1000;
2210 retVal = MYKONOS_waitArmCmdStatus(device, SETCMD_OPCODE, timeoutMs, &cmdStatusByte);
2211 if (retVal != MYKONOS_ERR_OK)
2212 {
2213 if (cmdStatusByte > 0)
2214 {
2215 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_ARMERROR, getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_ARMERROR));
2216 return MYKONOS_ERR_SETRFPLL_ARMERROR;
2217 }
2218
2219 return retVal;
2220 }
2221
2222 if (cmdStatusByte > 0)
2223 {
2224 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_ARMERROR, getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_ARMERROR));
2225 return MYKONOS_ERR_SETRFPLL_ARMERROR;
2226 }
2227
2228 return MYKONOS_ERR_OK;
2229 }
2230
2231 /**
2232 * \brief Gets the RF PLL local oscillator frequency (RF carrier frequency).
2233 *
2234 * This function is used to get the RF PLL's frequency. It can get the RX PLL, TX PLL
2235 * Sniffer PLL, and CLKPLL.
2236 *
2237 * <B>Dependencies</B>
2238 * - device->spiSettings->chipSelectIndex
2239 * - device->spiSettings
2240 * - device->clocks->deviceClock_kHz
2241 *
2242 * \param device is structure pointer to the MYKONOS data structure containing settings
2243 * \param pllName Name of the PLL for which to read the frequency
2244 * \param rfPllLoFrequency_Hz RF LO frequency currently set for the PLL specified
2245 *
2246 * \retval MYKONOS_ERR_OK Function completed successfully
2247 * \retval MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV Invalid CLKPLL reference clock divider read from Mykonos device
2248 * \retval MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV Invalid CLKPLL high speed clock divider read from Mykonos device
2249 * \retval MYKONOS_ERR_GETRFPLL_INV_PLLNAME Invalid PLL name, can not get PLL frequency. Use PLL name ENUM.
2250 * \retval MYKONOS_ERR_GETRFPLL_ARMERROR ARM Command to get RF PLL frequency failed
2251 * \retval MYKONOS_ERR_GETRFPLL_NULLPARAM rfPllLoFrequency_Hz function parameter pointer is NULL
2252 */
MYKONOS_getRfPllFrequency(mykonosDevice_t * device,mykonosRfPllName_t pllName,uint64_t * rfPllLoFrequency_Hz)2253 mykonosErr_t MYKONOS_getRfPllFrequency(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint64_t *rfPllLoFrequency_Hz)
2254 {
2255 const uint8_t RFPLL_LO_FREQUENCY = 0x63;
2256
2257 mykonosErr_t retVal = MYKONOS_ERR_OK;
2258 uint8_t armData[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2259 uint8_t extData[2] = {0, 0};
2260 uint32_t timeoutMs = 0;
2261 uint8_t cmdStatusByte = 0;
2262 uint8_t getClkPllFrequency = 0;
2263
2264 uint32_t clkPllIntWord = 0;
2265 uint32_t clkPllFracWord = 0;
2266 uint8_t clkPllRefClkDiv = 0;
2267 uint8_t hsDiv = 0;
2268 uint8_t vcoDivTimes10 = 0;
2269 uint8_t hsDivReg = 0;
2270 uint8_t vcoDivReg = 0;
2271 uint8_t clkPllIntWord7_0 = 0;
2272 uint8_t clkPllIntWord10_8 = 0;
2273 uint8_t clkPllFracWord7_0 = 0;
2274 uint8_t clkPllFracWord15_8 = 0;
2275 uint8_t clkPllFracWord22_16 = 0;
2276 uint64_t refclk_Hz = 0;
2277
2278 extData[0] = RFPLL_LO_FREQUENCY;
2279
2280 switch (pllName)
2281 {
2282 case CLK_PLL:
2283 getClkPllFrequency = 1;
2284 break;
2285 case RX_PLL:
2286 extData[1] = 0x00;
2287 break;
2288 case TX_PLL:
2289 extData[1] = 0x01;
2290 break;
2291 case SNIFFER_PLL:
2292 extData[1] = 0x02;
2293 break;
2294 default:
2295 {
2296 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_INV_PLLNAME,
2297 getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_INV_PLLNAME));
2298 return MYKONOS_ERR_GETRFPLL_INV_PLLNAME;
2299 }
2300 }
2301
2302 if (getClkPllFrequency > 0)
2303 {
2304 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, &hsDivReg, 0x0C, 2);
2305 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, &vcoDivReg, 0x03, 0);
2306 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, &clkPllRefClkDiv, 0x70, 4);
2307
2308 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE0, &clkPllIntWord7_0);
2309 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1, &clkPllIntWord10_8);
2310 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE0, &clkPllFracWord7_0);
2311 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE1, &clkPllFracWord15_8);
2312 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE2, &clkPllFracWord22_16);
2313
2314 clkPllIntWord = (((uint32_t)(clkPllIntWord10_8 & 0x7) << 8) | clkPllIntWord7_0);
2315 clkPllFracWord = (((uint32_t)(clkPllFracWord22_16 & 0x7F) << 16) | ((uint32_t)(clkPllFracWord15_8) << 8) | clkPllFracWord7_0);
2316
2317 switch (clkPllRefClkDiv)
2318 {
2319 case 0:
2320 refclk_Hz = ((uint64_t)device->clocks->deviceClock_kHz * 1000);
2321 break;
2322 case 1:
2323 refclk_Hz = (((uint64_t)device->clocks->deviceClock_kHz * 1000) >> 1);
2324 break; /* div 2 */
2325 case 2:
2326 refclk_Hz = (((uint64_t)device->clocks->deviceClock_kHz * 1000) >> 2);
2327 break; /* div 4 */
2328 case 3:
2329 refclk_Hz = (((uint64_t)device->clocks->deviceClock_kHz * 1000) << 1);
2330 break; /* times 2 */
2331 default:
2332 {
2333 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV,
2334 getMykonosErrorMessage(MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV));
2335 return MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV;
2336 }
2337 }
2338
2339 switch (vcoDivReg)
2340 {
2341 case 0:
2342 vcoDivTimes10 = 10;
2343 break;
2344 case 1:
2345 vcoDivTimes10 = 15;
2346 break;
2347 case 2:
2348 vcoDivTimes10 = 20;
2349 break;
2350 case 3:
2351 vcoDivTimes10 = 30;
2352 break;
2353 default:
2354 {
2355 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV,
2356 getMykonosErrorMessage(MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV));
2357 return MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV;
2358 }
2359 }
2360
2361 switch (hsDivReg)
2362 {
2363 case 0:
2364 hsDiv = 4;
2365 break;
2366 case 1:
2367 hsDiv = 5;
2368 break;
2369 default:
2370 {
2371 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV,
2372 getMykonosErrorMessage(MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV));
2373 return MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV;
2374 }
2375 }
2376
2377 /* round to nearest Hz for fractional word (fractional modulus = 2088960) */
2378 *rfPllLoFrequency_Hz = (uint64_t)(((refclk_Hz * clkPllIntWord) + (((refclk_Hz * clkPllFracWord / 1044480) + 1) >> 1)) * hsDiv * vcoDivTimes10 / 10);
2379 }
2380 else
2381 {
2382 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
2383 if (retVal != MYKONOS_ERR_OK)
2384 {
2385 return retVal;
2386 }
2387
2388 timeoutMs = 1000;
2389 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
2390 if (retVal != MYKONOS_ERR_OK)
2391 {
2392 if (cmdStatusByte > 0)
2393 {
2394 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_ARMERROR,
2395 getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_ARMERROR));
2396 return MYKONOS_ERR_GETRFPLL_ARMERROR;
2397 }
2398
2399 return retVal;
2400 }
2401
2402 /* read 64-bit frequency from ARM memory */
2403 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 8, 1);
2404 if (retVal != MYKONOS_ERR_OK)
2405 {
2406 return retVal;
2407 }
2408
2409 if (cmdStatusByte > 0)
2410 {
2411 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_ARMERROR, getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_ARMERROR));
2412 return MYKONOS_ERR_GETRFPLL_ARMERROR;
2413 }
2414
2415 if (rfPllLoFrequency_Hz == NULL)
2416 {
2417 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_NULLPARAM,
2418 getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_NULLPARAM));
2419 return MYKONOS_ERR_GETRFPLL_NULLPARAM;
2420 }
2421
2422 *rfPllLoFrequency_Hz = (uint64_t)((uint64_t)(armData[0])) | ((uint64_t)(armData[1]) << 8) | ((uint64_t)(armData[2]) << 16) | ((uint64_t)(armData[3]) << 24)
2423 | ((uint64_t)(armData[4]) << 32) | ((uint64_t)(armData[5]) << 40) | ((uint64_t)(armData[6]) << 48) | ((uint64_t)(armData[7]) << 56);
2424 }
2425 return MYKONOS_ERR_OK;
2426 }
2427
2428 /**
2429 * \brief Checks if the PLLs are locked
2430 *
2431 * This function updates the pllLockStatus pointer with a lock status it per
2432 * PLL.
2433 * pllLockStatus[0] = CLKPLL Locked
2434 * pllLockStatus[1] = RX_PLL Locked
2435 * pllLockStatus[2] = TX_PLL Locked
2436 * pllLockStatus[3] = SNIFFER_PLL Locked
2437 * pllLockStatus[4] = CAL_PLL Locked
2438 *
2439 * \param device the Mykonos device data structure
2440 * \param pllLockStatus Lock status bit per PLL
2441 *
2442 * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
2443 */
MYKONOS_checkPllsLockStatus(mykonosDevice_t * device,uint8_t * pllLockStatus)2444 mykonosErr_t MYKONOS_checkPllsLockStatus(mykonosDevice_t *device, uint8_t *pllLockStatus)
2445 {
2446 uint8_t readData = 0;
2447
2448 #if (MYKONOS_VERBOSE == 1)
2449 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_checkPllsLockStatus()\n");
2450 #endif
2451
2452 if (pllLockStatus == NULL)
2453 {
2454 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM,
2455 getMykonosErrorMessage(MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM));
2456 return MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM;
2457 }
2458
2459 *pllLockStatus = 0;
2460
2461 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0);
2462 *pllLockStatus = readData;
2463
2464 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RXSYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0);
2465 *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 1);
2466
2467 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TXSYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0);
2468 *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 2);
2469
2470 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_SNIFF_RXSYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0);
2471 *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 3);
2472
2473 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CALPLL_SDM_CONTROL, &readData, 0x80, 7);
2474 *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 4);
2475
2476 return MYKONOS_ERR_OK;
2477 }
2478
2479 /*
2480 *****************************************************************************
2481 * Shared Data path functions
2482 *****************************************************************************
2483 */
2484
2485 /**
2486 * \brief Sets the digital Tx PFIR SYNC clock divider.
2487 *
2488 * This function is a helper function. It is called automatically in
2489 * MYKONOS_initialize() and should not need to be called by the BBIC.
2490 *
2491 * This function sets the digital clock divider that is used to synchronize the
2492 * Tx PFIR each time the Tx channel power up. The Sync clock must
2493 * be set equal to or slower than the FIR processing clock.
2494 *
2495 * <B>Dependencies</B>
2496 * - device->spiSettings
2497 * - device->spiSettings->chipSelectIndex
2498 * - device->profilesValid
2499 * - device->tx->txProfile->txFir
2500 * - device->tx->txProfile->txFir->numFirCoefs
2501 * - device->tx->txProfile->txFirInterpolation
2502 * - device->tx->txProfile->iqRate_kHz
2503 *
2504 * \param device Pointer to the Mykonos data structure
2505 *
2506 * \retval MYKONOS_ERR_OK Function completed successfully
2507 * \retval MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM: Invalid number of Tx FIR coefficients
2508 * \retval MYKONOS_ERR_TXFIR_INV_NUMROWS Invalid number of PFIR coefficient rows
2509 * \retval MYKONOS_ERR_TXFIR_TAPSEXCEEDED Too many Tx PFIR taps for the IQ sample rate. FIR processing clock can not run fast enough to handle the number of taps
2510 */
MYKONOS_setTxPfirSyncClk(mykonosDevice_t * device)2511 mykonosErr_t MYKONOS_setTxPfirSyncClk(mykonosDevice_t *device)
2512 {
2513 const uint8_t numTapMultiple = 16;
2514 const uint8_t maxNumTaps = 96;
2515 uint8_t effectiveRows = 0;
2516 uint8_t numRows = 0;
2517 uint32_t dpClk_kHz = 0;
2518 uint32_t syncClk_kHz = 0;
2519 uint32_t hsDigClkDiv4or5_kHz = 0;
2520 uint8_t syncDiv = 0;
2521 mykonosErr_t retval = MYKONOS_ERR_OK;
2522
2523 if (((device->profilesValid & TX_PROFILE_VALID) > 0) && (device->tx->txProfile->txFir != NULL))
2524 {
2525 /* Calculate number of FIR rows for number of Taps */
2526 if ((device->tx->txProfile->txFir->numFirCoefs % numTapMultiple == 0) && (device->tx->txProfile->txFir->numFirCoefs > 0)
2527 && (device->tx->txProfile->txFir->numFirCoefs <= maxNumTaps))
2528 {
2529 numRows = (device->tx->txProfile->txFir->numFirCoefs / numTapMultiple);
2530 }
2531 else
2532 {
2533 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM,
2534 getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM));
2535 return MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM;
2536 }
2537
2538 effectiveRows = ((numRows + (device->tx->txProfile->txFirInterpolation - 1)) / device->tx->txProfile->txFirInterpolation);
2539
2540 /* round up to next power of 2 */
2541 switch (effectiveRows)
2542 {
2543 case 1:
2544 effectiveRows = 1;
2545 break;
2546 case 2:
2547 effectiveRows = 2;
2548 break;
2549 case 3: /* fall through */
2550 case 4:
2551 effectiveRows = 4;
2552 break;
2553 case 5: /* fall through */
2554 case 6: /* fall through */
2555 case 7: /* fall through */
2556 case 8:
2557 effectiveRows = 8;
2558 break;
2559 default:
2560 {
2561 /* invalid number of FIR taps */
2562 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_NUMROWS,
2563 getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_NUMROWS));
2564 return MYKONOS_ERR_TXFIR_INV_NUMROWS;
2565 }
2566 }
2567
2568 dpClk_kHz = (device->tx->txProfile->iqRate_kHz * device->tx->txProfile->txInputHbInterpolation * device->tx->txProfile->txFirInterpolation * effectiveRows);
2569
2570 /* FIR DPCLK can only run at max of 500MHz */
2571 if (dpClk_kHz > 500000)
2572 {
2573 /* Max number of Tx PFIR taps exceeded for Tx Profile */
2574 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_TAPSEXCEEDED,
2575 getMykonosErrorMessage(MYKONOS_ERR_TXFIR_TAPSEXCEEDED));
2576 return MYKONOS_ERR_TXFIR_TAPSEXCEEDED;
2577 }
2578
2579 /* SYNC CLOCK is the PFIR output rate / 2 */
2580 syncClk_kHz = device->tx->txProfile->iqRate_kHz * device->tx->txProfile->txFirInterpolation / 2;
2581 if ((retval = MYKONOS_calculateDigitalClocks(device, NULL, &hsDigClkDiv4or5_kHz)) != MYKONOS_ERR_OK)
2582 {
2583 return retval;
2584 }
2585
2586 /* Select correct divider setting for SYNCCLK - must be == syncClk_kHz or slower */
2587 for (syncDiv = 0; syncDiv < 5; syncDiv++)
2588 {
2589 if ((hsDigClkDiv4or5_kHz / (uint32_t)(4 << syncDiv)) <= syncClk_kHz)
2590 {
2591 break;
2592 }
2593 }
2594
2595 /* Write Tx PFIR SYNC Clock divider */
2596 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_5, syncDiv, 0x70, 4);
2597 }
2598
2599 return MYKONOS_ERR_OK;
2600 }
2601
2602 /**
2603 * \brief Sets the digital Rx PFIR SYNC clock divider.
2604 *
2605 * This function is a helper function. It is called automatically in
2606 * MYKONOS_initialize() and should not need to be called by the BBIC.
2607 *
2608 * This function sets the digital clock divider that is used to synchronize the
2609 * Rx/ORx/Sniffer PFIRs each time the channels power up. The Sync clock must
2610 * be set equal to or slower than the slowest Rx/ORx/Sniffer PFIR processing
2611 * clock.
2612 *
2613 * <B>Dependencies</B>
2614 * - device->spiSettings
2615 * - device->spiSettings->chipSelectIndex
2616 * - device->profilesValid
2617 * - device->rx->rxProfile->rxFir
2618 * - device->rx->rxProfile->rxFir->numFirCoefs
2619 * - device->rx->rxProfile->iqRate_kHz
2620 * - device->obsRx->orxProfile->rxFir
2621 * - device->obsRx->orxProfile->rxFir->numFirCoefs
2622 * - device->obsRx->orxProfile->iqRate_kHz
2623 * - device->obsRx->snifferProfile->rxFir
2624 * - device->obsRx->snifferProfile->rxFir->numFirCoefs
2625 * - device->obsRx->snifferProfile->iqRate_kHz
2626 *
2627 * \param device Pointer to the Mykonos data structure
2628 *
2629 * \retval MYKONOS_ERR_OK Function completed successfully
2630 * \retval MYKONOS_ERR_RXFIR_TAPSEXCEEDED ERROR: the number of Rx FIR taps exceeds the number of taps accommodated by the FIR processing clock
2631 * \retval MYKONOS_ERR_ORXFIR_TAPSEXCEEDED ERROR: the number of ORx FIR Taps exceeds the number of taps accommodated by the FIR processing clock
2632 * \retval MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED ERROR: the number of sniffer FIR taps exceeds the number of taps accommodated by the FIR processing clock
2633 */
MYKONOS_setRxPfirSyncClk(mykonosDevice_t * device)2634 mykonosErr_t MYKONOS_setRxPfirSyncClk(mykonosDevice_t *device)
2635 {
2636 uint32_t rxDpClk_kHz = 0;
2637 uint32_t orxDpClk_kHz = 0;
2638 uint32_t snRxDpClk_kHz = 0;
2639 uint32_t slowestIqRate_kHz = 0;
2640 uint32_t syncClk_kHz = 0;
2641 uint8_t effectiveRxNumRows = 0;
2642 uint8_t effectiveOrxNumRows = 0;
2643 uint8_t effectiveSnrxNumRows = 0;
2644
2645 uint32_t hsDigClkDiv4or5_kHz = 0;
2646 uint8_t syncDiv = 0;
2647 mykonosErr_t retval = MYKONOS_ERR_OK;
2648
2649 /**
2650 * Calculate Rx SYNC Clock divider for Rx PFIR. Same Rx SYNC Clock is used
2651 * for Rx, ORx, and Sniffer PFIRs, and must be slow enough to handle the slowest
2652 * PFIR rate.
2653 **/
2654
2655 if (((device->profilesValid & RX_PROFILE_VALID) > 0) && (device->rx->rxProfile->rxFir != NULL))
2656 {
2657 switch (device->rx->rxProfile->rxFir->numFirCoefs)
2658 {
2659 case 24:
2660 effectiveRxNumRows = 1;
2661 break;
2662 case 48:
2663 effectiveRxNumRows = 2;
2664 break;
2665 case 72:
2666 effectiveRxNumRows = 4;
2667 break;
2668 default:
2669 break;
2670 }
2671
2672 rxDpClk_kHz = device->rx->rxProfile->iqRate_kHz * effectiveRxNumRows;
2673
2674 if (rxDpClk_kHz > 500000)
2675 {
2676 /* Max number of Rx PFIR taps exceeded for Profile */
2677 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFIR_TAPSEXCEEDED,
2678 getMykonosErrorMessage(MYKONOS_ERR_RXFIR_TAPSEXCEEDED));
2679 return MYKONOS_ERR_RXFIR_TAPSEXCEEDED;
2680 }
2681
2682 slowestIqRate_kHz = device->rx->rxProfile->iqRate_kHz;
2683 }
2684
2685 if (((device->profilesValid & ORX_PROFILE_VALID) > 0) && (device->obsRx->orxProfile->rxFir != NULL))
2686 {
2687 switch (device->obsRx->orxProfile->rxFir->numFirCoefs)
2688 {
2689 case 24:
2690 effectiveOrxNumRows = 1;
2691 break;
2692 case 48:
2693 effectiveOrxNumRows = 2;
2694 break;
2695 case 72:
2696 effectiveOrxNumRows = 4;
2697 break;
2698 default:
2699 break;
2700 }
2701
2702 orxDpClk_kHz = device->obsRx->orxProfile->iqRate_kHz * effectiveOrxNumRows;
2703
2704 if (orxDpClk_kHz > 500000)
2705 {
2706 /* Max number of ORx PFIR taps exceeded for Profile */
2707 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ORXFIR_TAPSEXCEEDED,
2708 getMykonosErrorMessage(MYKONOS_ERR_ORXFIR_TAPSEXCEEDED));
2709 return MYKONOS_ERR_ORXFIR_TAPSEXCEEDED;
2710 }
2711
2712 if ((slowestIqRate_kHz == 0) || (slowestIqRate_kHz > device->obsRx->orxProfile->iqRate_kHz))
2713 {
2714 slowestIqRate_kHz = device->obsRx->orxProfile->iqRate_kHz;
2715
2716 }
2717 }
2718
2719 if (((device->profilesValid & SNIFF_PROFILE_VALID) > 0) && (device->obsRx->snifferProfile->rxFir != NULL))
2720 {
2721 switch (device->obsRx->snifferProfile->rxFir->numFirCoefs)
2722 {
2723 case 24:
2724 effectiveSnrxNumRows = 1;
2725 break;
2726 case 48:
2727 effectiveSnrxNumRows = 2;
2728 break;
2729 case 72:
2730 effectiveSnrxNumRows = 4;
2731 break;
2732 default:
2733 break;
2734 }
2735
2736 snRxDpClk_kHz = device->obsRx->snifferProfile->iqRate_kHz * effectiveSnrxNumRows;
2737
2738 if (snRxDpClk_kHz > 500000)
2739 {
2740 /* Max number of ORx PFIR taps exceeded for Profile */
2741 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED,
2742 getMykonosErrorMessage(MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED));
2743 return MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED;
2744 }
2745
2746 if ((slowestIqRate_kHz == 0) || (slowestIqRate_kHz > device->obsRx->snifferProfile->iqRate_kHz))
2747 {
2748 slowestIqRate_kHz = device->obsRx->snifferProfile->iqRate_kHz;
2749 }
2750 }
2751
2752 /* SYNC CLOCK should be FIR output rate / 2 */
2753 syncClk_kHz = (slowestIqRate_kHz / 2);
2754 if ((retval = MYKONOS_calculateDigitalClocks(device, NULL, &hsDigClkDiv4or5_kHz)) != MYKONOS_ERR_OK)
2755 {
2756 return retval;
2757 }
2758
2759 /* Select correct divider setting for SYNCCLK - must be == syncClk_kHz or slower */
2760 for (syncDiv = 0; syncDiv < 5; syncDiv++)
2761 {
2762 if ((hsDigClkDiv4or5_kHz / (uint32_t)(4 << syncDiv)) <= syncClk_kHz)
2763 {
2764 break;
2765 }
2766 }
2767
2768 /* Write Rx PFIR SYNC Clock divider */
2769 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_5, syncDiv, 0x07, 0);
2770
2771 return MYKONOS_ERR_OK;
2772 }
2773
2774 /**
2775 * \brief Configures one or more FIR filters in the device
2776 *
2777 * The device stores up to 6 FIR filters (2Rx, 2Obs Rx/Sniffer, and 2Tx).
2778 * Rx filters can have 24, 48, or 72 taps. Tx filters can have 16, 32,
2779 * 48, 64, 80, or 96 taps.
2780 *
2781 * <B>Dependencies</B>
2782 * - device->spiSettings
2783 * - device->spiSettings->chipSelectIndex
2784 *
2785 * \param device Pointer to the Mykonos data structure
2786 * \param filterToProgram Name of the desired filter to program
2787 * \param firFilter Pointer to the filter to write into the device
2788 *
2789 * \retval MYKONOS_ERR_OK Function completed successfully
2790 * \retval MYKONOS_ERR_PROGRAMFIR_NULL_PARM ERROR: firFilter parameter is a NULL pointer
2791 * \retval MYKONOS_ERR_PROGRAMFIR_COEFS_NULL ERROR: firFilter->coefs is a NULL pointer
2792 * \retval MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM ERROR: Invalid FIR filter name in filterToProgram parameter
2793 * \retval MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM ERROR: Invalid number of taps for the filter
2794 * \retval MYKONOS_ERR_RXFIR_INV_GAIN_PARM ERROR: Rx FIR filter has invalid gain setting
2795 * \retval MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM ERROR: OBSRX_A (ORX) FIR filter has invalid gain setting
2796 * \retval MYKONOS_ERR_SRXFIR_INV_GAIN_PARM ERROR: OBSRX_B (Sniffer) FIR filter has invalid gain setting
2797 * \retval MYKONOS_ERR_TXFIR_INV_GAIN_PARM ERROR: Tx FIR filter has invalid gain setting
2798 */
MYKONOS_programFir(mykonosDevice_t * device,mykonosfirName_t filterToProgram,mykonosFir_t * firFilter)2799 mykonosErr_t MYKONOS_programFir(mykonosDevice_t *device, mykonosfirName_t filterToProgram, mykonosFir_t *firFilter)
2800 {
2801 uint8_t filterSelect = 0;
2802 uint8_t i = 0;
2803 uint8_t numTapsReg = 0;
2804 uint8_t numTapMultiple = 24; /* Rx=24, Tx=16 */
2805 uint8_t maxNumTaps = 72; /* Rx=72, Tx=96 */
2806 uint8_t filterGain = 0;
2807
2808 #if MYK_ENABLE_SPIWRITEARRAY == 1
2809 uint32_t addrIndex = 0;
2810 uint32_t dataIndex = 0;
2811 uint32_t spiBufferSize = ((MYK_SPIWRITEARRAY_BUFFERSIZE / 6) * 6); /* Make buffer size a multiple of 6 */
2812 uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0};
2813 uint8_t dataArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0};
2814 #endif
2815
2816 const uint8_t COEF_WRITE_EN = 0x40;
2817 const uint8_t PROGRAM_CLK_EN = 0x80;
2818
2819 #if (MYKONOS_VERBOSE == 1)
2820 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_programFir()\n");
2821 #endif
2822
2823 if (firFilter == NULL)
2824 {
2825 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_NULL_PARM,
2826 getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_NULL_PARM));
2827 return MYKONOS_ERR_PROGRAMFIR_NULL_PARM;
2828 }
2829
2830 if (firFilter->coefs == NULL)
2831 {
2832 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_COEFS_NULL,
2833 getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_COEFS_NULL));
2834 return MYKONOS_ERR_PROGRAMFIR_COEFS_NULL;
2835 }
2836
2837 switch (filterToProgram)
2838 {
2839 case TX1_FIR:
2840 filterSelect = 0x01;
2841 numTapMultiple = 16;
2842 maxNumTaps = 96;
2843 break;
2844 case TX2_FIR:
2845 filterSelect = 0x02;
2846 numTapMultiple = 16;
2847 maxNumTaps = 96;
2848 break;
2849 case TX1TX2_FIR:
2850 filterSelect = 0x03;
2851 numTapMultiple = 16;
2852 maxNumTaps = 96;
2853 break;
2854 case RX1_FIR:
2855 filterSelect = 0x04;
2856 numTapMultiple = 24;
2857 maxNumTaps = 72;
2858 break;
2859 case RX2_FIR:
2860 filterSelect = 0x08;
2861 numTapMultiple = 24;
2862 maxNumTaps = 72;
2863 break;
2864 case RX1RX2_FIR:
2865 filterSelect = 0x0C;
2866 numTapMultiple = 24;
2867 maxNumTaps = 72;
2868 break;
2869 case OBSRX_A_FIR:
2870 filterSelect = 0x10;
2871 numTapMultiple = 24;
2872 maxNumTaps = 72;
2873 break;
2874 case OBSRX_B_FIR:
2875 filterSelect = 0x20;
2876 numTapMultiple = 24;
2877 maxNumTaps = 72;
2878 break;
2879 default:
2880 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM,
2881 getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM));
2882 return MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM;
2883 }
2884
2885 /* Calculate register value for number of Taps */
2886 if ((firFilter->numFirCoefs % numTapMultiple == 0) && (firFilter->numFirCoefs > 0) && (firFilter->numFirCoefs <= maxNumTaps))
2887 {
2888 numTapsReg = (firFilter->numFirCoefs / numTapMultiple) - 1;
2889 }
2890 else
2891 {
2892 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM,
2893 getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM));
2894 return MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM;
2895 }
2896
2897 /* Select which FIR filter to program coeffs for */
2898 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect)); //select filter and enable the programming clock
2899
2900 #if (MYK_ENABLE_SPIWRITEARRAY == 0)
2901
2902 /* write filter coefficients */
2903 for (i = 0; i < firFilter->numFirCoefs; i++)
2904 {
2905 /* Write Low byte of 16bit coefficient */
2906 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, (i * 2));
2907 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, (firFilter->coefs[i] & 0xFF));
2908 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect)); /* write enable (self clearing) */
2909
2910 /* Write High Byte of 16bit coefficient */
2911 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, ((i * 2) + 1));
2912 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, ((firFilter->coefs[i] >> 8) & 0xFF));
2913 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect));/* write enable (self clearing) */
2914 }
2915
2916 #elif (MYK_ENABLE_SPIWRITEARRAY == 1)
2917
2918 addrIndex = 0;
2919 dataIndex = 0;
2920 for (i = 0; i < firFilter->numFirCoefs; i++)
2921 {
2922 addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_ADDR;
2923 addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_DATA;
2924 addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_CTL;
2925 addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_ADDR;
2926 addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_DATA;
2927 addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_CTL;
2928
2929 dataArray[dataIndex++] = (uint8_t)(i * 2);
2930 dataArray[dataIndex++] = (firFilter->coefs[i] & 0xFF);
2931 dataArray[dataIndex++] = (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect);
2932 dataArray[dataIndex++] = (uint8_t)((i * 2) + 1);
2933 dataArray[dataIndex++] = (((uint16_t)firFilter->coefs[i] >> 8) & 0xFF);
2934 dataArray[dataIndex++] = (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect);
2935
2936 /* Send full buffer size when possible */
2937 /* spiBufferSize set to multiple of 6 at top of function */
2938 if (addrIndex >= spiBufferSize)
2939 {
2940 CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex);
2941 dataIndex = 0;
2942 addrIndex = 0;
2943 }
2944 }
2945
2946 if (addrIndex > 0)
2947 {
2948 CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex);
2949 }
2950
2951 #endif
2952
2953 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, filterSelect); /* clear Program clock enable */
2954 /* write filter gain and #taps */
2955 if (filterToProgram == RX1_FIR || filterToProgram == RX2_FIR || filterToProgram == RX1RX2_FIR)
2956 {
2957 /* Write Rx FIR #taps */
2958 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, numTapsReg, 0x60, 5);
2959
2960 /* Set Rx filter gain */
2961 switch (firFilter->gain_dB)
2962 {
2963 case -12:
2964 filterGain = 0x00;
2965 break;
2966 case -6:
2967 filterGain = 0x01;
2968 break;
2969 case 0:
2970 filterGain = 0x02;
2971 break;
2972 case 6:
2973 filterGain = 0x03;
2974 break;
2975 default:
2976 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFIR_INV_GAIN_PARM,
2977 getMykonosErrorMessage(MYKONOS_ERR_RXFIR_INV_GAIN_PARM));
2978 return MYKONOS_ERR_RXFIR_INV_GAIN_PARM;
2979 }
2980
2981 /* Write Rx filter gain */
2982 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_GAIN, filterGain, 0x03, 0);
2983 }
2984 else if (filterToProgram == OBSRX_A_FIR)
2985 {
2986 /* Write Obs Rx FIR A #taps */
2987 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, numTapsReg, 0x06, 1);
2988
2989 /* Set Rx filter gain */
2990 switch (firFilter->gain_dB)
2991 {
2992 case -12:
2993 filterGain = 0x00;
2994 break;
2995 case -6:
2996 filterGain = 0x01;
2997 break;
2998 case 0:
2999 filterGain = 0x02;
3000 break;
3001 case 6:
3002 filterGain = 0x03;
3003 break;
3004 default:
3005 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM,
3006 getMykonosErrorMessage(MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM));
3007 return MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM;
3008 }
3009
3010 /* Write Obs Rx filter gain */
3011 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, filterGain, 0x03, 0);
3012 }
3013 else if (filterToProgram == OBSRX_B_FIR)
3014 {
3015 /* Write Obs Rx FIR B #taps */
3016 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, numTapsReg, 0x18, 3);
3017
3018 /* Set Rx filter gain */
3019 switch (firFilter->gain_dB)
3020 {
3021 case -12:
3022 filterGain = 0x00;
3023 break;
3024 case -6:
3025 filterGain = 0x01;
3026 break;
3027 case 0:
3028 filterGain = 0x02;
3029 break;
3030 case 6:
3031 filterGain = 0x03;
3032 break;
3033 default:
3034 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SRXFIR_INV_GAIN_PARM,
3035 getMykonosErrorMessage(MYKONOS_ERR_SRXFIR_INV_GAIN_PARM));
3036 return MYKONOS_ERR_SRXFIR_INV_GAIN_PARM;
3037 }
3038
3039 /* Write Obs Rx filter gain */
3040 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, filterGain, 0x60, 5);
3041 }
3042 else if (filterToProgram == TX1_FIR || filterToProgram == TX2_FIR || filterToProgram == TX1TX2_FIR)
3043 {
3044 /* Write number of Taps */
3045 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, numTapsReg, 0xE0, 5);
3046
3047 switch (firFilter->gain_dB)
3048 {
3049 case 0:
3050 filterGain = 0;
3051 break;
3052 case 6:
3053 filterGain = 1;
3054 break;
3055 default:
3056 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_GAIN_PARM,
3057 getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_GAIN_PARM));
3058 return MYKONOS_ERR_TXFIR_INV_GAIN_PARM;
3059 }
3060
3061 /* Write Tx Filter gain */
3062 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, filterGain, 0x01, 0);
3063
3064 }
3065
3066 return MYKONOS_ERR_OK;
3067 }
3068
3069 /**
3070 * \brief Reads the FIR filter programmed into the device
3071 *
3072 * The device stores up to 6 FIR filters (2Rx, 2Obs Rx/Sniffer, and 2Tx).
3073 * Rx filters can have 24, 48, or 72 taps. Tx filters can have 16, 32,
3074 * 48, 64, 80, or 96 taps.
3075 *
3076 * <B>Dependencies</B>
3077 * - device->spiSettings
3078 * - device->spiSettings->chipSelectIndex
3079 *
3080 * \param device Pointer to the Mykonos data structure
3081 * \param filterToRead Name of the desired filter to be read
3082 * \param firFilter Pointer to the filter to be read from the device
3083 *
3084 * \retval MYKONOS_ERR_OK Function completed successfully
3085 * \retval MYKONOS_ERR_READFIR_NULL_PARM ERROR: firFilter parameter is a NULL pointer
3086 * \retval MYKONOS_ERR_READFIR_COEFS_NULL ERROR: firFilter->coefs is a NULL pointer
3087 * \retval MYKONOS_ERR_READFIR_INV_FIRNAME_PARM ERROR: Invalid FIR filter name in filterToRead parameter
3088 * \retval MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM ERROR: Invalid number of taps for the filter
3089 * \retval MYKONOS_ERR_RXFIR_INV_GAIN_PARM ERROR: Rx FIR filter has invalid gain setting
3090 * \retval MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM ERROR: OBSRX_A (ORX) FIR filter has invalid gain setting
3091 * \retval MYKONOS_ERR_SRXFIR_INV_GAIN_PARM ERROR: OBSRX_B (Sniffer) FIR filter has invalid gain setting
3092 * \retval MYKONOS_ERR_TXFIR_INV_GAIN_PARM ERROR: Tx FIR filter has invalid gain setting
3093 */
MYKONOS_readFir(mykonosDevice_t * device,mykonosfirName_t filterToRead,mykonosFir_t * firFilter)3094 mykonosErr_t MYKONOS_readFir(mykonosDevice_t *device, mykonosfirName_t filterToRead, mykonosFir_t *firFilter)
3095 {
3096 uint8_t filterSelect = 0;
3097 uint8_t i = 0;
3098 uint8_t numTapsReg = 0;
3099 uint8_t numTapMultiple = 24;
3100 uint8_t maxNumTaps = 72;
3101 uint8_t filterGain = 0;
3102 uint8_t msbRead = 0;
3103 uint8_t lsbRead = 0;
3104
3105 const uint8_t PROGRAM_CLK_EN = 0x80;
3106
3107 #if (MYKONOS_VERBOSE == 1)
3108 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readFir()\n");
3109 #endif
3110
3111 if (firFilter == NULL)
3112 {
3113 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_NULL_PARM, getMykonosErrorMessage(MYKONOS_ERR_READFIR_NULL_PARM));
3114 return MYKONOS_ERR_READFIR_NULL_PARM;
3115 }
3116
3117 if (firFilter->coefs == NULL)
3118 {
3119 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_COEFS_NULL, getMykonosErrorMessage(MYKONOS_ERR_READFIR_COEFS_NULL));
3120 return MYKONOS_ERR_READFIR_COEFS_NULL;
3121 }
3122
3123 switch (filterToRead)
3124 {
3125 case TX1_FIR:
3126 filterSelect = 0x01;
3127 numTapMultiple = 16;
3128 maxNumTaps = 96;
3129 break;
3130 case TX2_FIR:
3131 filterSelect = 0x02;
3132 numTapMultiple = 16;
3133 maxNumTaps = 96;
3134 break;
3135 case TX1TX2_FIR:
3136 filterSelect = 0x03;
3137 numTapMultiple = 16;
3138 maxNumTaps = 96;
3139 break;
3140 case RX1_FIR:
3141 filterSelect = 0x04;
3142 numTapMultiple = 24;
3143 maxNumTaps = 72;
3144 break;
3145 case RX2_FIR:
3146 filterSelect = 0x08;
3147 numTapMultiple = 24;
3148 maxNumTaps = 72;
3149 break;
3150 case RX1RX2_FIR:
3151 filterSelect = 0x0C;
3152 numTapMultiple = 24;
3153 maxNumTaps = 72;
3154 break;
3155 case OBSRX_A_FIR:
3156 filterSelect = 0x10;
3157 numTapMultiple = 24;
3158 maxNumTaps = 72;
3159 break;
3160 case OBSRX_B_FIR:
3161 filterSelect = 0x20;
3162 numTapMultiple = 24;
3163 maxNumTaps = 72;
3164 break;
3165 default:
3166 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_INV_FIRNAME_PARM,
3167 getMykonosErrorMessage(MYKONOS_ERR_READFIR_INV_FIRNAME_PARM));
3168 return MYKONOS_ERR_READFIR_INV_FIRNAME_PARM;
3169 }
3170
3171 /* clear Program clock enable */
3172 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, filterSelect);
3173
3174 /* Read filter gain and #taps */
3175 if (filterToRead == RX1_FIR || filterToRead == RX2_FIR || filterToRead == RX1RX2_FIR)
3176 {
3177 /* Read Rx FIR #taps */
3178 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, &numTapsReg, 0x60, 5);
3179
3180 firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple);
3181
3182 /* Read Rx filter gain */
3183 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_GAIN, &filterGain, 0x03, 0);
3184
3185 switch (filterGain)
3186 {
3187 case 0x00:
3188 firFilter->gain_dB = -12;
3189 break;
3190 case 0x01:
3191 firFilter->gain_dB = -6;
3192 break;
3193 case 0x02:
3194 firFilter->gain_dB = 0;
3195 break;
3196 case 0x03:
3197 firFilter->gain_dB = 6;
3198 break;
3199 default:
3200 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFIR_INV_GAIN_PARM,
3201 getMykonosErrorMessage(MYKONOS_ERR_RXFIR_INV_GAIN_PARM));
3202 return MYKONOS_ERR_RXFIR_INV_GAIN_PARM;
3203 }
3204 }
3205 else if (filterToRead == OBSRX_A_FIR)
3206 {
3207 /* Read Obs Rx FIR A #taps */
3208 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, &numTapsReg, 0x60, 1);
3209
3210 firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple);
3211
3212 /* Read Obs Rx FIR A gain */
3213 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, &filterGain, 0x03, 0);
3214
3215 switch (filterGain)
3216 {
3217 case 0x00:
3218 firFilter->gain_dB = -12;
3219 break;
3220 case 0x01:
3221 firFilter->gain_dB = -6;
3222 break;
3223 case 0x02:
3224 firFilter->gain_dB = 0;
3225 break;
3226 case 0x03:
3227 firFilter->gain_dB = 6;
3228 break;
3229 default:
3230 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM,
3231 getMykonosErrorMessage(MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM));
3232 return MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM;
3233 }
3234 }
3235 else if (filterToRead == OBSRX_B_FIR)
3236 {
3237 /* Read Obs Rx FIR B #taps */
3238 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, &numTapsReg, 0x18, 3);
3239
3240 firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple);
3241
3242 /* Read Obs Rx FIR B gain */
3243 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, &filterGain, 0x60, 5);
3244
3245 switch (filterGain)
3246 {
3247 case 0x00:
3248 firFilter->gain_dB = -12;
3249 break;
3250 case 0x01:
3251 firFilter->gain_dB = -6;
3252 break;
3253 case 0x02:
3254 firFilter->gain_dB = 0;
3255 break;
3256 case 0x03:
3257 firFilter->gain_dB = 6;
3258 break;
3259 default:
3260 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SRXFIR_INV_GAIN_PARM,
3261 getMykonosErrorMessage(MYKONOS_ERR_SRXFIR_INV_GAIN_PARM));
3262 return MYKONOS_ERR_SRXFIR_INV_GAIN_PARM;
3263 }
3264 }
3265 else if (filterToRead == TX1_FIR || filterToRead == TX2_FIR || filterToRead == TX1TX2_FIR)
3266 {
3267 /* Read number of Taps */
3268 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, &numTapsReg, 0xE0, 5);
3269
3270 firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple);
3271
3272 /* Read Tx Filter gain */
3273 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, &filterGain, 0x01, 0);
3274
3275 switch (filterGain)
3276 {
3277 case 0:
3278 firFilter->gain_dB = 0;
3279 break;
3280 case 1:
3281 firFilter->gain_dB = 6;
3282 break;
3283 default:
3284 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_GAIN_PARM,
3285 getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_GAIN_PARM));
3286 return MYKONOS_ERR_TXFIR_INV_GAIN_PARM;
3287 }
3288 }
3289
3290 /* Select which FIR filter to read the coeffs for */
3291 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect)); //select filter and enable the programming clock
3292
3293 if (firFilter->numFirCoefs > maxNumTaps)
3294 {
3295 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM,
3296 getMykonosErrorMessage(MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM));
3297 return MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM;
3298 }
3299
3300 /* write filter coefficients */
3301 for (i = 0; i < firFilter->numFirCoefs; i++)
3302 {
3303 /* Write Low byte of 16bit coefficient */
3304 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, (uint8_t)(i * 2));
3305 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect)); /* write enable (self clearing) */
3306 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, &lsbRead);
3307
3308 /* Write High Byte of 16bit coefficient */
3309 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, (uint8_t)((i * 2) + 1));
3310 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect));/* write enable (self clearing) */
3311 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, &msbRead);
3312
3313 firFilter->coefs[i] = (int16_t)((lsbRead & 0xFF) | ((msbRead << 8) & 0xFF00));
3314 }
3315
3316 return MYKONOS_ERR_OK;
3317 }
3318
3319 /*
3320 *****************************************************************************
3321 * Rx Data path functions
3322 *****************************************************************************
3323 */
3324 /*!
3325 * \brief Programs the gain table settings for either Rx1, Rx2, Rx1 + Rx2, ORx, or SnRx receiver types
3326 *
3327 * The gain table for a receiver type is set with the parameters passed by uint8_t gainTablePtr array.
3328 * gainTablePtr is a 4 x n array, where there are four (4) elements per index, and the array
3329 * length (n) is dependent upon receiver type. The (n) value is conveyed by numGainIndexesInTable.
3330 * All gain tables have a maximum index of 255 when used with this function. The minimum gain index is
3331 * application dependent.
3332 *
3333 * Where for Rx1, Rx2, and ObsRx:
3334 * [A, B, C, D]: A = Front End Gain, B = External Control, C = Digital Attenuation/Gain, D = Attenuation/Gain select
3335 *
3336 * Where for SnRx:
3337 * [A, B, C, D]: A = Front End Gain, B = LNA Bypass, C = Digital Attenuation/Gain, D = Attenuation/Gain select
3338 *
3339 * The gain table starting address changes with each receiver type. This function accounts for this change as well as the
3340 * difference between byte [B] for {Rx1, Rx2, ObsRx} and SnRx receiver array values and programs the correct registers.
3341 *
3342 * <B>Dependencies</B>
3343 * - device->spiSettings->chipSelectIndex
3344 *
3345 * \param device Pointer to the Mykonos data structure
3346 * \param gainTablePtr Pointer to 4 x n array containing gain table program values
3347 * \param numGainIndexesInTable The number of 'n' indices in 4 x n array. A range check is performed to ensure the maximum is not exceeded.
3348 * \param rxChannel mykonosGainTable_t enum type to select either Rx1, Rx2, Rx1 + Rx2, ORx, or SnRx gain table for programming. A
3349 * channel check is performed to ensure a valid selection.
3350 *
3351 * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK if successful, MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL if invalid channel is selected, MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE
3352 * if numGainIndexesInTable exceeds range for selected receiver gain table
3353 */
MYKONOS_programRxGainTable(mykonosDevice_t * device,uint8_t * gainTablePtr,uint8_t numGainIndexesInTable,mykonosGainTable_t rxChannel)3354 mykonosErr_t MYKONOS_programRxGainTable(mykonosDevice_t *device, uint8_t *gainTablePtr, uint8_t numGainIndexesInTable, mykonosGainTable_t rxChannel)
3355 {
3356 uint8_t ctlReg = 0;
3357 uint8_t ch3CtlReg = 0;
3358 uint16_t rxFEGainAddr = 0;
3359 uint16_t rxExtCtlLnaAddr = 0;
3360 uint16_t rxDigGainAttenAddr = 0;
3361 uint16_t rx2FEGainAddr = 0;
3362 uint16_t rx2ExtCtlAddr = 0;
3363 uint16_t rx2DigGainAttenAddr = 0;
3364 uint8_t minGainIndex = 0;
3365 uint8_t startIndex = 0;
3366 int16_t i = 0;
3367 uint16_t tableRowIndex = 0;
3368 uint8_t retFlag = 0;
3369
3370 #if MYK_ENABLE_SPIWRITEARRAY
3371 uint32_t addrIndex = 0;
3372 uint32_t dataIndex = 0;
3373 uint32_t spiBufferSize = (((MYK_SPIWRITEARRAY_BUFFERSIZE / 9) - 1) * 9);
3374 uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0};
3375 uint8_t dataArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0};
3376 #endif
3377
3378 #if (MYKONOS_VERBOSE == 1)
3379 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_programRxGainTable()\n");
3380 #endif
3381
3382 if (gainTablePtr == NULL)
3383 {
3384 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM,
3385 getMykonosErrorMessage(MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM));
3386 return MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM;
3387 }
3388
3389 /* checking range of numGainIndexesInTable against maximums and for valid rxChannel selection */
3390 switch (rxChannel)
3391 {
3392 case RX1_GT:
3393 /* Rx1 max gain index = 255, check is out of range of uint8_t */
3394 break;
3395 case RX2_GT:
3396 /* Rx1 max gain index = 255, check is out of range of uint8_t */
3397 break;
3398 case RX1_RX2_GT:
3399 /* Rx1 max gain index = 255, check is out of range of uint8_t */
3400 break;
3401 case ORX_GT:
3402 if (numGainIndexesInTable > MAX_ORX_GAIN_TABLE_NUMINDEXES)
3403 {
3404 retFlag = 1;
3405 }
3406 break;
3407 case SNRX_GT:
3408 if (numGainIndexesInTable > MAX_SNRX_GAIN_TABLE_NUMINDEXES)
3409 {
3410 retFlag = 1;
3411 }
3412 break;
3413 case LOOPBACK_GT:
3414 if (numGainIndexesInTable > MAX_LOOPBACK_GAIN_TABLE_NUMINDEXES)
3415 {
3416 retFlag = 1;
3417 }
3418 break;
3419 default:
3420 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL,
3421 getMykonosErrorMessage(MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL));
3422 return MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL;
3423 }
3424
3425 if (retFlag)
3426 {
3427 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE,
3428 getMykonosErrorMessage(MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE));
3429 return MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE;
3430 }
3431 else
3432 {
3433 /* calculating minimum gain index value */
3434 minGainIndex = MAX_GAIN_TABLE_INDEX - numGainIndexesInTable + 1;
3435 }
3436
3437 /* forming control register words based on channel select, assigning starting index, and register addressing, also updating max and min gain table indices in structure */
3438 switch (rxChannel)
3439 {
3440 case RX1_GT:
3441 ctlReg = ((uint8_t)rxChannel << 3) | 0x05;
3442 startIndex = START_RX_GAIN_INDEX;
3443 rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_FE_GAIN;
3444 rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_EXT_CTL;
3445 rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_DIG_GAIN;
3446 device->rx->rxGainCtrl->rx1MaxGainIndex = MAX_GAIN_TABLE_INDEX;
3447 device->rx->rxGainCtrl->rx1MinGainIndex = minGainIndex;
3448 break;
3449 case RX2_GT:
3450 ctlReg = ((uint8_t)rxChannel << 3) | 0x05;
3451 startIndex = START_RX_GAIN_INDEX;
3452 rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_FE_GAIN;
3453 rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_EXT_CTL;
3454 rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_DIG_GAIN;
3455 device->rx->rxGainCtrl->rx2MaxGainIndex = MAX_GAIN_TABLE_INDEX;
3456 device->rx->rxGainCtrl->rx2MinGainIndex = minGainIndex;
3457 break;
3458 case RX1_RX2_GT:
3459 ctlReg = ((uint8_t)rxChannel << 3) | 0x05;
3460 startIndex = START_RX_GAIN_INDEX;
3461 rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_FE_GAIN;
3462 rx2FEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_FE_GAIN;
3463 rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_EXT_CTL;
3464 rx2ExtCtlAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_EXT_CTL;
3465 rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_DIG_GAIN;
3466 rx2DigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_DIG_GAIN;
3467 device->rx->rxGainCtrl->rx1MaxGainIndex = MAX_GAIN_TABLE_INDEX;
3468 device->rx->rxGainCtrl->rx1MinGainIndex = minGainIndex;
3469 device->rx->rxGainCtrl->rx2MaxGainIndex = MAX_GAIN_TABLE_INDEX;
3470 device->rx->rxGainCtrl->rx2MinGainIndex = minGainIndex;
3471 break;
3472 case ORX_GT:
3473 ctlReg = 0x05;
3474 ch3CtlReg = 0x08;
3475 startIndex = START_ORX_GAIN_INDEX;
3476 rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_FE_GAIN;
3477 rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_LNA_ENAB;
3478 rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_DIG_GAIN;
3479 device->obsRx->orxGainCtrl->maxGainIndex = MAX_GAIN_TABLE_INDEX;
3480 device->obsRx->orxGainCtrl->minGainIndex = minGainIndex;
3481 break;
3482 case SNRX_GT:
3483 ctlReg = 0x05;
3484 ch3CtlReg = 0x00;
3485 startIndex = START_SNRX_GAIN_INDEX;
3486 rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_FE_GAIN;
3487 rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_LNA_ENAB;
3488 rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_DIG_GAIN;
3489 device->obsRx->snifferGainCtrl->maxGainIndex = MAX_GAIN_TABLE_INDEX;
3490 device->obsRx->snifferGainCtrl->minGainIndex = minGainIndex;
3491 break;
3492 /*case LOOPBACK_GT: Loopback is only for ARM calibrations */
3493 default:
3494 ctlReg = 0x05;
3495 ch3CtlReg = 0x10;
3496 startIndex = START_LOOPBACK_GAIN_INDEX;
3497 rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_FE_GAIN;
3498 rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_LNA_ENAB;
3499 rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_DIG_GAIN;
3500 break;
3501 }
3502
3503 /* starting the gain table clock and read from gain table address bits */
3504 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg);
3505
3506 /* if ORx or Sniffer are selected also writing channel 3 readback bits for ObsRx or Sniffer selection */
3507 if (rxChannel > RX1_RX2_GT)
3508 {
3509 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg);
3510 }
3511
3512 /* programming a table selected by rxChannel enum type */
3513
3514 #if MYK_ENABLE_SPIWRITEARRAY == 0
3515
3516 for(i = startIndex; i >= ((startIndex + 1) - numGainIndexesInTable); i--)
3517 {
3518 tableRowIndex = (uint16_t)(startIndex - i) << 2;
3519
3520 /* set current gain table index (address) */
3521 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_ADDR, i);
3522
3523 /* Set Rx Front End gain[5:0] */
3524 CMB_SPIWriteByte(device->spiSettings, rxFEGainAddr, gainTablePtr[tableRowIndex]);
3525
3526 /* Set external control [5:0] OR LNA bypass if rxChannel == SNRX_GT */
3527 if (rxChannel == SNRX_GT)
3528 {
3529 CMB_SPIWriteByte(device->spiSettings, rxExtCtlLnaAddr, gainTablePtr[tableRowIndex + 1] << 4);
3530 }
3531 else
3532 {
3533 CMB_SPIWriteByte(device->spiSettings, rxExtCtlLnaAddr, gainTablePtr[tableRowIndex + 1]);
3534 }
3535
3536 /* Set digital attenuation/gain[6:0] and set/clear attenuation bit */
3537 CMB_SPIWriteByte(device->spiSettings, rxDigGainAttenAddr, (gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]);
3538
3539 /* repeating gain table settings if Rx1 and Rx2 are selected for Rx2 configuration */
3540 if (rxChannel == RX1_RX2_GT)
3541 {
3542 /* Set Rx Front End gain[5:0] */
3543 CMB_SPIWriteByte(device->spiSettings, rx2FEGainAddr, gainTablePtr[tableRowIndex]);
3544
3545 /* Set external control [5:0] */
3546 CMB_SPIWriteByte(device->spiSettings, rx2ExtCtlAddr, gainTablePtr[tableRowIndex + 1]);
3547
3548 /* Set digital attenuation/gain[6:0] */
3549 CMB_SPIWriteByte(device->spiSettings, rx2DigGainAttenAddr, (gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]);
3550 }
3551
3552 /* setting the write enable depending on rxChannel choice */
3553 if (rxChannel == ORX_GT)
3554 {
3555 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg | 0x02);
3556 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02);
3557 }
3558 else if (rxChannel == SNRX_GT)
3559 {
3560 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg | 0x01);
3561 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02);
3562 }
3563 else if (rxChannel == LOOPBACK_GT)
3564 {
3565 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg | 0x04);
3566 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02);
3567 }
3568 else
3569 {
3570 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02);
3571 }
3572 }
3573
3574 #elif MYK_ENABLE_SPIWRITEARRAY == 1
3575 //#elif 0
3576
3577 addrIndex = 0;
3578 dataIndex = 0;
3579 for(i = startIndex; i >= ((startIndex + 1) - numGainIndexesInTable); i--)
3580 {
3581 tableRowIndex = (uint16_t)(startIndex - (uint8_t)i) << 2;
3582
3583 /* set current gain table index (address) */
3584 addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_ADDR;
3585 dataArray[dataIndex++] = (uint8_t)i;
3586
3587 /* Set Rx Front End gain[5:0] */
3588 addrArray[addrIndex++] = rxFEGainAddr;
3589 dataArray[dataIndex++] = gainTablePtr[tableRowIndex];
3590
3591 /* Set external control [5:0] OR LNA bypass if rxChannel == SNRX_GT */
3592 addrArray[addrIndex++] = rxExtCtlLnaAddr;
3593 dataArray[dataIndex++] = (rxChannel == SNRX_GT) ? (uint8_t)(gainTablePtr[tableRowIndex + 1] << 4) : (gainTablePtr[tableRowIndex + 1]);
3594
3595 /* Set digital attenuation/gain[6:0] and set/clear attenuation bit */
3596 addrArray[addrIndex++] = rxDigGainAttenAddr;
3597 dataArray[dataIndex++] = ((uint8_t)(gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]);
3598
3599 /* repeating gain table settings if Rx1 and Rx2 are selected for Rx2 configuration */
3600 if (rxChannel == RX1_RX2_GT)
3601 {
3602 /* Set Rx Front End gain[5:0] */
3603 addrArray[addrIndex++] = rx2FEGainAddr;
3604 dataArray[dataIndex++] = gainTablePtr[tableRowIndex];
3605
3606 /* Set external control [5:0] */
3607 addrArray[addrIndex++] = rx2ExtCtlAddr;
3608 dataArray[dataIndex++] = gainTablePtr[tableRowIndex + 1];
3609
3610 /* Set digital attenuation/gain[6:0] */
3611 addrArray[addrIndex++] = rx2DigGainAttenAddr;
3612 dataArray[dataIndex++] = ((uint8_t)(gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]);
3613 }
3614
3615 /* setting the write enable depending on rxChannel choice */
3616 if (rxChannel == ORX_GT)
3617 {
3618 addrArray[addrIndex++] = MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION;
3619 dataArray[dataIndex++] = (ch3CtlReg | 0x02);
3620 addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION;
3621 dataArray[dataIndex++] = (ctlReg | 0x02);
3622 }
3623 else if (rxChannel == SNRX_GT)
3624 {
3625 addrArray[addrIndex++] = MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION;
3626 dataArray[dataIndex++] = (ch3CtlReg | 0x01);
3627 addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION;
3628 dataArray[dataIndex++] = (ctlReg | 0x02);
3629 }
3630 else if (rxChannel == LOOPBACK_GT)
3631 {
3632 addrArray[addrIndex++] = MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION;
3633 dataArray[dataIndex++] = (ch3CtlReg | 0x04);
3634 addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION;
3635 dataArray[dataIndex++] = (ctlReg | 0x02);
3636 }
3637 else
3638 {
3639 addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION;
3640 dataArray[dataIndex++] = (ctlReg | 0x02);
3641 }
3642
3643 if (addrIndex >= spiBufferSize)
3644 {
3645 CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex);
3646 dataIndex = 0;
3647 addrIndex = 0;
3648 }
3649 }
3650
3651 if (addrIndex > 0)
3652 {
3653 CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex);
3654 }
3655
3656 #endif
3657
3658 /* clearing the channel 3 gain table configuration register if selected and stopping the gain table clock */
3659 if (rxChannel > RX1_RX2_GT)
3660 {
3661 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, 0x00);
3662 }
3663 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, 0x08);
3664
3665 return MYKONOS_ERR_OK;
3666 }
3667
3668 /**
3669 * \brief Sets the Rx1 Manual Gain Index
3670 *
3671 * If the value passed in the gainIndex parameter is within range of the gain table minimum and
3672 * maximum indexes, the Rx1 gain index will be updated in the device data structure
3673 * and written to the transceiver. Else, an error will be returned. The maximum index is 255
3674 * and the minimum index is application specific.
3675 *
3676 * <B>Dependencies</B>
3677 * - device->spiSettings
3678 * - device->rxSettings->rxGainControl->rx1GainIndex
3679 * - device->rxSettings->rxGainControl->rx1MaxGainIndex
3680 * - device->rxSettings->rxGainControl->rx1MinGainIndex
3681 *
3682 * \param device Pointer to the Mykonos data structure
3683 * \param gainIndex Desired Rx1 gain index
3684 *
3685 * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
3686 */
MYKONOS_setRx1ManualGain(mykonosDevice_t * device,uint8_t gainIndex)3687 mykonosErr_t MYKONOS_setRx1ManualGain(mykonosDevice_t *device, uint8_t gainIndex)
3688 {
3689
3690 #if (MYKONOS_VERBOSE == 1)
3691 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx1ManualGain()\n");
3692 #endif
3693
3694 if ((gainIndex < device->rx->rxGainCtrl->rx1MinGainIndex) || (gainIndex > device->rx->rxGainCtrl->rx1MaxGainIndex))
3695 {
3696 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM,
3697 getMykonosErrorMessage(MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM));
3698 return MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM;
3699
3700 }
3701 else
3702 {
3703 /* If the desired gain index is in range of the gain table, update the
3704 * value in the device data structure, and write to device.
3705 */
3706 device->rx->rxGainCtrl->rx1GainIndex = gainIndex;
3707
3708 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_INDEX_CH_1, gainIndex);
3709
3710 return MYKONOS_ERR_OK;
3711 }
3712 }
3713
3714 /**
3715 * \brief Sets the Rx2 Manual Gain index
3716 *
3717 * If the value passed in the gainIndex parameter is within range of the gain table minimum and
3718 * maximum indexes, the Rx2 gain index will be updated in the device data structure
3719 * and written to the transceiver. Else, an error will be returned. The maximum index is 255
3720 * and the minimum index is application specific.
3721 *
3722 * <B>Dependencies</B>
3723 * - device->spiSettings
3724 * - device->rxTxSettings->rxGainControl->rx2GainIndex
3725 * - device->rxTxSettings->rxGainControl->rx2MaxGainIndex
3726 * - device->rxTxSettings->rxGainControl->rx2MinGainIndex
3727 *
3728 * \param device Pointer to the Mykonos data structure
3729 * \param gainIndex Desired Rx2 gain index
3730 *
3731 * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
3732 */
MYKONOS_setRx2ManualGain(mykonosDevice_t * device,uint8_t gainIndex)3733 mykonosErr_t MYKONOS_setRx2ManualGain(mykonosDevice_t *device, uint8_t gainIndex)
3734 {
3735
3736 #if (MYKONOS_VERBOSE == 1)
3737 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx2ManualGain()\n");
3738 #endif
3739
3740 if ((gainIndex < device->rx->rxGainCtrl->rx2MinGainIndex) || (gainIndex > device->rx->rxGainCtrl->rx2MaxGainIndex))
3741 {
3742 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM,
3743 getMykonosErrorMessage(MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM));
3744 return MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM;
3745
3746 }
3747 else
3748 {
3749 /* If the desired gain index is in range of the gain table, update the
3750 * value in the device data structure, and write to device.
3751 */
3752 device->rx->rxGainCtrl->rx2GainIndex = gainIndex;
3753
3754 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_INDEX_CH_2, gainIndex);
3755
3756 return MYKONOS_ERR_OK;
3757 }
3758 }
3759
3760 /**
3761 * \brief Reads the Rx1 Gain Index for Manual or AGC gain control mode
3762 *
3763 * This function reads the Rx1 gain index for manual or AGC modes. If the
3764 * *rx1GainIndex pointer is nonzero, the read back gain index will
3765 * be returned in the parameter. If the *rx1GainIndex pointer
3766 * is NULL, the device data structure will be updated with the new read back value
3767 *
3768 * <B>Dependencies</B>
3769 * - device->spiSettings
3770 * - device->rxTxSettings->rxGainControl->rx1GainIndex
3771 *
3772 * \param device Pointer to the Mykonos data structure
3773 * \param rx1GainIndex uint8_t Pointer to the Rx1 gain index value
3774 *
3775 * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
3776 */
MYKONOS_getRx1Gain(mykonosDevice_t * device,uint8_t * rx1GainIndex)3777 mykonosErr_t MYKONOS_getRx1Gain(mykonosDevice_t *device, uint8_t *rx1GainIndex)
3778 {
3779 uint8_t readData = 0;
3780
3781 #if (MYKONOS_VERBOSE == 1)
3782 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx1Gain()\n");
3783 #endif
3784
3785 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GAIN_CTL_CHANNEL_1, &readData);
3786
3787 /*
3788 * If rx1GainIndex address is not NULL, return the Rx1 gain index in the
3789 * rx1GainIndex function parameter
3790 */
3791 if (rx1GainIndex != NULL)
3792 {
3793 *rx1GainIndex = readData;
3794 }
3795
3796 /*
3797 * set the current Rx1 gain in the device data structure
3798 */
3799 if (device->profilesValid & RX_PROFILE_VALID)
3800 {
3801 device->rx->rxGainCtrl->rx1GainIndex = readData;
3802 }
3803
3804 return MYKONOS_ERR_OK;
3805 }
3806
3807 /**
3808 * \brief Reads the Rx2 Gain Index for Manual or AGC gain control mode
3809 *
3810 * This function reads the Rx2 gain index for manual or AGC modes. If the
3811 * *rx1GainIndex pointer is nonzero, the read back gain index will
3812 * be returned in the parameter. If the *rx1GainIndex pointer
3813 * is NULL, the device data structure will be updated with the new read back value
3814 *
3815 * <B>Dependencies</B>
3816 * - device->spiSettings
3817 * - device->rxTxSettings->rxGainControl->rx2GainIndex
3818 *
3819 * \param device Pointer to the Mykonos data structure
3820 * \param rx2GainIndex Desired Rx2 gain index
3821 *
3822 * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail
3823 */
MYKONOS_getRx2Gain(mykonosDevice_t * device,uint8_t * rx2GainIndex)3824 mykonosErr_t MYKONOS_getRx2Gain(mykonosDevice_t *device, uint8_t *rx2GainIndex)
3825 {
3826 uint8_t readData = 0;
3827
3828 #if (MYKONOS_VERBOSE == 1)
3829 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx2Gain()\n");
3830 #endif
3831
3832 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GAIN_CTL_CHANNEL_2, &readData);
3833
3834 /*
3835 * If rx1GainIndex address is not NULL, return the Rx1 gain index in the
3836 * rx1GainIndex function parameter
3837 */
3838 if (rx2GainIndex != NULL)
3839 {
3840 *rx2GainIndex = readData;
3841 }
3842
3843 /*
3844 * set the current Rx2 gain in the device data structure
3845 */
3846 if (device->profilesValid & RX_PROFILE_VALID)
3847 {
3848 device->rx->rxGainCtrl->rx2GainIndex = readData;
3849 }
3850
3851 return MYKONOS_ERR_OK;
3852 }
3853
3854 /**
3855 * \brief Sets up the device Rx Automatic Gain Control (AGC) registers.
3856 *
3857 * Three data structures (mykonosAgcCfg_t, mykonosPeakDetAgcCfg_t, mykonosPowerMeasAgcCfg_t)
3858 * must be instantiated prior to calling this function. Valid ranges for data structure members
3859 * must also be provided.
3860 *
3861 *
3862 * <B>Dependencies:</B>
3863 * - device->spiSettings
3864 * - device->spiSettings->chipSelectIndex
3865 * - device->rx->rxAgcCtrl->agcRx1MaxGainIndex
3866 * - device->rx->rxAgcCtrl->agcRx1MinGainIndex
3867 * - device->rx->rxAgcCtrl->agcRx2MaxGainIndex
3868 * - device->rx->rxAgcCtrl->agcRx2MinGainIndex
3869 * - device->rx->rxAgcCtrl->agcObsRxMaxGainIndex
3870 * - device->rx->rxAgcCtrl->agcObsRxMinGainIndex
3871 * - device->rx->rxAgcCtrl->agcObsRxSelect
3872 * - device->rx->rxAgcCtrl->agcPeakThresholdMode
3873 * - device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease
3874 * - device->rx->rxAgcCtrl->agcGainUpdateCounter
3875 * - device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay
3876 * - device->rx->rxAgcCtrl->agcPeakWaitTime
3877 * - device->rx->rxAgcCtrl->agcResetOnRxEnable
3878 * - device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter
3879 * - device->rx->rxAgcCtrl->peakAgc->apdHighThresh
3880 * - device->rx->rxAgcCtrl->peakAgc->apdLowThresh
3881 * - device->rx->rxAgcCtrl->peakAgc->hb2HighThresh
3882 * - device->rx->rxAgcCtrl->peakAgc->hb2LowThresh
3883 * - device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh
3884 * - device->rx->rxAgcCtrl->peakAgc->apdHighThreshExceededCnt
3885 * - device->rx->rxAgcCtrl->peakAgc->apdLowThreshExceededCnt
3886 * - device->rx->rxAgcCtrl->peakAgc->hb2HighThreshExceededCnt
3887 * - device->rx->rxAgcCtrl->peakAgc->hb2LowThreshExceededCnt
3888 * - device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt
3889 * - device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack
3890 * - device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery
3891 * - device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack
3892 * - device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery
3893 * - device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery
3894 * - device->rx->rxAgcCtrl->peakAgc->apdFastAttack
3895 * - device->rx->rxAgcCtrl->peakAgc->hb2FastAttack
3896 * - device->rx->rxAgcCtrl->peakAgc->hb2OverloadDetectEnable
3897 * - device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt
3898 * - device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt
3899 * - device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh
3900 * - device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh
3901 * - device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh
3902 * - device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh
3903 * - device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack
3904 * - device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack
3905 * - device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery
3906 * - device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery
3907 * - device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration
3908 * - device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig
3909 *
3910 * \param device is structure pointer to the Mykonos data structure containing settings
3911 * The pointer to the Mykonos AGC data structure containing settings is checked for a null pointer
3912 * to ensure it has been initialized. If not an error is thrown.
3913 *
3914 * \retval Returns MYKONOS_ERR=pass, !MYKONOS_ERR=fail
3915 * \retval MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT
3916 * \retval MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT
3917 * \retval MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT
3918 * \retval MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX
3919 * \retval MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX
3920 * \retval MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX
3921 * \retval MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX
3922 * \retval MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM
3923 * \retval MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM
3924 * \retval MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY
3925 * \retval MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION
3926 * \retval MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG
3927 * \retval MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC
3928 * \retval MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE
3929 * \retval MYKONOS_ERR_INV_AGC_RX_RESET_ON_RX_ENABLE
3930 * \retval MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER
3931 * \retval MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH
3932 * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH
3933 * \retval MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH
3934 * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH
3935 * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP
3936 * \retval MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP
3937 * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP
3938 * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP
3939 * \retval MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE
3940 * \retval MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM
3941 * \retval MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM
3942 * \retval MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM
3943 * \retval MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM
3944 * \retval MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM
3945 * \retval MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM
3946 * \retval MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM
3947 * \retval MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM
3948 * \retval MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM
3949 * \retval MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM
3950 * \retval MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE
3951 * \retval MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT
3952 * \retval MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT
3953 */
MYKONOS_setupRxAgc(mykonosDevice_t * device)3954 mykonosErr_t MYKONOS_setupRxAgc(mykonosDevice_t *device)
3955 {
3956 uint8_t decPowerConfig = 0;
3957 uint8_t lower1ThreshGainStepRegValue = 0;
3958 uint8_t powerThresholdsRegValue = 0;
3959 uint8_t hb2OvldCfgRegValue = 0;
3960 uint8_t agcGainUpdateCtr[3] = {0};
3961
3962 #if (MYKONOS_VERBOSE == 1)
3963 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxAgc()\n");
3964 #endif
3965
3966 /* Check mykonosAgcCfg_t device->rx->rxAgcCtrl pointer for initialization */
3967 if (device->rx->rxAgcCtrl == NULL)
3968 {
3969 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT,
3970 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT));
3971 return MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT;
3972 }
3973
3974 /* Check mykonosPeakDetAgcCfg_t device->rx->rxAgcCtrl->peakAgc pointer for initialization */
3975 if (device->rx->rxAgcCtrl->peakAgc == NULL)
3976 {
3977 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT,
3978 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT));
3979 return MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT;
3980 }
3981
3982 /* Check mykonosPowerMeasAgcCfg_t device->rx->rxAgcCtrl->powerAgc pointer for initialization */
3983 if (device->rx->rxAgcCtrl->powerAgc == NULL)
3984 {
3985 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT,
3986 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT));
3987 return MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT;
3988 }
3989
3990 /* Range check agcRx1MaxGainIndex versus gain table limits */
3991 if ((device->rx->rxAgcCtrl->agcRx1MaxGainIndex > device->rx->rxGainCtrl->rx1MaxGainIndex)
3992 || (device->rx->rxAgcCtrl->agcRx1MaxGainIndex < device->rx->rxAgcCtrl->agcRx1MinGainIndex))
3993
3994 {
3995 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX,
3996 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX));
3997 return MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX;
3998 }
3999 else
4000 {
4001 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MAX_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx1MaxGainIndex);
4002 }
4003
4004 /* Range check agcRx1MinGainIndex versus gain table limits */
4005 if ((device->rx->rxAgcCtrl->agcRx1MinGainIndex < device->rx->rxGainCtrl->rx1MinGainIndex)
4006 || (device->rx->rxAgcCtrl->agcRx1MaxGainIndex < device->rx->rxAgcCtrl->agcRx1MinGainIndex))
4007 {
4008 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX,
4009 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX));
4010 return MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX;
4011 }
4012 else
4013 {
4014 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MIN_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx1MinGainIndex);
4015 }
4016
4017 /* Range check agcRx2MaxGainIndex versus gain table limits */
4018 if ((device->rx->rxAgcCtrl->agcRx2MaxGainIndex > device->rx->rxGainCtrl->rx2MaxGainIndex)
4019 || (device->rx->rxAgcCtrl->agcRx2MaxGainIndex < device->rx->rxAgcCtrl->agcRx2MinGainIndex))
4020 {
4021 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX,
4022 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX));
4023 return MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX;
4024 }
4025 else
4026 {
4027 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MAX_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx2MaxGainIndex);
4028 }
4029
4030 /* Range check agcRx2MinGainIndex versus gain table limits */
4031 if ((device->rx->rxAgcCtrl->agcRx2MinGainIndex < device->rx->rxGainCtrl->rx2MinGainIndex)
4032 || (device->rx->rxAgcCtrl->agcRx2MaxGainIndex < device->rx->rxAgcCtrl->agcRx2MinGainIndex))
4033 {
4034 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX,
4035 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX));
4036 return MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX;
4037 }
4038 else
4039 {
4040 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MIN_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx2MinGainIndex);
4041 }
4042
4043 /* Range check for agcGainUpdateCounter (22-bit) */
4044 if ((device->rx->rxAgcCtrl->agcGainUpdateCounter > 0x3FFFFF) || (device->rx->rxAgcCtrl->agcGainUpdateCounter < 1))
4045 {
4046 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM,
4047 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM));
4048 return MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM;
4049 }
4050 else
4051 {
4052 /* Split agcGainUpdateCounter into three values */
4053 agcGainUpdateCtr[0] = (uint8_t)(device->rx->rxAgcCtrl->agcGainUpdateCounter);
4054 agcGainUpdateCtr[1] = (uint8_t)(device->rx->rxAgcCtrl->agcGainUpdateCounter >> 8);
4055 agcGainUpdateCtr[2] = (uint8_t)(device->rx->rxAgcCtrl->agcGainUpdateCounter >> 16);
4056
4057 /* Write two bytes directly due. Third word has its upper two bits masked off. */
4058 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_1, agcGainUpdateCtr[0]);
4059 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_2, agcGainUpdateCtr[1]);
4060 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_3, agcGainUpdateCtr[2], 0x3F, 0);
4061 }
4062
4063 /* Range check on agcPeakWaitTime (5-bit) */
4064 if (device->rx->rxAgcCtrl->agcPeakWaitTime > 0x1F || device->rx->rxAgcCtrl->agcPeakWaitTime < 0x02)
4065 {
4066 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM,
4067 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM));
4068 return MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM;
4069 }
4070 else
4071 {
4072 /* Write agcPeakWaitTime */
4073 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, device->rx->rxAgcCtrl->agcPeakWaitTime, 0x1F, 0);
4074 }
4075
4076 /* Set MYKONOS_ADDR_AGC_CFG_2 bits [6:5] = b11 to enable AGC counters for MGC mode - needed for ARM cals to work correctly */
4077 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, 3, 0x60, 5);
4078
4079 /* Range check for agcSlowLoopSettlingDelay (7-bit) */
4080 if (device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay > 0x7F)
4081 {
4082 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY,
4083 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY));
4084 return MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY;
4085 }
4086 else
4087 {
4088 /* Write agcSlowLoopSettlingDelay */
4089 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOOP_CFG, device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay, 0x7F, 0);
4090 }
4091
4092 /* Range check for pmdMeasDuration */
4093 if ((uint32_t)(1 << (3 + device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration)) >= (device->rx->rxAgcCtrl->agcGainUpdateCounter))
4094 {
4095 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION,
4096 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION));
4097 return MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION;
4098 }
4099 else
4100 {
4101 /* Write pmdMeasDuration */
4102 CMB_SPIWriteField(device->spiSettings, MYKONOS_DEC_POWER_CONFIG_2, device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration, 0x0F, 0);
4103 }
4104
4105 /* Range check for pmdMeasConfig */
4106 if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig > 0x3)
4107 {
4108 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG,
4109 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG));
4110 return MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG;
4111 }
4112 else
4113 {
4114 if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 0)
4115 {
4116 decPowerConfig = 0x0; /* Dec Pwr measurement disable */
4117 }
4118 else if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 1)
4119 {
4120 decPowerConfig = 0x3; /* Dec Pwr measurement enable, HB2 for decPwr measurement */
4121 }
4122 else if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 2)
4123 {
4124 decPowerConfig = 0x5; /* Dec Pwr measurement enable, RFIR for decPwr measurement */
4125 }
4126 else if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 3)
4127 {
4128 decPowerConfig = 0x11; /* Dec Pwr measurement enable, BBDC2 for decPwr measurement */
4129 }
4130 /* Write pmdMeasConfig */
4131 CMB_SPIWriteByte(device->spiSettings, MYKONOS_DEC_POWER_CONFIG_1, decPowerConfig);
4132 }
4133
4134 /* Range check agcLowThsPreventGainIncrease (1-bit) */
4135 if (device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease > 1)
4136 {
4137 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC,
4138 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC));
4139 return MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC;
4140 }
4141 else
4142 {
4143 /* Write agcLowThsPreventGainIncrease */
4144 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOCK_LEV_THRSH, device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease, 0x80, 7);
4145 }
4146
4147 /* Range check agcPeakThresholdMode (1-bit), */
4148 if (device->rx->rxAgcCtrl->agcPeakThresholdMode > 1)
4149 {
4150 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE,
4151 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE));
4152 return MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE;
4153 }
4154 else
4155 {
4156 /* Save to lower1ThreshGainStepRegValue register variable */
4157 lower1ThreshGainStepRegValue |= (uint8_t)(device->rx->rxAgcCtrl->agcPeakThresholdMode << 5);
4158 }
4159
4160 /* Range check agcResetOnRxEnable (1-bit) */
4161 if (device->rx->rxAgcCtrl->agcResetOnRxEnable > 1)
4162 {
4163 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC,
4164 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC));
4165 return MYKONOS_ERR_INV_AGC_RX_RESET_ON_RX_ENABLE;
4166 }
4167 else
4168 {
4169 /* Write agcResetOnRxEnable */
4170 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_3, (uint8_t)(device->rx->rxAgcCtrl->agcResetOnRxEnable << 7), 0x80, 0);
4171 }
4172
4173 /* Range check agcEnableSyncPulseForGainCounter (1-bit) */
4174 if (device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter > 1)
4175 {
4176 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER,
4177 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER));
4178 return MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER;
4179 }
4180 else
4181 {
4182 /* Write agcEnableSyncPulseForGainCounter */
4183 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOOP_CFG, (uint8_t)(device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter << 7), 0x80, 0);
4184 }
4185
4186 /* WRITE REGISTERS FOR THE AGC POWER MEASUREMENT DETECTOR (PMD) STRUCTURE */
4187
4188 /* Range check pmdLowerHighThresh (7-bit) vs 0x7F and pmdUpperLowThresh */
4189 if ((device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh <= device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh)
4190 || device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh > 0x7F)
4191 {
4192 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH,
4193 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH));
4194 return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH;
4195 }
4196 else
4197 {
4198 /* Write pmdLowerHighThresh */
4199 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOCK_LEV_THRSH, device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh, 0x7F, 0);
4200 }
4201
4202 /* Range check pmdUpperLowThresh (7-bit): Comparison to pmdLowerHigh done earlier */
4203 if (device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh > 0x7F)
4204 {
4205 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH,
4206 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH));
4207 return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH;
4208 }
4209 else
4210 {
4211 /* Write pmdUpperLowThresh */
4212 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_LOCK_LEVEL, device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh);
4213 }
4214
4215 /* Range check pmdLowerLowThresh (4-bit) */
4216 if (device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh > 0xF)
4217 {
4218 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH,
4219 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH));
4220 return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH;
4221 }
4222 else
4223 {
4224 /* Write pmdUpperLowThresh to temp variable */
4225 powerThresholdsRegValue |= device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh;
4226 }
4227
4228 /* Range check pmdUpperHighThresh (4-bit) */
4229 if (device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh > 0xF)
4230 {
4231 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH,
4232 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH));
4233 return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH;
4234 }
4235 else
4236 {
4237 /* Write pmdUpperHighThresh to temp var, then to register */
4238 powerThresholdsRegValue |= (uint8_t)(device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh << 4);
4239 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_POWER_THRSH, powerThresholdsRegValue);
4240 }
4241
4242 /* Range check pmdUpperHighGainStepAttack (5-bit) */
4243 if (device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack > 0x1F)
4244 {
4245 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP,
4246 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP));
4247 return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP;
4248 }
4249 else
4250 {
4251 /* Write pmdUpperHighGainStepAttack */
4252 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_UPPER1_THRSH_GAIN_STEP, device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack, 0x1F, 0);
4253 }
4254
4255 /* Range check pmdLowerLowGainStepRecovery (5-bit) */
4256 if (device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery > 0x1F)
4257 {
4258 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP,
4259 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP));
4260 return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP;
4261 }
4262 else
4263 {
4264 /* Write pmdLowerLowGainStepRecovery to temp var, then to register */
4265 lower1ThreshGainStepRegValue |= (device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery);
4266 }
4267
4268 /* Range check pmdUpperLowGainStepRecovery (5-bit) */
4269 if (device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack > 0x1F)
4270 {
4271 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP,
4272 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP));
4273 return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP;
4274 }
4275 else
4276 {
4277 /* Write pmdLowerLowGainStepRecovery to temp var, then to register */
4278 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_UPPER0_THRSH_GAIN_STEP, device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack);
4279 }
4280
4281 /* Range check pmdLowerHighGainStepRecovery (5-bit) */
4282 if (device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery > 0x1F)
4283 {
4284 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP,
4285 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP));
4286 return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP;
4287 }
4288 else
4289 {
4290 /* Write pmdLowerLowGainStepRecovery to temp var, then to register */
4291 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOWER0_THRSH_GAIN_STEP, device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery);
4292 }
4293
4294 /* WRITE REGISTERS FOR THE AGC PEAK DETECTOR (APD/HB2) STRUCTURE */
4295
4296 /* Range check apdFastAttack and hb2FastAttack (1-bit) */
4297 if (device->rx->rxAgcCtrl->peakAgc->apdFastAttack > 0x1 || device->rx->rxAgcCtrl->peakAgc->hb2FastAttack > 0x1)
4298 {
4299 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE,
4300 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE));
4301 return MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE;
4302 }
4303 else
4304 {
4305 /* Write pmdLowerLowGainStepRecovery to temp var, then to register */
4306 lower1ThreshGainStepRegValue |= (uint8_t)(device->rx->rxAgcCtrl->peakAgc->apdFastAttack << 7);
4307 lower1ThreshGainStepRegValue |= (uint8_t)(device->rx->rxAgcCtrl->peakAgc->hb2FastAttack << 6);
4308 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOWER1_THRSH_GAIN_STEP, lower1ThreshGainStepRegValue);
4309 }
4310
4311 /* Range check apdHighThresh */
4312 if ((device->rx->rxAgcCtrl->peakAgc->apdHighThresh > 0x3F) || (device->rx->rxAgcCtrl->peakAgc->apdHighThresh <= device->rx->rxAgcCtrl->peakAgc->apdLowThresh))
4313 {
4314 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM,
4315 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM));
4316 return MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM;
4317 }
4318 else
4319 {
4320 /* Write apdHighThresh */
4321 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ULB_THRSH, device->rx->rxAgcCtrl->peakAgc->apdHighThresh, 0X3F, 0);
4322 }
4323
4324 /* Range check apdLowThresh */
4325 if ((device->rx->rxAgcCtrl->peakAgc->apdLowThresh > 0x3F) || (device->rx->rxAgcCtrl->peakAgc->apdHighThresh < device->rx->rxAgcCtrl->peakAgc->apdLowThresh))
4326 {
4327 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM,
4328 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM));
4329 return MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM;
4330 }
4331 else
4332 {
4333 /* write apdLowThresh */
4334 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_LLB_THRSH, device->rx->rxAgcCtrl->peakAgc->apdLowThresh, 0x3F, 0);
4335 }
4336
4337 /* Range check hb2HighThresh */
4338 if (device->rx->rxAgcCtrl->peakAgc->hb2HighThresh < device->rx->rxAgcCtrl->peakAgc->hb2LowThresh)
4339 {
4340 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM,
4341 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM));
4342 return MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM;
4343 }
4344 else
4345 {
4346 /* write hb2HighThresh */
4347 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_UPPER_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2HighThresh);
4348 }
4349
4350 /* Range check hb2LowThresh */
4351 if (device->rx->rxAgcCtrl->peakAgc->hb2LowThresh > device->rx->rxAgcCtrl->peakAgc->hb2HighThresh)
4352 {
4353 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM,
4354 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM));
4355 return MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM;
4356 }
4357 else
4358 {
4359 /* write hb2LowThresh */
4360 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_LOWER_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2LowThresh);
4361 }
4362
4363 /* Range check hb2VeryLowThresh */
4364 if (device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh > device->rx->rxAgcCtrl->peakAgc->hb2LowThresh)
4365 {
4366 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM,
4367 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM));
4368 return MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM;
4369 }
4370 else
4371 {
4372 /* write hb2VeryLowThresh */
4373 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_VERYLOW_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh);
4374 }
4375
4376 /* Write threshold counter values for apdHigh/apdLow/hb2High/hb2Low/hb2VeryLow */
4377 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ULB_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->apdHighThreshExceededCnt);
4378 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LLB_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->apdLowThreshExceededCnt);
4379 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_HIGH_OVRG_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2HighThreshExceededCnt);
4380 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOW_OVRG_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2LowThreshExceededCnt);
4381 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_VERYLOW_OVRG_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt);
4382
4383 /* Range check on apdHighGainStepAttack (5-bit) */
4384 if (device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack > 0x1F)
4385 {
4386 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM,
4387 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM));
4388 return MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM;
4389 }
4390 else
4391 {
4392 /* Write apdHighGainStepAttack */
4393 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_1, device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack);
4394 }
4395
4396 /* Range check on apdLowGainStepRecovery (5-bit) */
4397 if (device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery > 0x1F)
4398 {
4399 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM,
4400 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM));
4401 return MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM;
4402 }
4403 else
4404 {
4405 /* Write apdLowGainStepRecovery */
4406 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_4, device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery);
4407 }
4408
4409 /* Range check on hb2HighGainStepAttack (5-bit) */
4410 if (device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack > 0x1F)
4411 {
4412 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM,
4413 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM));
4414 return MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM;
4415 }
4416 else
4417 {
4418 /* Write hb2HighGainStepAttack */
4419 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_2, device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack);
4420 }
4421
4422 /* Range check on hb2LowGainStepRecovery (5-bit) */
4423 if (device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery > 0x1F)
4424 {
4425 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM,
4426 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM));
4427 return MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM;
4428 }
4429 else
4430 {
4431 /* Write hb2LowGainStepRecovery */
4432 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_5, device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery);
4433 }
4434
4435 /* Range check on hb2VeryLowGainStepRecovery (5-bit) */
4436 if (device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery > 0x1F)
4437 {
4438 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM,
4439 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM));
4440 return MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM;
4441 }
4442 else
4443 {
4444 /* Write hb2VeryLowGainStepRecovery */
4445 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_6, device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery);
4446 }
4447
4448 /* Range Check on hb2OverloadDetectEnable */
4449 if (device->rx->rxAgcCtrl->peakAgc->hb2OverloadDetectEnable > 0x1)
4450 {
4451 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE,
4452 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE));
4453 return MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE;
4454 }
4455
4456 /* Range Check on hb2OverloadDetectEnable */
4457 if (device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt > 0x7)
4458 {
4459 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT,
4460 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT));
4461 return MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT;
4462 }
4463
4464 /* Range Check on hb2OverloadDetectEnable */
4465 if (device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt > 0xF)
4466 {
4467 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT,
4468 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT));
4469 return MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT;
4470 }
4471 else
4472 {
4473 /* Write the hb2OvldCfgRegValue, the combination of hb2OverloadThreshCnt, hb2OverloadDurationCnt, and hb2OverloadDetectEnable */
4474 hb2OvldCfgRegValue = (device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt) |(uint8_t)(device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt << 4)
4475 | (uint8_t)(device->rx->rxAgcCtrl->peakAgc->hb2OverloadDetectEnable << 7);
4476 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_CFG, hb2OvldCfgRegValue);
4477 }
4478
4479 /* Hard-coded value for the ADC overload configuration. Sets the HB2 offset to -6dB.*/
4480 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_ADC_OVRLD_CFG, 0x18);
4481 /* Hard-coded value for APD decay setting. Setting allows for the quickest settling time of peak detector */
4482 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX_BLOCK_DET_DECAY, 0x0);
4483
4484 /* performing a soft reset */
4485 return MYKONOS_resetRxAgc(device);
4486 }
4487
4488 /**
4489 * \brief This function resets the AGC state machine
4490 *
4491 * Calling this function resets all state machines within the gain control and maximum gain.
4492 *
4493 * <B>Dependencies:</B>
4494 * - device->spiSettings
4495 *
4496 * \param device is structure pointer to the Mykonos data structure containing the device SPI settings
4497 *
4498 * \retval MYKONOS_ERR_OK Function completed successfully
4499 */
MYKONOS_resetRxAgc(mykonosDevice_t * device)4500 mykonosErr_t MYKONOS_resetRxAgc(mykonosDevice_t *device)
4501 {
4502 const uint8_t AGC_RESET = 0x80;
4503
4504 #if (MYKONOS_VERBOSE == 1)
4505 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetRxAgc()\n");
4506 #endif
4507
4508 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, 1, AGC_RESET, 7);
4509 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, 0, AGC_RESET, 7);
4510
4511 return MYKONOS_ERR_OK;
4512
4513 }
4514
4515 /**
4516 * \brief This function sets the min/max gain indexes for AGC in the main RX channel
4517 *
4518 * Allows to change min/max gain index on runtime.
4519 * If RX1_RX2 selected, then the maxGainIndex/minGainIndex value will be applied to both channels.
4520 * If only Rx1 selected, then only Rx1 min/max gain indices will be updated, along with their device data structure values.
4521 * If only Rx2 selected, then only Rx2 min/max gain indices will be updated, along with their device data structure values.
4522 *
4523 * <B>Dependencies:</B>
4524 * - device->spiSettings
4525 * - device->rx->rxAgcCtrl
4526 *
4527 * \param device is structure pointer to the Mykonos data structure containing the device SPI settings
4528 * \param rxChannelSelect RX channel for setting the max and min gain index settings
4529 * \param maxGainIndex Max gain index setting
4530 * \param minGainIndex Min gain index setting
4531 *
4532 * \retval MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX Max gain index bigger than max gain index loaded table.
4533 * \retval MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX Min gain index lower than min gain index loaded table.
4534 * \retval MYKONOS_ERR_AGC_MIN_MAX_CHANNEL Wrong RX channel selected
4535 * \retval MYKONOS_ERR_OK Function completed successfully
4536 */
MYKONOS_setRxAgcMinMaxGainIndex(mykonosDevice_t * device,mykonosRxChannels_t rxChannelSelect,uint8_t maxGainIndex,uint8_t minGainIndex)4537 mykonosErr_t MYKONOS_setRxAgcMinMaxGainIndex(mykonosDevice_t *device, mykonosRxChannels_t rxChannelSelect, uint8_t maxGainIndex, uint8_t minGainIndex)
4538 {
4539 const uint8_t MIN_GAIN_INDEX = 1 + MAX_GAIN_TABLE_INDEX - (sizeof(RxGainTable) / sizeof(RxGainTable[0]));
4540
4541 #if (MYKONOS_VERBOSE == 1)
4542 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxAgcMinMaxGainIndex()\n");
4543 #endif
4544
4545 /* Check for maxGainIndex */
4546 if (maxGainIndex > MAX_GAIN_TABLE_INDEX)
4547 {
4548 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX,
4549 getMykonosErrorMessage(MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX));
4550 return MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX;
4551 }
4552
4553 /* Check for minGainIndex */
4554 if (minGainIndex < MIN_GAIN_INDEX)
4555 {
4556 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX,
4557 getMykonosErrorMessage(MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX));
4558 return MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX;
4559 }
4560
4561 if ((uint32_t)rxChannelSelect & (uint32_t)RX1)
4562 {
4563 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MAX_GAIN_INDEX, maxGainIndex);
4564 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MIN_GAIN_INDEX, minGainIndex);
4565 device->rx->rxAgcCtrl->agcRx1MaxGainIndex = maxGainIndex;
4566 device->rx->rxAgcCtrl->agcRx1MinGainIndex = minGainIndex;
4567 }
4568
4569 if ((uint32_t)rxChannelSelect & (uint32_t)RX2)
4570 {
4571 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MAX_GAIN_INDEX, maxGainIndex);
4572 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MIN_GAIN_INDEX, minGainIndex);
4573 device->rx->rxAgcCtrl->agcRx2MaxGainIndex = maxGainIndex;
4574 device->rx->rxAgcCtrl->agcRx2MinGainIndex = minGainIndex;
4575 }
4576
4577 /* Check for invalid Rx channel */
4578 if (!((uint32_t)rxChannelSelect & (uint32_t)RX1_RX2))
4579 {
4580 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL,
4581 getMykonosErrorMessage(MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL));
4582 return MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL;
4583 }
4584
4585 return MYKONOS_ERR_OK;
4586 }
4587
4588 /**
4589 * \brief This function sets the min/max gain indexes for AGC in the observation channel
4590 *
4591 * Allows to change min/max gain index on runtime.
4592 *
4593 * <B>Dependencies:</B>
4594 * - device->spiSettings
4595 * - device->rx->rxAgcCtrl
4596 *
4597 * \param device is structure pointer to the Mykonos data structure containing the device SPI settings
4598 * \param obsRxChannelSelect Observation channel for setting the max and min gain index settings
4599 * \param maxGainIndex Max gain index setting
4600 * \param minGainIndex Min gain index setting
4601 *
4602 * \retval MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL Wrong read back channel.
4603 * \retval MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX Max gain index bigger than max gain index loaded table.
4604 * \retval MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX Min gain index lower than min gain index loaded table.
4605 * \retval MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL Wrong observation channel selected
4606 * \retval MYKONOS_ERR_OK Function completed successfully
4607 */
MYKONOS_setObsRxAgcMinMaxGainIndex(mykonosDevice_t * device,mykonosObsRxChannels_t obsRxChannelSelect,uint8_t maxGainIndex,uint8_t minGainIndex)4608 mykonosErr_t MYKONOS_setObsRxAgcMinMaxGainIndex(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxChannelSelect, uint8_t maxGainIndex, uint8_t minGainIndex)
4609 {
4610 uint8_t rdObsActive = 0x00;
4611 uint8_t obsActive = 0x00;
4612 uint8_t obsCheck = 0x00;
4613 uint8_t minGainIndexCheck = 0x00;
4614 uint8_t maxGainIndexCheck = 0x00;
4615
4616 #if (MYKONOS_VERBOSE == 1)
4617 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxAgcMinMaxGainIndex()\n");
4618 #endif
4619
4620 /* Read active channel */
4621 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_ACTIVE, &rdObsActive, 0x03, 0);
4622
4623 /* Check active channel and set min/max checks */
4624 switch (rdObsActive)
4625 {
4626 case 0x00:
4627 case 0x01:
4628 /*sniffer*/
4629 maxGainIndexCheck = MAX_GAIN_TABLE_INDEX;
4630 minGainIndexCheck = MAX_GAIN_TABLE_INDEX - (sizeof(SnRxGainTable) / sizeof(SnRxGainTable[0]));
4631 obsActive = (uint32_t)OBS_SNIFFER | (uint32_t)OBS_SNIFFER_A | (uint32_t)OBS_SNIFFER_B | (uint32_t)OBS_SNIFFER_C;
4632 break;
4633 case 0x02:
4634 case 0x03:
4635 /*observation 1*/
4636 maxGainIndexCheck = MAX_GAIN_TABLE_INDEX;
4637 minGainIndexCheck = MAX_GAIN_TABLE_INDEX - (sizeof(ORxGainTable) / sizeof(ORxGainTable[0]));
4638 obsActive = (uint32_t)OBS_RX1_TXLO | (uint32_t)OBS_RX1_SNIFFERLO | (uint32_t)OBS_RX2_TXLO | (uint32_t)OBS_RX2_SNIFFERLO;
4639 break;
4640
4641 default:
4642 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL,
4643 getMykonosErrorMessage(MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL));
4644 return MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL;
4645 }
4646
4647 /* Check for maxGainIndex */
4648 if ((maxGainIndex > maxGainIndexCheck) || (maxGainIndex < minGainIndexCheck))
4649 {
4650 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX,
4651 getMykonosErrorMessage(MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX));
4652 return MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX;
4653 }
4654
4655 /* Check for minGainIndex */
4656 if ((minGainIndex < minGainIndexCheck) || (minGainIndex > maxGainIndexCheck))
4657 {
4658 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX,
4659 getMykonosErrorMessage(MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX));
4660 return MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX;
4661 }
4662
4663 device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex = maxGainIndex;
4664 device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex = minGainIndex;
4665
4666 switch (obsRxChannelSelect)
4667 {
4668 case OBS_SNIFFER:
4669 case OBS_SNIFFER_A:
4670 case OBS_SNIFFER_B:
4671 case OBS_SNIFFER_C:
4672 obsCheck = (uint32_t)OBS_SNIFFER | (uint32_t)OBS_SNIFFER_A | (uint32_t)OBS_SNIFFER_B | (uint32_t)OBS_SNIFFER_C;
4673 maxGainIndex = maxGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES;
4674 minGainIndex = minGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES;
4675 break;
4676
4677 case OBS_RX1_TXLO:
4678 case OBS_RX2_TXLO:
4679 case OBS_RX1_SNIFFERLO:
4680 case OBS_RX2_SNIFFERLO:
4681 obsCheck = (uint32_t)OBS_RX1_TXLO | (uint32_t)OBS_RX1_SNIFFERLO | (uint32_t)OBS_RX2_TXLO | (uint32_t)OBS_RX2_SNIFFERLO;
4682 maxGainIndex = maxGainIndex - MAX_ORX_GAIN_TABLE_NUMINDEXES;
4683 minGainIndex = minGainIndex - MAX_ORX_GAIN_TABLE_NUMINDEXES;
4684 break;
4685
4686 default:
4687 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL,
4688 getMykonosErrorMessage(MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL));
4689 return MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL;
4690 }
4691
4692 if (obsCheck == obsActive)
4693 {
4694 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MAX_GAIN_INDEX, maxGainIndex);
4695 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MIN_GAIN_INDEX, minGainIndex);
4696 }
4697 else
4698 {
4699 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL,
4700 getMykonosErrorMessage(MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL));
4701 return MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL;
4702 }
4703
4704 return MYKONOS_ERR_OK;
4705 }
4706
4707 /**
4708 * \brief This function sets the Temperature gain compensation for Rx1 channel
4709 *
4710 * The temperature gain compensation control allow for a +3000mdB to -3000mdB digital gain
4711 * in the data path.
4712 * The resolution of the temperature compensation gain is 250mdB.
4713 *
4714 * <B>Dependencies:</B>
4715 * - device->spiSettings
4716 *
4717 * \param device is structure pointer to the Mykonos data structure containing the device SPI settings
4718 * \param rx1TempCompGain_mdB gain compensation for Rx1, the range is from -3000mdB to +3000mdB in steps of 250mdB
4719 *
4720 * \retval MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE The temp gain compensation is outside range (-3000mdB to 3000mdB)
4721 * \retval MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP Not valid temp gain compensation, step size is 250mdB
4722 * \retval MYKONOS_ERR_OK Function completed successfully
4723 */
MYKONOS_setRx1TempGainComp(mykonosDevice_t * device,int16_t rx1TempCompGain_mdB)4724 mykonosErr_t MYKONOS_setRx1TempGainComp(mykonosDevice_t *device, int16_t rx1TempCompGain_mdB)
4725 {
4726 int8_t tempGainComp = 0x00;
4727
4728 const int16_t LOW_LIMIT_GAIN_COMP = -3000;
4729 const int16_t HIGH_LIMIT_GAIN_COMP = 3000;
4730 const int16_t GAIN_COMP_STEP = 250;
4731
4732 #if (MYKONOS_VERBOSE == 1)
4733 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx1TempGainComp()\n");
4734 #endif
4735
4736 /* Check for Gain compensation range */
4737 if ((rx1TempCompGain_mdB > HIGH_LIMIT_GAIN_COMP) || (rx1TempCompGain_mdB < LOW_LIMIT_GAIN_COMP))
4738 {
4739 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE,
4740 getMykonosErrorMessage(MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE));
4741 return MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE;
4742 }
4743
4744 /* Check for Gain compensation steps */
4745 if (rx1TempCompGain_mdB % GAIN_COMP_STEP)
4746 {
4747 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP,
4748 getMykonosErrorMessage(MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP));
4749 return MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP;
4750 }
4751
4752 /* Prepare register write */
4753 tempGainComp = (rx1TempCompGain_mdB / GAIN_COMP_STEP) & 0x1F;
4754 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX1_TEMP_GAIN_COMP, (uint8_t)tempGainComp);
4755
4756 return MYKONOS_ERR_OK;
4757 }
4758
4759 /**
4760 * \brief This function gets the Temperature gain compensation for Rx1
4761 *
4762 * <B>Dependencies:</B>
4763 * - device->spiSettings
4764 *
4765 * \param device is structure pointer to the Mykonos data structure containing the device SPI settings
4766 * \param rx1TempCompGain_mdB Which will be populated with the Temperature Gain Compensation in mdB value for Rx1 channel.
4767 *
4768 * \retval MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL rx1TempCompGain_mdB pointer is null.
4769 * \retval MYKONOS_ERR_OK Function completed successfully
4770 */
MYKONOS_getRx1TempGainComp(mykonosDevice_t * device,int16_t * rx1TempCompGain_mdB)4771 mykonosErr_t MYKONOS_getRx1TempGainComp(mykonosDevice_t *device, int16_t *rx1TempCompGain_mdB)
4772 {
4773 uint8_t tempGainComp = 0x00;
4774 int8_t tempGainCompDB = 0x00;
4775
4776 const int16_t GAIN_COMP_STEP = 250;
4777
4778 #if (MYKONOS_VERBOSE == 1)
4779 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx1TempGainComp()\n");
4780 #endif
4781
4782 /* Check for null passed parameter */
4783 if (rx1TempCompGain_mdB == NULL)
4784 {
4785 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL,
4786 getMykonosErrorMessage(MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL));
4787 return MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL;
4788 }
4789
4790 /* Read Temperature Gain Compensation */
4791 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX1_TEMP_GAIN_COMP, &tempGainComp);
4792
4793 /* Convert to dB and prepare the signed return */
4794 tempGainCompDB = tempGainComp & 0x1F;
4795 if (tempGainCompDB & 0x10)
4796 {
4797 tempGainCompDB = ((((~((uint8_t)tempGainCompDB)) & 0x0F) + 1) * (-1));
4798 }
4799
4800 /* Assign value to the passed pointer */
4801 *rx1TempCompGain_mdB = tempGainCompDB * GAIN_COMP_STEP;
4802
4803 return MYKONOS_ERR_OK;
4804 }
4805
4806 /**
4807 * \brief This function sets the Temperature gain compensation for Rx2 channel
4808 *
4809 * The temperature gain compensation control allow for a +3000mdB to -3000mdB digital gain
4810 * in the data path.
4811 * The resolution of the temperature compensation gain is 250mdB.
4812 *
4813 * <B>Dependencies:</B>
4814 * - device->spiSettings
4815 *
4816 * \param device is structure pointer to the Mykonos data structure containing the device SPI settings
4817 * \param rx2TempCompGain_mdB gain compensation for Rx1,
4818 * the range is from -3000mdB to +3000mdB in steps of 250mdB
4819 *
4820 * \retval MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE The temp gain compensation is outside range (-3000mdB to 3000mdB)
4821 * \retval MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP Not valid temp gain compensation, step size is 250mdB
4822 * \retval MYKONOS_ERR_OK Function completed successfully
4823 */
MYKONOS_setRx2TempGainComp(mykonosDevice_t * device,int16_t rx2TempCompGain_mdB)4824 mykonosErr_t MYKONOS_setRx2TempGainComp(mykonosDevice_t *device, int16_t rx2TempCompGain_mdB)
4825 {
4826 int8_t tempGainComp = 0x00;
4827
4828 const int16_t LOW_LIMIT_GAIN_COMP = -3000;
4829 const int16_t HIGH_LIMIT_GAIN_COMP = 3000;
4830 const int16_t GAIN_COMP_STEP = 250;
4831
4832 #if (MYKONOS_VERBOSE == 1)
4833 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx2TempGainComp()\n");
4834 #endif
4835
4836 /* Check for Gain compensation range */
4837 if ((rx2TempCompGain_mdB > HIGH_LIMIT_GAIN_COMP) || (rx2TempCompGain_mdB < LOW_LIMIT_GAIN_COMP))
4838 {
4839 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE,
4840 getMykonosErrorMessage(MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE));
4841 return MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE;
4842 }
4843
4844 /* Check for Gain compensation range */
4845 if (rx2TempCompGain_mdB % GAIN_COMP_STEP)
4846 {
4847 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP,
4848 getMykonosErrorMessage(MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP));
4849 return MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP;
4850 }
4851
4852 /* Prepare register write */
4853 tempGainComp = (rx2TempCompGain_mdB / GAIN_COMP_STEP) & 0x1F;
4854 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX2_TEMP_GAIN_COMP, (uint8_t)tempGainComp);
4855
4856 return MYKONOS_ERR_OK;
4857 }
4858
4859 /**
4860 * \brief This function gets the Temperature gain compensation for Rx2
4861 *
4862 * <B>Dependencies:</B>
4863 * - device->spiSettings
4864 *
4865 * \param device is structure pointer to the Mykonos data structure containing the device SPI settings
4866 * \param rx2TempCompGain_mdB Which will be populated with the Temperature Gain Compensation in mdB value for Rx2 channel.
4867 *
4868 * \retval MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL rx2TempCompGain_mdB pointer is null.
4869 * \retval MYKONOS_ERR_OK Function completed successfully
4870 */
MYKONOS_getRx2TempGainComp(mykonosDevice_t * device,int16_t * rx2TempCompGain_mdB)4871 mykonosErr_t MYKONOS_getRx2TempGainComp(mykonosDevice_t *device, int16_t *rx2TempCompGain_mdB)
4872 {
4873 uint8_t tempGainComp = 0x00;
4874 int8_t tempGainCompDB = 0x00;
4875
4876 const int16_t GAIN_COMP_STEP = 250;
4877
4878 #if (MYKONOS_VERBOSE == 1)
4879 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx2TempGainComp()\n");
4880 #endif
4881
4882 /* Check for null passed parameter */
4883 if (rx2TempCompGain_mdB == NULL)
4884 {
4885 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL,
4886 getMykonosErrorMessage(MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL));
4887 return MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL;
4888 }
4889
4890 /* Read programmed Temperature Gain Compensation */
4891 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX2_TEMP_GAIN_COMP, &tempGainComp);
4892
4893 /* Convert to dB and prepare the signed return */
4894 tempGainCompDB = tempGainComp & 0x1F;
4895 if (tempGainCompDB & 0x10)
4896 {
4897 tempGainCompDB = (((~((uint8_t)tempGainCompDB)) & 0x0F) + 1) * (-1);
4898 }
4899
4900 /* Assign value to the passed pointer */
4901 *rx2TempCompGain_mdB = tempGainCompDB * GAIN_COMP_STEP;
4902
4903 return MYKONOS_ERR_OK;
4904 }
4905
4906 /**
4907 * \brief This function sets the Temperature gain compensation for the observation channel
4908 *
4909 * The temperature gain compensation control allow for a +3000mdB to -3000mdB digital gain
4910 * in the data path.
4911 * The resolution of the temperature compensation gain is 250mdB.
4912 *
4913 * <B>Dependencies:</B>
4914 * - device->spiSettings
4915 *
4916 * \param device is structure pointer to the Mykonos data structure containing the device SPI settings
4917 * \param obsRxTempCompGain_mdB gain compensation for observation channel,
4918 * the range is from -3000mdB to +3000mdB in steps of 250mdB
4919 *
4920 * \retval MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE The temp gain compensation is outside range (-3000mdB to 3000mdB)
4921 * \retval MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP Not valid temp gain compensation, step size is 250mdB
4922 * \retval MYKONOS_ERR_OK Function completed successfully
4923 */
MYKONOS_setObsRxTempGainComp(mykonosDevice_t * device,int16_t obsRxTempCompGain_mdB)4924 mykonosErr_t MYKONOS_setObsRxTempGainComp(mykonosDevice_t *device, int16_t obsRxTempCompGain_mdB)
4925 {
4926 int8_t tempGainComp = 0x00;
4927
4928 const int16_t LOW_LIMIT_GAIN_COMP = -3000;
4929 const int16_t HIGH_LIMIT_GAIN_COMP = 3000;
4930 const int16_t GAIN_COMP_STEP = 250;
4931
4932 #if (MYKONOS_VERBOSE == 1)
4933 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxTempGainComp()\n");
4934 #endif
4935
4936 /* Check for Gain compensation range */
4937 if ((obsRxTempCompGain_mdB > HIGH_LIMIT_GAIN_COMP) || (obsRxTempCompGain_mdB < LOW_LIMIT_GAIN_COMP))
4938 {
4939 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE,
4940 getMykonosErrorMessage(MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE));
4941 return MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE;
4942 }
4943
4944 /* Check for Gain compensation range */
4945 if (obsRxTempCompGain_mdB % GAIN_COMP_STEP)
4946 {
4947 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP,
4948 getMykonosErrorMessage(MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP));
4949 return MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP;
4950 }
4951
4952 /* Prepare register write */
4953 tempGainComp = (obsRxTempCompGain_mdB / GAIN_COMP_STEP) & 0x1F;
4954 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_TEMP_GAIN_COMP, (uint8_t)tempGainComp);
4955
4956 return MYKONOS_ERR_OK;
4957 }
4958
4959 /**
4960 * \brief This function gets the Temperature gain compensation for the observation channel
4961 *
4962 *
4963 * <B>Dependencies:</B>
4964 * - device->spiSettings
4965 *
4966 * \param device is structure pointer to the Mykonos data structure containing the device SPI settings
4967 * \param obsRxTempCompGain_mdB Which will be populated with the Temperature Gain Compensation in mdB value for the observation channel.
4968 *
4969 * \retval MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL obsRxTempCompGain_mdB pointer is null.
4970 * \retval MYKONOS_ERR_OK Function completed successfully
4971 */
MYKONOS_getObsRxTempGainComp(mykonosDevice_t * device,int16_t * obsRxTempCompGain_mdB)4972 mykonosErr_t MYKONOS_getObsRxTempGainComp(mykonosDevice_t *device, int16_t *obsRxTempCompGain_mdB)
4973 {
4974 uint8_t tempGainComp = 0x00;
4975 int8_t tempGainCompDB = 0x00;
4976
4977 const int16_t GAIN_COMP_STEP = 250;
4978
4979 #if (MYKONOS_VERBOSE == 1)
4980 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxTempGainComp()\n");
4981 #endif
4982
4983 /* Check for null passed parameter */
4984 if (obsRxTempCompGain_mdB == NULL)
4985 {
4986 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL,
4987 getMykonosErrorMessage(MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL));
4988 return MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL;
4989 }
4990
4991 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_OBS_TEMP_GAIN_COMP, &tempGainComp);
4992
4993 /* Convert to dB and prepare the signed return */
4994 tempGainCompDB = tempGainComp & 0x1F;
4995 if (tempGainCompDB & 0x10)
4996 {
4997 tempGainCompDB = (((~((uint8_t)tempGainCompDB)) & 0x0F) + 1) * (-1);
4998 }
4999
5000 /* Assign value to the passed pointer */
5001 *obsRxTempCompGain_mdB = tempGainCompDB * GAIN_COMP_STEP;
5002
5003 return MYKONOS_ERR_OK;
5004 }
5005
5006 /**
5007 * \brief Enables or disables the Rx slow loop gain counter to use the sync pulse
5008 *
5009 * <B>Dependencies:</B>
5010 * - device->spiSettings
5011 *
5012 * \param device is structure pointer to the Mykonos data structure containing the device SPI settings
5013 * \param enable is a uint8_t data type where '0' = disable Rx gain counter from using sync pulse, '1' = enable Rx gain. All other values will throw an error.
5014 * counter to use the sync pulse. This value is written back to the device data structure for storage.
5015 *
5016 * \retval MYKONOS_ERR_OK Function completed successfully
5017 */
MYKONOS_enableRxGainCtrSyncPulse(mykonosDevice_t * device,uint8_t enable)5018 mykonosErr_t MYKONOS_enableRxGainCtrSyncPulse(mykonosDevice_t *device, uint8_t enable)
5019 {
5020 const uint8_t syncPulseBitMask = 0x80;
5021 uint8_t enableBit = 0;
5022
5023 #if (MYKONOS_VERBOSE == 1)
5024 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxGainCtrSyncPulse()\n");
5025 #endif
5026
5027 /* read, modify, write Rx gain counter sync pulse enable bit */
5028 enableBit = (enable > 0) ? 1 : 0;
5029 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOOP_CFG, enableBit, syncPulseBitMask, 7);
5030
5031 return MYKONOS_ERR_OK;
5032 }
5033
5034 /**
5035 * \brief Configures the Rx gain control mode
5036 *
5037 * <B>Dependencies:</B>
5038 * - device->spiSettings
5039 * - device->spiSettings->chipSelectIndex
5040 * - device->rx->rxGainCtrl->gainMode
5041 *
5042 * \param device is structure pointer to the Mykonos data structure containing settings
5043 * \param mode is a mykonosGainMode_t enumerated gain control mode type where:
5044 * Manual Gain = MGC, Automatic Gain Control = AGC, and hybrid mode = HYBRID
5045 *
5046 * When the mode enumerated type is passed, the Rx1 and Rx2 gain mode is set to this value and the
5047 * Rx gainMode structure member is updated with the new value
5048 *
5049 * \retval MYKONOS_ERR_OK Function completed successfully
5050 * \retval MYKONOS_ERR_INV_RX_GAIN_MODE_PARM Invalid AGC mode pass in function mode paramter
5051 */
MYKONOS_setRxGainControlMode(mykonosDevice_t * device,mykonosGainMode_t mode)5052 mykonosErr_t MYKONOS_setRxGainControlMode(mykonosDevice_t *device, mykonosGainMode_t mode)
5053 {
5054 uint8_t rxGainCfgReg = 0;
5055
5056 const uint8_t RX_GAIN_TYPE_MASK = 0x1F;
5057 const uint8_t RX_GAIN_HYBRID_MASK = 0x10;
5058 const uint8_t RX_GAIN_TYPE_SHIFT = 0x02;
5059
5060 #if (MYKONOS_VERBOSE == 1)
5061 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxGainControlMode()\n");
5062 #endif
5063
5064 /* read AGC type for Rx1 and Rx2 for modify, write */
5065 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_CFG_1, &rxGainCfgReg);
5066 rxGainCfgReg &= ~RX_GAIN_TYPE_MASK;
5067
5068 /* performing AGC type check */
5069 switch (mode)
5070 {
5071 case MGC:
5072 rxGainCfgReg &= ~RX_GAIN_HYBRID_MASK;
5073 break;
5074 case AGC:
5075 rxGainCfgReg &= ~RX_GAIN_HYBRID_MASK;
5076 break;
5077 case HYBRID:
5078 rxGainCfgReg |= RX_GAIN_HYBRID_MASK;
5079 break;
5080 default:
5081 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RX_GAIN_MODE_PARM,
5082 getMykonosErrorMessage(MYKONOS_ERR_INV_RX_GAIN_MODE_PARM));
5083 return MYKONOS_ERR_INV_RX_GAIN_MODE_PARM;
5084 }
5085
5086 /* modify, write AGC type for Rx1 and Rx2 */
5087 rxGainCfgReg |= (uint8_t)mode;
5088 rxGainCfgReg |= (uint8_t)((uint8_t)mode << RX_GAIN_TYPE_SHIFT);
5089 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_CFG_1, rxGainCfgReg);
5090
5091 /* writing mode setting to data structure */
5092 if ((device->profilesValid & RX_PROFILE_VALID) > 0)
5093 {
5094 device->rx->rxGainCtrl->gainMode = mode;
5095 }
5096
5097 return MYKONOS_ERR_OK;
5098 }
5099
5100 /**
5101 * \brief Performs a power measurement in the Rx1 digital data path.
5102 *
5103 * Due to interdependencies between the AGC and power measurement the power measurement duration and
5104 * where the measurement is taken is variable.
5105 * The location of the power measurement is given by device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasConfig
5106 * The number of samples the power measurement uses is given by 8*2^(device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasDuration) at the IQ rate,
5107 * if measured at RFIR output. This number of samples must be less than the agcGainUpdateCounter.
5108 * If the receiver is disabled during the power measurement, this function returns a 0 value for rx1DecPower_mdBFS
5109 *
5110 * The resolution of this function is 0.25dB.
5111 * The dynamic range of this function is 40dB. Signals lower than 40dBFS may not be measured accurately.
5112 *
5113 * <B>Dependencies</B>
5114 * - device->spiSettings
5115 * - device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasConfig
5116 * - device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasDuration
5117 *
5118 * \param device Pointer to the Mykonos data structure
5119 * \param rx1DecPower_mdBFS Pointer to store the Rx1 decimated power return. Value returned in mdBFS
5120 *
5121 * \retval MYKONOS_ERR_OK Function completed successfully
5122 */
MYKONOS_getRx1DecPower(mykonosDevice_t * device,uint16_t * rx1DecPower_mdBFS)5123 mykonosErr_t MYKONOS_getRx1DecPower(mykonosDevice_t *device, uint16_t *rx1DecPower_mdBFS)
5124 {
5125 uint8_t rx1DecPower_dBFS = 0;
5126
5127 #if (MYKONOS_VERBOSE == 1)
5128 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx1DecPower()\n");
5129 #endif
5130
5131 /* read Rx1 Dec Power Measurement */
5132 if (rx1DecPower_mdBFS != NULL)
5133 {
5134 CMB_SPIReadByte(device->spiSettings, MYKONOS_CH1_DECIMATED_PWR, &rx1DecPower_dBFS);
5135 *rx1DecPower_mdBFS = (uint16_t)(rx1DecPower_dBFS * 250); /* 250 = 1000 * 0.25dB */
5136 }
5137 else
5138 {
5139 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM,
5140 getMykonosErrorMessage(MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM));
5141 return MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM;
5142 }
5143
5144 return MYKONOS_ERR_OK;
5145 }
5146
5147 /**
5148 * \brief Performs a power measurement in the Rx2 digital data path.
5149 *
5150 * Due to interdependencies between the AGC and power measurement the power measurement duration and
5151 * where the measurement is taken is variable.
5152 * The location of the power measurement is given by device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasConfig
5153 * The number of samples the power measurement uses is given by 8*2^(device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasDuration) at the IQ rate,
5154 * if measured at RFIR output. This number of samples must be less than the agcGainUpdateCounter.
5155 * If the receiver is disabled during the power measurement, this function returns a 0 value for rx2DecPower_mdBFS
5156 *
5157 * The resolution of this function is 0.25dB.
5158 * The dynamic range of this function is 40dB. Signals lower than 40dBFS may not be measured accurately.
5159 *
5160 * <B>Dependencies</B>
5161 * - device->spiSettings
5162 *
5163 * \param device Pointer to the Mykonos data structure
5164 * \param rx2DecPower_mdBFS Pointer to store the Rx1 decimated power return. Value returned in mdBFS
5165 *
5166 * \retval MYKONOS_ERR_OK Function completed successfully
5167 */
MYKONOS_getRx2DecPower(mykonosDevice_t * device,uint16_t * rx2DecPower_mdBFS)5168 mykonosErr_t MYKONOS_getRx2DecPower(mykonosDevice_t *device, uint16_t *rx2DecPower_mdBFS)
5169 {
5170 uint8_t rx2DecPower_dBFS = 0;
5171
5172 #if (MYKONOS_VERBOSE == 1)
5173 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx2DecPower()\n");
5174 #endif
5175
5176 /* read Rx2 Dec Power Measurement */
5177 if (rx2DecPower_mdBFS != NULL)
5178 {
5179 CMB_SPIReadByte(device->spiSettings, MYKONOS_CH2_DECIMATED_PWR, &rx2DecPower_dBFS);
5180 *rx2DecPower_mdBFS = (uint16_t)(rx2DecPower_dBFS * 250); /* 250 = 1000 * 0.25dB */
5181 }
5182 else
5183 {
5184 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM,
5185 getMykonosErrorMessage(MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM));
5186 return MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM;
5187 }
5188
5189 return MYKONOS_ERR_OK;
5190 }
5191
5192 /*
5193 *****************************************************************************
5194 * Observation Rx Data path functions
5195 *****************************************************************************
5196 */
5197
5198 /**
5199 * \brief Sets the default Obs Rx channel to enter when device moves from
5200 * radioOff to radioOn
5201 *
5202 * By default, the observation receiver remains powered down when the device
5203 * moves into the radioOn state. If the BBIC prefers a particular ObsRx
5204 * channel to be enabled, this function can be called in radioOff to set
5205 * the default channel to power up when the device moves to radioOn.
5206 *
5207 * <B>Dependencies</B>
5208 * - device->spiSettings->chipSelectIndex
5209 * - device->obsRx->defaultObsRxChannel
5210 *
5211 * \param device is structure pointer to the Mykonos data structure containing settings
5212 * \param defaultObsRxCh is mykonosObsRxChannels_t enum type which selects the desired observation receive path to power up
5213 *
5214 * \retval MYKONOS_ERR_OK Function completed successfully
5215 * \retval MYKONOS_ERR_SETDEFOBSRXPATH_NULL_OBSRX_STRUCT Observation profile not valid, device->obsRx structure is NULL
5216 * \retval MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT Invalid defaultObsRxCh function parameter
5217 */
MYKONOS_setDefaultObsRxPath(mykonosDevice_t * device,mykonosObsRxChannels_t defaultObsRxCh)5218 mykonosErr_t MYKONOS_setDefaultObsRxPath(mykonosDevice_t *device, mykonosObsRxChannels_t defaultObsRxCh)
5219 {
5220 uint8_t orxEntryMode[1] = {0};
5221 uint16_t byteOffset = 0;
5222 mykonosErr_t retVal = MYKONOS_ERR_OK;
5223
5224 #if (MYKONOS_VERBOSE == 1)
5225 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDefaultObsRxPath()\n");
5226 #endif
5227
5228 if (device->obsRx == NULL)
5229 {
5230 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT,
5231 getMykonosErrorMessage(MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT));
5232 return MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT;
5233 }
5234
5235 if (((defaultObsRxCh > OBS_RX2_SNIFFERLO) && (defaultObsRxCh != OBS_SNIFFER_A) && (defaultObsRxCh != OBS_SNIFFER_B) && (defaultObsRxCh != OBS_SNIFFER_C)))
5236 {
5237 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM,
5238 getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM));
5239 return MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM;
5240 }
5241
5242 device->obsRx->defaultObsRxChannel = defaultObsRxCh;
5243 orxEntryMode[0] = ((uint8_t)device->obsRx->defaultObsRxChannel & 0xFF);
5244
5245 byteOffset = 6;
5246 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_RADIO_CONTROL, byteOffset, &orxEntryMode[0], 1);
5247 if (retVal != MYKONOS_ERR_OK)
5248 {
5249 return retVal;
5250 }
5251
5252 return MYKONOS_ERR_OK;
5253 }
5254
5255 /**
5256 * \brief Powers up or down the Observation Rx signal chain in the radioOn state
5257 *
5258 * When the ARM radio control is in ARM command mode, this
5259 * function allows the user to selectively power up or down the desired ObsRx
5260 * data path. If this function is called when the ARM is expecting GPIO pin
5261 * control of the ObsRx path source, an error will be returned.
5262 *
5263 * <B>Dependencies</B>
5264 * - device->spiSettings->chipSelectIndex
5265 *
5266 * \param device is structure pointer to the Mykonos data structure containing settings
5267 * \param obsRxCh is mykonosObsRxChannels_t enum type which selects the desired observation receive path to power up
5268 *
5269 * \retval MYKONOS_ERR_OK Function completed successfully
5270 * \retval MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM Invalid obsRxCh function parameter
5271 * \retval MYKONOS_ERR_PU_OBSRXPATH_ARMERROR ARM returned an error while trying to set the ObsRx Path source
5272 */
MYKONOS_setObsRxPathSource(mykonosDevice_t * device,mykonosObsRxChannels_t obsRxCh)5273 mykonosErr_t MYKONOS_setObsRxPathSource(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxCh)
5274 {
5275 uint8_t cmdStatByte = 0;
5276 uint32_t timeoutMs = 0;
5277 uint8_t payload[2] = {0, 0};
5278 mykonosErr_t retVal = MYKONOS_ERR_OK;
5279
5280 #if (MYKONOS_VERBOSE == 1)
5281 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxPathSource()\n");
5282 #endif
5283
5284 if (((obsRxCh > OBS_RX2_SNIFFERLO) && (obsRxCh != OBS_SNIFFER_A) && (obsRxCh != OBS_SNIFFER_B) && (obsRxCh != OBS_SNIFFER_C)))
5285 {
5286 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM,
5287 getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM));
5288 return MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM;
5289 }
5290
5291 payload[0] = MYKONOS_ARM_OBJECTID_ORX_MODE;
5292 payload[1] = (uint8_t)(obsRxCh);
5293
5294 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &payload[0], sizeof(payload));
5295 if (retVal != MYKONOS_ERR_OK)
5296 {
5297 return retVal;
5298 }
5299
5300 timeoutMs = 1000; /* wait max of 1sec for command to complete */
5301 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatByte);
5302 if (retVal != MYKONOS_ERR_OK)
5303 {
5304 if (cmdStatByte > 0)
5305 {
5306 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_ARMERROR,
5307 getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_ARMERROR));
5308 return MYKONOS_ERR_PU_OBSRXPATH_ARMERROR;
5309 }
5310
5311 return retVal;
5312 }
5313
5314 /* Verify ARM command did not return an error */
5315 if (cmdStatByte > 0)
5316 {
5317 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_ARMERROR,
5318 getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_ARMERROR));
5319 return MYKONOS_ERR_PU_OBSRXPATH_ARMERROR;
5320 }
5321
5322 return MYKONOS_ERR_OK;
5323 }
5324
5325 /**
5326 * \brief Reads back the currently enabled Observation Rx channel in the
5327 * radioOn state
5328 *
5329 * In pin mode, the pin could change asynchronous to reading back the
5330 * current enable ObsRx path. Calling this function while in radioOff will
5331 * return OBS_RXOFF since all radio channels are powered down.
5332 *
5333 * <B>Dependencies</B>
5334 * - device->spiSettings->chipSelectIndex
5335 *
5336 * \param device is structure pointer to the Mykonos data structure containing settings
5337 * \param obsRxCh Parameter to return enum of the current observation receive
5338 * path powered up
5339 *
5340 * \retval MYKONOS_ERR_OK Function completed successfully
5341 * \retval MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR ARM returned an error while trying to get the ObsRx Path source
5342 */
MYKONOS_getObsRxPathSource(mykonosDevice_t * device,mykonosObsRxChannels_t * obsRxCh)5343 mykonosErr_t MYKONOS_getObsRxPathSource(mykonosDevice_t *device, mykonosObsRxChannels_t *obsRxCh)
5344 {
5345 uint8_t extData[1] = {MYKONOS_ARM_OBJECTID_ORX_MODE};
5346 uint8_t cmdStatusByte = 0;
5347 uint8_t armData[1] = {0};
5348 uint32_t timeoutMs = 0;
5349 mykonosErr_t retVal = MYKONOS_ERR_OK;
5350
5351 #if (MYKONOS_VERBOSE == 1)
5352 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxPathSource()\n");
5353 #endif
5354
5355 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
5356 if (retVal != MYKONOS_ERR_OK)
5357 {
5358 return retVal;
5359 }
5360
5361 timeoutMs = 1000;
5362 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
5363 if (retVal != MYKONOS_ERR_OK)
5364 {
5365 if (cmdStatusByte > 0)
5366 {
5367 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR,
5368 getMykonosErrorMessage(MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR));
5369 return MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR;
5370 }
5371
5372 return retVal;
5373 }
5374
5375 /* read 64-bit frequency from ARM memory */
5376 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 1, 1);
5377 if (retVal != MYKONOS_ERR_OK)
5378 {
5379 return retVal;
5380 }
5381
5382 if (cmdStatusByte > 0)
5383 {
5384 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR,
5385 getMykonosErrorMessage(MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR));
5386 return MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR;
5387 }
5388
5389 *obsRxCh = (mykonosObsRxChannels_t)(armData[0]);
5390
5391 return MYKONOS_ERR_OK;
5392 }
5393
5394 /**
5395 * \brief Sets the Rx gain of the ObsRx channel
5396 *
5397 * The ObsRx channel can have different RF inputs (ORx1/ORx2/SnRx A,B,C)
5398 * This function sets the ObsRx gain index independently for ORx1/ORx2, or SnRx.
5399 * SnRx A, B, and C share the same gain index. Please note that ORx1/ORx2 share a gain
5400 * table, as does SnRx A, B, and C. The maximum index is 255
5401 * and the minimum index is application specific.
5402 *
5403 * <B>Dependencies</B>
5404 * - device->spiSettings
5405 * - device->obsRx->orxGainCtrl->maxGainIndex
5406 * - device->obsRx->orxGainCtrl->minGainIndex
5407 * - device->obsRx->orxGainCtrl->orx1GainIndex
5408 * - device->obsRx->orxGainCtrl->orx2GainIndex
5409 * - device->obsRx->snifferGainCtrl->maxGainIndex
5410 * - device->obsRx->snifferGainCtrl->minGainIndex
5411 * - device->obsRx->snifferGainCtrl->gainIndex
5412 *
5413 * \param device Pointer to the Mykonos device data structure
5414 * \param obsRxCh is an enum type mykonosObsRxChannels_t to identify the desired RF input for gain change
5415 * \param gainIndex Desired manual gain table index to set
5416 *
5417 * \retval MYKONOS_ERR_OK Function completed successfully
5418 * \retval MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN Invalid gain requested for ORx1: outside gain table min/max index
5419 * \retval MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN Invalid gain requested for ORx2: outside gain table min/max index
5420 * \retval MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN Invalid gain requested for Sniffer: outside gain table min/max index
5421 * \retval MYKONOS_ERR_SETORXGAIN_INV_CHANNEL Function parameter obsRxCh has an invalid enum value
5422 */
MYKONOS_setObsRxManualGain(mykonosDevice_t * device,mykonosObsRxChannels_t obsRxCh,uint8_t gainIndex)5423 mykonosErr_t MYKONOS_setObsRxManualGain(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxCh, uint8_t gainIndex)
5424 {
5425
5426 #if (MYKONOS_VERBOSE == 1)
5427 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxManualGain()\n");
5428 #endif
5429
5430 if ((obsRxCh == OBS_RX1_TXLO) || (obsRxCh == OBS_RX1_SNIFFERLO))
5431 {
5432 if (gainIndex <= device->obsRx->orxGainCtrl->maxGainIndex && gainIndex >= device->obsRx->orxGainCtrl->minGainIndex)
5433 {
5434 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX1_MANUAL_GAIN_INDEX, (gainIndex - MIN_ORX_GAIN_TABLE_INDEX));
5435 device->obsRx->orxGainCtrl->orx1GainIndex = gainIndex;
5436 }
5437 else
5438 {
5439 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN,
5440 getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN));
5441 return MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN;
5442 }
5443 }
5444 else if ((obsRxCh == OBS_RX2_TXLO) || (obsRxCh == OBS_RX2_SNIFFERLO))
5445 {
5446 if (gainIndex <= device->obsRx->orxGainCtrl->maxGainIndex && gainIndex >= device->obsRx->orxGainCtrl->minGainIndex)
5447 {
5448 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX2_MANUAL_GAIN_INDEX, (gainIndex - MIN_ORX_GAIN_TABLE_INDEX));
5449 device->obsRx->orxGainCtrl->orx2GainIndex = gainIndex;
5450 }
5451 else
5452 {
5453 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN,
5454 getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN));
5455 return MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN;
5456 }
5457
5458 }
5459 else if (obsRxCh == OBS_SNIFFER_A || obsRxCh == OBS_SNIFFER_B || obsRxCh == OBS_SNIFFER_C || obsRxCh == OBS_SNIFFER)
5460 {
5461 if (gainIndex <= device->obsRx->snifferGainCtrl->maxGainIndex && gainIndex >= device->obsRx->snifferGainCtrl->minGainIndex)
5462 {
5463 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SNRX_MANUAL_GAIN_INDEX, (gainIndex - MIN_SNRX_GAIN_TABLE_INDEX));
5464 device->obsRx->snifferGainCtrl->gainIndex = gainIndex;
5465 }
5466 else
5467 {
5468 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN,
5469 getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN));
5470 return MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN;
5471 }
5472 }
5473 else
5474 {
5475 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_CHANNEL,
5476 getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_CHANNEL));
5477 return MYKONOS_ERR_SETORXGAIN_INV_CHANNEL;
5478 }
5479
5480 return MYKONOS_ERR_OK;
5481 }
5482
5483 /**
5484 * \brief Gets the gain index of the currently enabled ObsRx channel
5485 *
5486 * The ObsRx data path can have multiple RF sources. This function will
5487 * read back the gain index of the currently enabled RF source. If the ObsRx
5488 * data path is disabled, an error is returned. If the functions uint8_t *gainIndex
5489 * parameter is a valid pointer, the gain index is returned at the pointers
5490 * address. Else, if the uint8_t *gainIndex pointer is NULL, the gainIndex read back
5491 * is stored in the device data structure.
5492 *
5493 * NOTE: if the observation source is chosen by ORX_MODE pins, it is possible that
5494 * the readback value will be incorrect if the obsRx channel changes while this function
5495 * reads the gain.
5496 *
5497 * <B>Dependencies</B>
5498 * - device->spiSettings
5499 * - device->profilesValid
5500 * - device->obsRx->orxGainCtrl->orx1GainIndex
5501 * - device->obsRx->orxGainCtrl->orx2GainIndex
5502 * - device->obsRx->snifferGainCtrl->gainIndex
5503 *
5504 * \param device Pointer to the Mykonos device data structure
5505 * \param gainIndex Return value of the current gain index for the currently enabled ObsRx channel.
5506 *
5507 * \retval MYKONOS_ERR_OK Function completed successfully
5508 * \retval MYKONOS_ERR_GETORX1GAIN_INV_POINTER The ObsRx profile is not valid in the device data structure
5509 * \retval MYKONOS_ERR_GETORX2GAIN_INV_POINTER The ObsRx profile is not valid in the device data structure
5510 * \retval MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER The sniffer profile is not valid in the device data structure
5511 * \retval MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED The observation receiver is currently disabled, can not read back gain index.
5512 */
MYKONOS_getObsRxGain(mykonosDevice_t * device,uint8_t * gainIndex)5513 mykonosErr_t MYKONOS_getObsRxGain(mykonosDevice_t *device, uint8_t *gainIndex)
5514 {
5515 /* Potential issue, if ARM is using loopback path when this function is called, it will likely readback loopback gain */
5516 uint8_t readObsRxPathEnabled = 0;
5517 uint8_t readObsRxGain = 0;
5518
5519 const uint8_t ORX1_EN = 0x01;
5520 const uint8_t ORX2_EN = 0x02;
5521 const uint8_t SNRX_EN = 0x04;
5522
5523 #if (MYKONOS_VERBOSE == 1)
5524 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxGain()\n");
5525 #endif
5526
5527 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_CONFIGURATION_CONTROL_1, &readObsRxPathEnabled);
5528
5529 /* If obsRx channel enabled, then read gain index */
5530 if (readObsRxPathEnabled > 0)
5531 {
5532 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GAIN_CTL_ORX_SNRX_GAIN, &readObsRxGain);
5533
5534 switch (readObsRxPathEnabled)
5535 {
5536 case 0x01:
5537 readObsRxGain += MIN_ORX_GAIN_TABLE_INDEX;
5538 break;
5539 case 0x02:
5540 readObsRxGain += MIN_ORX_GAIN_TABLE_INDEX;
5541 break;
5542 case 0x04:
5543 readObsRxGain += MIN_SNRX_GAIN_TABLE_INDEX;
5544 break;
5545 default:
5546 break;
5547 }
5548
5549 if (gainIndex != NULL)
5550 {
5551 *gainIndex = readObsRxGain;
5552 }
5553
5554 /* Store the gain index in the device's gain control data structure. */
5555
5556 if (readObsRxPathEnabled == ORX1_EN)
5557 {
5558 /* verify valid data structure pointers */
5559 if (device->profilesValid & ORX_PROFILE_VALID)
5560 {
5561 device->obsRx->orxGainCtrl->orx1GainIndex = readObsRxGain;
5562 }
5563 else
5564 {
5565 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORX1GAIN_INV_POINTER,
5566 getMykonosErrorMessage(MYKONOS_ERR_GETORX1GAIN_INV_POINTER));
5567 return MYKONOS_ERR_GETORX1GAIN_INV_POINTER;
5568 }
5569
5570 }
5571 else if (readObsRxPathEnabled == ORX2_EN)
5572 {
5573 /* verify valid pointers */
5574 if (device->profilesValid & ORX_PROFILE_VALID)
5575 {
5576 device->obsRx->orxGainCtrl->orx2GainIndex = readObsRxGain;
5577 }
5578 else
5579 {
5580 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORX2GAIN_INV_POINTER,
5581 getMykonosErrorMessage(MYKONOS_ERR_GETORX2GAIN_INV_POINTER));
5582 return MYKONOS_ERR_GETORX2GAIN_INV_POINTER;
5583 }
5584
5585 }
5586 else if (readObsRxPathEnabled == SNRX_EN)
5587 {
5588 /* verify valid pointers */
5589 if (device->profilesValid & SNIFF_PROFILE_VALID)
5590 {
5591 device->obsRx->snifferGainCtrl->gainIndex = readObsRxGain;
5592 }
5593 else
5594 {
5595 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER,
5596 getMykonosErrorMessage(MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER));
5597 return MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER;
5598 }
5599 }
5600 else
5601 {
5602 /* ignore gain index for Tx loopback input into obsRx channel */
5603 }
5604 }
5605 else
5606 {
5607 CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED,
5608 getMykonosErrorMessage(MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED));
5609 return MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED;
5610 }
5611
5612 return MYKONOS_ERR_OK;
5613 }
5614
5615 /**
5616 * \brief Sets up the device ObsRx Automatic Gain Control (AGC) registers.
5617 *
5618 * Three data structures (of types mykonosAgcCfg_t, mykonosPeakDetAgcCfg_t, mykonosPowerMeasAgcCfg_t)
5619 * must be instantiated prior to calling this function. Valid ranges for data structure members
5620 * must also be provided.
5621 *
5622 *
5623 * <B>Dependencies:</B>
5624 * - device->spiSettings
5625 * - device->spiSettings->chipSelectIndex
5626 * - device->obsRx->orxAgcCtrl->agcRx1MaxGainIndex
5627 * - device->obsRx->orxAgcCtrl->agcRx1MinGainIndex
5628 * - device->obsRx->orxAgcCtrl->agcRx2MaxGainIndex
5629 * - device->obsRx->orxAgcCtrl->agcRx2MinGainIndex
5630 * - device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex
5631 * - device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex
5632 * - device->obsRx->orxAgcCtrl->agcObsRxSelect
5633 * - device->obsRx->orxAgcCtrl->agcPeakThresholdMode
5634 * - device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease
5635 * - device->obsRx->orxAgcCtrl->agcGainUpdateCounter
5636 * - device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay
5637 * - device->obsRx->orxAgcCtrl->agcPeakWaitTime
5638 * - device->obsRx->orxAgcCtrl->agcResetOnRxEnable
5639 * - device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter
5640 * - device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh
5641 * - device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh
5642 * - device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh
5643 * - device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh
5644 * - device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh
5645 * - device->obsRx->orxAgcCtrl->peakAgc->apdHighThreshExceededCnt
5646 * - device->obsRx->orxAgcCtrl->peakAgc->apdLowThreshExceededCnt
5647 * - device->obsRx->orxAgcCtrl->peakAgc->hb2HighThreshExceededCnt
5648 * - device->obsRx->orxAgcCtrl->peakAgc->hb2LowThreshExceededCnt
5649 * - device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt
5650 * - device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack
5651 * - device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery
5652 * - device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack
5653 * - device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery
5654 * - device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery
5655 * - device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack
5656 * - device->obsRx->orxAgcCtrl->peakAgc->hb2FastAttack
5657 * - device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDetectEnable
5658 * - device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt
5659 * - device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThreshCnt
5660 * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh
5661 * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh
5662 * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh
5663 * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh
5664 * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack
5665 * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack
5666 * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery
5667 * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery
5668 * - device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration
5669 * - device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig
5670 *
5671 * \param device is structure pointer to the Mykonos data structure containing settings
5672 * The pointer to the Mykonos AGC data structure containing settings is checked for a null pointer
5673 * to ensure it has been initialized. If not an error is thrown.
5674 *
5675 * \retval Returns MYKONOS_ERR=pass, !MYKONOS_ERR=fail
5676 * \retval MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT
5677 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT
5678 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT
5679 * \retval MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX
5680 * \retval MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX
5681 * \retval MYKONOS_ERR_INV_AGC_OBSRX_SELECT
5682 * \retval MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM
5683 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM
5684 * \retval MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY
5685 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION
5686 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG
5687 * \retval MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC
5688 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE
5689 * \retval MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE
5690 * \retval MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER
5691 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH
5692 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH
5693 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH
5694 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH
5695 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP
5696 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP
5697 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP
5698 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP
5699 * \retval MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE
5700 * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM
5701 * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM
5702 * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM
5703 * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM
5704 * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM
5705 * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM
5706 * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM
5707 * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM
5708 * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM
5709 * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM
5710 * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE
5711 * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT
5712 * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT
5713 */
MYKONOS_setupObsRxAgc(mykonosDevice_t * device)5714 mykonosErr_t MYKONOS_setupObsRxAgc(mykonosDevice_t *device)
5715 {
5716 /* Current configuration does not support AGC on ORx channel */
5717 uint8_t decPowerConfig = 0;
5718 uint8_t lower1ThreshGainStepRegValue = 0;
5719 uint8_t powerThresholdsRegValue = 0;
5720 uint8_t hb2OvldCfgRegValue = 0;
5721 uint8_t agcGainUpdateCtr[3] = {0};
5722
5723 #if (MYKONOS_VERBOSE == 1)
5724 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupObsRxAgc()\n");
5725 #endif
5726
5727 /* Check mykonosAgcCfg_t device->obsRx->orxAgcCtrl pointer for initialization */
5728 if (device->obsRx->orxAgcCtrl == NULL)
5729 {
5730 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT,
5731 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT));
5732 return MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT;
5733 }
5734
5735 /* Check mykonosPeakDetAgcCfg_t device->orx->orxAgcCtrl->peakAgc pointer for initialization */
5736 if (device->obsRx->orxAgcCtrl->peakAgc == NULL)
5737 {
5738 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT,
5739 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT));
5740 return MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT;
5741 }
5742
5743 /* Check mykonosPowerMeasAgcCfg_t device->obsRx->orxAgcCtrl->powerAgc pointer for initialization */
5744 if (device->obsRx->orxAgcCtrl->powerAgc == NULL)
5745 {
5746 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT,
5747 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT));
5748 return MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT;
5749 }
5750
5751 /* Range check agcObsRxMaxGainIndex versus gain table limits and agcObsRxMinGainIndex */
5752 if ((device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex > device->obsRx->snifferGainCtrl->maxGainIndex) ||
5753 (device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex < device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex))
5754 {
5755 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX,
5756 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX));
5757 return MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX;
5758 }
5759 else
5760 {
5761 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MAX_GAIN_INDEX,
5762 (device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES));
5763 }
5764
5765 /* Range check agcObsRxMinGainIndex versus gain table limits and agcObsRxMaxGainIndex */
5766 if ((device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex < device->obsRx->snifferGainCtrl->minGainIndex) ||
5767 (device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex < device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex))
5768 {
5769 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX,
5770 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX));
5771 return MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX;
5772 }
5773 else
5774 {
5775 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MIN_GAIN_INDEX,
5776 (device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES));
5777 }
5778
5779 /* Range check agcObsRxSelect. Sniffer only support. Sniffer is selected if value is 0 or 1. 2 or 3 select ORx1/ORx2 respectively */
5780 if (device->obsRx->orxAgcCtrl->agcObsRxSelect > 1)
5781 {
5782 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_SELECT,
5783 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_SELECT));
5784 return MYKONOS_ERR_INV_AGC_OBSRX_SELECT;
5785 }
5786 else
5787 {
5788 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_ACTIVE, device->obsRx->orxAgcCtrl->agcObsRxSelect);
5789 }
5790
5791 /* Range check for agcGainUpdateCounter (22-bit) */
5792 if ((device->obsRx->orxAgcCtrl->agcGainUpdateCounter > 0x3FFFFF) ||
5793 (device->obsRx->orxAgcCtrl->agcGainUpdateCounter < 1))
5794 {
5795 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM,
5796 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM));
5797 return MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM;
5798 }
5799 else
5800 {
5801 /* Split agcGainUpdateCounter into three values */
5802 agcGainUpdateCtr[0] = (uint8_t)(device->obsRx->orxAgcCtrl->agcGainUpdateCounter);
5803 agcGainUpdateCtr[1] = (uint8_t)(device->obsRx->orxAgcCtrl->agcGainUpdateCounter >> 8);
5804 agcGainUpdateCtr[2] = (uint8_t)(device->obsRx->orxAgcCtrl->agcGainUpdateCounter >> 16);
5805
5806 /* Write two bytes directly due. Third word has its upper two bits masked off. */
5807 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_1, agcGainUpdateCtr[0]);
5808 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_2, agcGainUpdateCtr[1]);
5809 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_3, agcGainUpdateCtr[2], 0x3F, 0);
5810 }
5811
5812 /* Range check on agcPeakWaitTime (5-bit) */
5813 if ((device->obsRx->orxAgcCtrl->agcPeakWaitTime > 0x1F) ||
5814 (device->obsRx->orxAgcCtrl->agcPeakWaitTime < 0x02))
5815 {
5816 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM,
5817 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM));
5818 return MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM;
5819 }
5820 else
5821 {
5822 /* Write agcPeakWaitTime */
5823 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_CFG_2, device->obsRx->orxAgcCtrl->agcPeakWaitTime, 0x1F, 0);
5824 }
5825
5826 /* Range check for agcSlowLoopSettlingDelay (7-bit) */
5827 if (device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay > 0x7F)
5828 {
5829 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY,
5830 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY));
5831 return MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY;
5832 }
5833 else
5834 {
5835 /* Write agcSlowLoopSettlingDelay */
5836 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOOP_CFG, device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay, 0x7F, 0);
5837 }
5838
5839 /* Range check for pmdMeasDuration */
5840 if ((uint32_t)(1 << (3 + device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration)) >= (device->obsRx->orxAgcCtrl->agcGainUpdateCounter))
5841 {
5842 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION,
5843 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION));
5844 return MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION;
5845 }
5846 else
5847 {
5848 /* Write pmdMeasDuration */
5849 CMB_SPIWriteField(device->spiSettings, MYKONOS_SNIFFER_DEC_POWER_CONFIG_2, device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration, 0x0F, 0);
5850 }
5851
5852 /* Range check for pmdMeasConfig */
5853 if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig > 0x3)
5854 {
5855 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG,
5856 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG));
5857 return MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG;
5858 }
5859 else
5860 {
5861 if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 0)
5862 {
5863 decPowerConfig = 0x0; /* Dec Pwr measurement disable */
5864 }
5865 else if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 1)
5866 {
5867 decPowerConfig = 0x3; /* Dec Pwr measurement enable, HB2 for decPwr measurement */
5868 }
5869 else if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 2)
5870 {
5871 decPowerConfig = 0x5; /* Dec Pwr measurement enable, RFIR for decPwr measurement */
5872 }
5873 else if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 3)
5874 {
5875 decPowerConfig = 0x11; /* Dec Pwr measurement enable, BBDC2 for decPwr measurement */
5876 }
5877 /* Write pmdMeasConfig */
5878 CMB_SPIWriteByte(device->spiSettings, MYKONOS_SNIFFER_DEC_POWER_CONFIG_1, decPowerConfig);
5879 }
5880
5881 /* Range check agcLowThsPreventGainIncrease (1-bit) */
5882 if (device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease > 1)
5883 {
5884 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC,
5885 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC));
5886 return MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC;
5887 }
5888 else
5889 {
5890 /* Write agcLowThsPreventGainIncrease */
5891 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOCK_LEV_THRSH, device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease, 0x80, 7);
5892 }
5893
5894 /* Range check agcPeakThresholdMode (1-bit), */
5895 if (device->obsRx->orxAgcCtrl->agcPeakThresholdMode > 1)
5896 {
5897 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE,
5898 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE));
5899 return MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE;
5900 }
5901 else
5902 {
5903 /* Save to lower1ThreshGainStepRegValue register variable */
5904 lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->agcPeakThresholdMode << 5);
5905 }
5906
5907 /* Range check agcResetOnRxEnable (1-bit) */
5908 if (device->obsRx->orxAgcCtrl->agcResetOnRxEnable > 1)
5909 {
5910 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE,
5911 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE));
5912 return MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE;
5913 }
5914 else
5915 {
5916 /* Write agcResetOnRxEnable */
5917 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_3, (uint8_t)(device->obsRx->orxAgcCtrl->agcResetOnRxEnable << 7), 0x80, 0);
5918 }
5919
5920 /* Range check agcEnableSyncPulseForGainCounter (1-bit) */
5921 if (device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter > 1)
5922 {
5923 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER,
5924 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER));
5925 return MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER;
5926 }
5927 else
5928 {
5929 /* Write agcEnableSyncPulseForGainCounter */
5930 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOOP_CFG, (uint8_t)(device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter << 7), 0x80, 0);
5931 }
5932
5933 /* WRITE REGISTERS FOR THE AGC POWER MEASUREMENT DETECTOR (PMD) STRUCTURE */
5934
5935 /* Range check pmdLowerHighThresh (7-bit) vs 0x7F and pmdUpperLowThresh */
5936 if ((device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh <= device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh) ||
5937 device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh > 0x7F)
5938 {
5939 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH,
5940 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH));
5941 return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH;
5942 }
5943 else
5944 {
5945 /* Write pmdLowerHighThresh */
5946 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOCK_LEV_THRSH, device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh, 0x7F, 0);
5947 }
5948
5949 /* Range check pmdUpperLowThresh (7-bit): Comparison to pmdLowerHigh done earlier */
5950 if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh > 0x7F)
5951 {
5952 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH,
5953 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH));
5954 return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH;
5955 }
5956 else
5957 {
5958 /* Write pmdUpperLowThresh */
5959 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_LOCK_LEVEL, device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh);
5960 }
5961
5962 /* Range check pmdLowerLowThresh (4-bit) */
5963 if (device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh > 0xF)
5964 {
5965 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH,
5966 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH));
5967 return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH;
5968 }
5969 else
5970 {
5971 /* Write pmdUpperLowThresh to temp variable */
5972 powerThresholdsRegValue |= device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh;
5973 }
5974
5975 /* Range check pmdUpperHighThresh (4-bit) */
5976 if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh > 0xF)
5977 {
5978 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH,
5979 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH));
5980 return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH;
5981 }
5982 else
5983 {
5984 /* Write pmdUpperHighThresh to temp var, then to register */
5985 powerThresholdsRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh << 4);
5986 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_POWER_THRSH, powerThresholdsRegValue);
5987 }
5988
5989 /* Range check pmdUpperHighGainStepAttack (5-bit) */
5990 if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack > 0x1F)
5991 {
5992 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP,
5993 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP));
5994 return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP;
5995 }
5996 else
5997 {
5998 /* Write pmdUpperHighGainStepAttack */
5999 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UPPER1_THRSH_GAIN_STEP, device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack, 0x1F, 0);
6000 }
6001
6002 /* Range check pmdLowerLowGainStepRecovery (5-bit) */
6003 if (device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery > 0x1F)
6004 {
6005 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP,
6006 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP));
6007 return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP;
6008 }
6009 else
6010 {
6011 /* Write pmdLowerLowGainStepRecovery to temp var, then to register */
6012 lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery);
6013 }
6014
6015 /* Range check pmdUpperLowGainStepRecovery (5-bit) */
6016 if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack > 0x1F)
6017 {
6018 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP,
6019 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP));
6020 return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP;
6021 }
6022 else
6023 {
6024 /* Write pmdUpperLowGainStepRecovery to register */
6025 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UPPER0_THRSH_GAIN_STEP, device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack);
6026 }
6027
6028 /* Range check pmdLowerHighGainStepRecovery (5-bit) */
6029 if (device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery > 0x1F)
6030 {
6031 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP,
6032 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP));
6033 return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP;
6034 }
6035 else
6036 {
6037 /* Write pmdLowerLowGainStepRecovery to temp var, then to register */
6038 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOWER0_THRSH_GAIN_STEP, device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery);
6039 }
6040
6041 /* WRITE REGISTERS FOR THE AGC PEAK DETECTOR (APD/HB2) STRUCTURE */
6042
6043 /* Range check apdFastAttack and hb2FastAttack (1-bit) */
6044 if ((device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack > 0x1) ||
6045 (device->obsRx->orxAgcCtrl->peakAgc->hb2FastAttack > 0x1))
6046 {
6047 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE,
6048 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE));
6049 return MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE;
6050 }
6051 else
6052 {
6053 /* Write pmdLowerLowGainStepRecovery to temp var, then to register */
6054 lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack << 7);
6055 lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->hb2FastAttack << 6);
6056 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOWER1_THRSH_GAIN_STEP, lower1ThreshGainStepRegValue);
6057 }
6058
6059 /* Range check apdHighThresh */
6060 if ((device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh > 0x3F) ||
6061 (device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh <= device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh))
6062 {
6063 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM,
6064 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM));
6065 return MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM;
6066 }
6067 else
6068 {
6069 /* Write apdHighThresh */
6070 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_ULB_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh, 0X3F, 0);
6071 }
6072
6073 /* Range check apdLowThresh */
6074 if ((device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh > 0x3F) ||
6075 (device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh < device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh))
6076 {
6077 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM,
6078 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM));
6079 return MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM;
6080 }
6081 else
6082 {
6083 /* write apdLowThresh */
6084 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_LLB_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh, 0x3F, 0);
6085 }
6086
6087 /* Range check hb2HighThresh */
6088 if (device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh < device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh)
6089 {
6090 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM,
6091 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM));
6092 return MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM;
6093 }
6094 else
6095 {
6096 /* write hb2HighThresh */
6097 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_UPPER_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh);
6098 }
6099
6100 /* Range check hb2LowThresh */
6101 if (device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh > device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh)
6102 {
6103 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM,
6104 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM));
6105 return MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM;
6106 }
6107 else
6108 {
6109 /* write hb2LowThresh */
6110 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_LOWER_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh);
6111 }
6112
6113 /* Range check hb2VeryLowThresh */
6114 if (device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh > device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh)
6115 {
6116 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM,
6117 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM));
6118 return MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM;
6119 }
6120 else
6121 {
6122 /* write hb2VeryLowThresh */
6123 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_VERYLOW_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh);
6124 }
6125
6126 /* Write threshold counter values for apdHigh/apdLow/hb2High/hb2Low/hb2VeryLow */
6127 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ULB_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdHighThreshExceededCnt);
6128 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LLB_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdLowThreshExceededCnt);
6129 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_HIGH_OVRG_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2HighThreshExceededCnt);
6130 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_LOW_OVRG_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2LowThreshExceededCnt);
6131 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_VERYLOW_OVRG_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt);
6132
6133 /* Range check on apdHighGainStepAttack (5-bit) */
6134 if (device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack > 0x1F)
6135 {
6136 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM,
6137 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM));
6138 return MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM;
6139 }
6140 else
6141 {
6142 /* Write apdHighGainStepAttack */
6143 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_1, device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack);
6144 }
6145
6146 /* Range check on apdLowGainStepRecovery (5-bit) */
6147 if (device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery > 0x1F)
6148 {
6149 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM,
6150 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM));
6151 return MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM;
6152 }
6153 else
6154 {
6155 /* Write apdLowGainStepRecovery */
6156 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_4, device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery);
6157 }
6158
6159 /* Range check on hb2HighGainStepAttack (5-bit) */
6160 if (device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack > 0x1F)
6161 {
6162 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM,
6163 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM));
6164 return MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM;
6165 }
6166 else
6167 {
6168 /* Write hb2HighGainStepAttack */
6169 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_2, device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack);
6170 }
6171
6172 /* Range check on hb2LowGainStepRecovery (5-bit) */
6173 if (device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery > 0x1F)
6174 {
6175 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM,
6176 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM));
6177 return MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM;
6178 }
6179 else
6180 {
6181 /* Write hb2LowGainStepRecovery */
6182 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_5, device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery);
6183 }
6184
6185 /* Range check on hb2VeryLowGainStepRecovery (5-bit) */
6186 if (device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery > 0x1F)
6187 {
6188 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM,
6189 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM));
6190 return MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM;
6191 }
6192 else
6193 {
6194 /* Write hb2VeryLowGainStepRecovery */
6195 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_6, device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery);
6196 }
6197
6198 /* Range Check on hb2OverloadDetectEnable */
6199 if (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDetectEnable > 0x1)
6200 {
6201 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE,
6202 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE));
6203 return MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE;
6204 }
6205
6206 /* Range Check on hb2OverloadDetectEnable */
6207 if (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt > 0x7)
6208 {
6209 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT,
6210 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT));
6211 return MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT;
6212 }
6213
6214 /* Range Check on hb2OverloadDetectEnable */
6215 if (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThreshCnt > 0xF)
6216 {
6217 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT,
6218 getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT));
6219 return MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT;
6220 }
6221 else
6222 {
6223 /* Write the hb2OvldCfgRegValue, the combination of hb2OverloadThreshCnt, hb2OverloadDurationCnt, and hb2OverloadDetectEnable */
6224 hb2OvldCfgRegValue = (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThreshCnt) |
6225 (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt << 4) |
6226 (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDetectEnable << 7);
6227 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_CFG, hb2OvldCfgRegValue);
6228 }
6229
6230 /* Hard-coded value for the ADC overload configuration. Sets the HB2 offset to -6dB.*/
6231 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_ADC_OVRLD_CFG, 0x18);
6232 /* Hard-coded value for APD decay setting. Setting allows for the quickest settling time of peak detector */
6233 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_BLOCK_DET_DECAY, 0x0);
6234
6235 /* performing a soft reset */
6236 return MYKONOS_resetRxAgc(device);
6237 }
6238
6239 /**
6240 * \brief Enables or disables the ObsRx slow loop gain counter to use the sync pulse
6241 *
6242 * <B>Dependencies:</B>
6243 * - device->spiSettings
6244 *
6245 * \param device is structure pointer to the Mykonos data structure containing the device SPI settings
6246 * \param enable is a uint8_t data type where '0' = disable ObsRx gain counter from using sync pulse, '1' = enable ObsRx gain. All other values will throw an error.
6247 * counter to use the sync pulse. This value is written back to the device data structure for storage.
6248 *
6249 * \retval MYKONOS_ERR_OK Function completed successfully
6250 */
MYKONOS_enableObsRxGainCtrSyncPulse(mykonosDevice_t * device,uint8_t enable)6251 mykonosErr_t MYKONOS_enableObsRxGainCtrSyncPulse(mykonosDevice_t *device, uint8_t enable)
6252 {
6253 const uint8_t syncPulseBitMask = 0x80;
6254 uint8_t enableBit = 0;
6255
6256 #if (MYKONOS_VERBOSE == 1)
6257 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableObsRxGainCtrSyncPulse()\n");
6258 #endif
6259
6260 enableBit = (enable > 0) ? 1 : 0;
6261
6262 /* read, modify, write ObsRx gain counter sync pulse enable bit */
6263 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOOP_CFG, enableBit, syncPulseBitMask, 7);
6264
6265 return MYKONOS_ERR_OK;
6266 }
6267
6268 /**
6269 * \brief Configures the ObsRx gain control mode
6270 *
6271 * <B>Dependencies:</B>
6272 * - device->spiSettings
6273 * - device->obsRx->orxGainCtrl->gainMode
6274 *
6275 * \param device is structure pointer to the Mykonos data structure containing settings
6276 * \param mode is a mykonosGainMode_t enumerated gain control mode type
6277 *
6278 * When the mode enumerated type is passed, the ObsRx gain mode is set to this value and the
6279 * ObsRX agcType mykonosAgcCfg_t structure member is updated with the new value
6280 *
6281 * \retval MYKONOS_ERR_OK Function completed successfully
6282 * \retval MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM Invalid Observation Rx Gain control mode selected (use mykonosGainMode_t ENUM values)
6283 */
MYKONOS_setObsRxGainControlMode(mykonosDevice_t * device,mykonosGainMode_t mode)6284 mykonosErr_t MYKONOS_setObsRxGainControlMode(mykonosDevice_t *device, mykonosGainMode_t mode)
6285 {
6286 const uint8_t ORX_GAIN_TYPE_MASK = 0x3;
6287
6288 #if (MYKONOS_VERBOSE == 1)
6289 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxGainControlMode()\n");
6290 #endif
6291
6292 /* performing gain type check */
6293 switch (mode)
6294 {
6295 case MGC:
6296 break;
6297 case AGC:
6298 break;
6299 case HYBRID:
6300 break;
6301 default:
6302 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM,
6303 getMykonosErrorMessage(MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM));
6304 return MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM;
6305 }
6306
6307 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_CFG_1, mode, ORX_GAIN_TYPE_MASK, 0);
6308
6309 /* writing mode setting to data structure */
6310 if ((device->profilesValid & ORX_PROFILE_VALID) > 0)
6311 {
6312 device->obsRx->orxGainCtrl->gainMode = mode;
6313 }
6314
6315 return MYKONOS_ERR_OK;
6316 }
6317
6318 /**
6319 * \brief Performs a power measurement in the ObsRx digital data path.
6320 *
6321 * Due to interdependencies between the AGC and power measurement the power measurement duration and
6322 * where the measurement is taken is variable.
6323 * The location of the power measurement is given by device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig
6324 * The number of samples the power measurement uses is given by 8*2^(device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig) at the IQ rate,
6325 * if measured at RFIR output. This number of samples must be less than the agcGainUpdateCounter.
6326 * If the receiver is disabled during the power measurement, this function returns a 0 value for rx2DecPower_mdBFS
6327 *
6328 * The resolution of this function is 0.25dB.
6329 * The dynamic range of this function is 40dB. Signals lower than 40dBFS may not be measured accurately.
6330 *
6331 * <B>Dependencies</B>
6332 * - device->spiSettings
6333 * - device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig
6334 * - device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig
6335 *
6336 * \param device Pointer to the Mykonos data structure
6337 * \param obsRxDecPower_mdBFS Pointer to store the Rx1 decimated power return. Value returned in mdBFS
6338 *
6339 * \retval MYKONOS_ERR_OK Function completed successfully
6340 */
MYKONOS_getObsRxDecPower(mykonosDevice_t * device,uint16_t * obsRxDecPower_mdBFS)6341 mykonosErr_t MYKONOS_getObsRxDecPower(mykonosDevice_t *device, uint16_t *obsRxDecPower_mdBFS)
6342 {
6343 uint8_t obsRxDecPower_dBFS = 0;
6344
6345 #if (MYKONOS_VERBOSE == 1)
6346 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxDecPower()\n");
6347 #endif
6348
6349 /* read ObsRx Dec Power Measurement */
6350 if (obsRxDecPower_mdBFS != NULL)
6351 {
6352 CMB_SPIReadByte(device->spiSettings, MYKONOS_SNIFFER_DECIMATED_PWR, &obsRxDecPower_dBFS);
6353 *obsRxDecPower_mdBFS = (uint16_t)(obsRxDecPower_dBFS * 250); /* 250 = 1000 * 0.25dB */
6354 }
6355 else
6356 {
6357 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM,
6358 getMykonosErrorMessage(MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM));
6359 return MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM;
6360 }
6361
6362 return MYKONOS_ERR_OK;
6363 }
6364
6365 /*
6366 *****************************************************************************
6367 * Tx Data path functions
6368 *****************************************************************************
6369 */
6370
6371 /**
6372 * \brief Sets the Tx1 RF output Attenuation
6373 *
6374 * <B>Dependencies</B>
6375 * - device->spiSettings
6376 * - device->spiSettings->chipSelectIndex
6377 * - device->tx->txAttenStepSize
6378 *
6379 * \param device Pointer to the Mykonos device's data structure
6380 * \param tx1Attenuation_mdB The desired TxAttenuation in milli-dB (Range: 0 to 41950 mdB)
6381 *
6382 * \retval MYKONOS_ERR_OK Function completed successfully
6383 * \retval MYKONOS_ERR_SETTX1ATTEN_INV_PARM tx1Attenuation_mdB parameter is out of range (0 - 41950)
6384 * \retval MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM device->tx->txAttenStepSize is not a valid enum value
6385 */
MYKONOS_setTx1Attenuation(mykonosDevice_t * device,uint16_t tx1Attenuation_mdB)6386 mykonosErr_t MYKONOS_setTx1Attenuation(mykonosDevice_t *device, uint16_t tx1Attenuation_mdB)
6387 {
6388 uint16_t data = 0;
6389 uint16_t attenStepSizeDiv = 50;
6390
6391 #if (MYKONOS_VERBOSE == 1)
6392 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setTx1Attenuation()\n");
6393 #endif
6394
6395 /* check input parameter is in valid range */
6396 if (tx1Attenuation_mdB > 41950)
6397 {
6398 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX1ATTEN_INV_PARM,
6399 getMykonosErrorMessage(MYKONOS_ERR_SETTX1ATTEN_INV_PARM));
6400 return MYKONOS_ERR_SETTX1ATTEN_INV_PARM;
6401 }
6402
6403 switch (device->tx->txAttenStepSize)
6404 {
6405 case TXATTEN_0P05_DB:
6406 attenStepSizeDiv = 50;
6407 break;
6408 case TXATTEN_0P1_DB:
6409 attenStepSizeDiv = 100;
6410 break;
6411 case TXATTEN_0P2_DB:
6412 attenStepSizeDiv = 200;
6413 break;
6414 case TXATTEN_0P4_DB:
6415 attenStepSizeDiv = 400;
6416 break;
6417 default:
6418 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM,
6419 getMykonosErrorMessage(MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM));
6420 return MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM;
6421
6422 }
6423
6424 data = (tx1Attenuation_mdB / attenStepSizeDiv);
6425
6426 /* Write MSB bits followed by LSB bits, TxAtten updates when [7:0] written */
6427 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_1, ((data >> 8) & 0x03));
6428 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_0, (data & 0xFF));
6429
6430 return MYKONOS_ERR_OK;
6431 }
6432
6433 /**
6434 * \brief Sets the Tx2 RF output Attenuation (Step size is 0.05dB.)
6435 *
6436 * <B>Dependencies</B>
6437 * - device->spiSettings
6438 * - device->spiSettings->chipSelectIndex
6439 * - device->tx->txAttenStepSize
6440 *
6441 * \param device Pointer to the Mykonos device's data structure
6442 * \param tx2Attenuation_mdB The desired TxAttenuation in milli-dB
6443 * (Range: 0 to 41950 mdB)
6444 *
6445 * \retval MYKONOS_ERR_OK Function completed successfully
6446 * \retval MYKONOS_ERR_SETTX2ATTEN_INV_PARM tx2Attenuation_mdB parameter is out of range (0 - 41950)
6447 * \retval MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM device->tx->txAttenStepSize is not a valid enum value
6448 */
MYKONOS_setTx2Attenuation(mykonosDevice_t * device,uint16_t tx2Attenuation_mdB)6449 mykonosErr_t MYKONOS_setTx2Attenuation(mykonosDevice_t *device, uint16_t tx2Attenuation_mdB)
6450 {
6451 uint16_t attenStepSizeDiv = 50;
6452 uint16_t data = 0;
6453 //const uint8_t SPI_TXATTEN_MODE = 0x01;
6454
6455 #if (MYKONOS_VERBOSE == 1)
6456 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setTx2Attenuation()\n");
6457 #endif
6458
6459 /* check input parameter is in valid range */
6460 if (tx2Attenuation_mdB > 41950)
6461 {
6462 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX2ATTEN_INV_PARM,
6463 getMykonosErrorMessage(MYKONOS_ERR_SETTX2ATTEN_INV_PARM));
6464 return MYKONOS_ERR_SETTX2ATTEN_INV_PARM;
6465 }
6466
6467 switch (device->tx->txAttenStepSize)
6468 {
6469 case TXATTEN_0P05_DB:
6470 attenStepSizeDiv = 50;
6471 break;
6472 case TXATTEN_0P1_DB:
6473 attenStepSizeDiv = 100;
6474 break;
6475 case TXATTEN_0P2_DB:
6476 attenStepSizeDiv = 200;
6477 break;
6478 case TXATTEN_0P4_DB:
6479 attenStepSizeDiv = 400;
6480 break;
6481 default:
6482 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM,
6483 getMykonosErrorMessage(MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM));
6484 return MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM;
6485 }
6486
6487 data = (tx2Attenuation_mdB / attenStepSizeDiv);
6488
6489 /* Write MSB bits followed by LSB bits, TxAtten updates when [7:0] written */
6490 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_1, ((data >> 8) & 0x03));
6491 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_0, (data & 0xFF));
6492
6493 return MYKONOS_ERR_OK;
6494 }
6495
6496 /**
6497 * \brief Reads back the Tx1 RF output Attenuation
6498 *
6499 * This function reads back the TxAttenuation setting currently applied to the transmit chain.
6500 * The function will work with SPI mode or pin controlled TxAtten mode using the increment/decrement GPIO
6501 * pins. For the readback value to be valid the Tx data path must be powered up. If the Tx data path
6502 * is powered down or radioOff state, the last TxAtten setting while the Tx was powered up will be
6503 * read back.
6504 *
6505 * <B>Dependencies</B>
6506 * - device->spiSettings
6507 * - device->spiSettings->chipSelectIndex
6508 *
6509 * \param device Pointer to the Mykonos device's data structure
6510 * \param tx1Attenuation_mdB The readback value of the Tx1 Attenuation in milli-dB (Range: 0 to 41950 mdB)
6511 *
6512 * \retval MYKONOS_ERR_OK Function completed successfully
6513 * \retval MYKONOS_ERR_GETTX1ATTEN_NULL_PARM tx1Attenuation_mdB return parameter has NULL pointer
6514 */
MYKONOS_getTx1Attenuation(mykonosDevice_t * device,uint16_t * tx1Attenuation_mdB)6515 mykonosErr_t MYKONOS_getTx1Attenuation(mykonosDevice_t *device, uint16_t *tx1Attenuation_mdB)
6516 {
6517 uint8_t txAttenLsb = 0;
6518 uint8_t txAttenMsb = 0;
6519 uint16_t attenStepSizeDiv = 50;
6520
6521 #if (MYKONOS_VERBOSE == 1)
6522 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTx1Attenuation()\n");
6523 #endif
6524
6525 /* check return parameter pointer is not NULL pointer */
6526 if (tx1Attenuation_mdB == NULL)
6527 {
6528 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1ATTEN_NULL_PARM,
6529 getMykonosErrorMessage(MYKONOS_ERR_GETTX1ATTEN_NULL_PARM));
6530 return MYKONOS_ERR_GETTX1ATTEN_NULL_PARM;
6531 }
6532
6533 /* Write TxAtten read back reg to update readback values, then read Tx1Atten */
6534 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_1_READBACK, 0x00);
6535 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_0_READBACK, &txAttenLsb, 0xFF, 0);
6536 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_1_READBACK, &txAttenMsb, 0x03, 0);
6537
6538 /* Readback word always reads back with 0.05dB resolution */
6539 *tx1Attenuation_mdB = (uint16_t)(((uint16_t)(txAttenLsb) | ((uint16_t)(txAttenMsb) << 8)) * attenStepSizeDiv);
6540
6541 return MYKONOS_ERR_OK;
6542 }
6543
6544 /**
6545 * \brief Reads back the Tx2 RF output Attenuation
6546 *
6547 * This function reads back the TxAttenuation setting currently applied to the transmit chain.
6548 * The function will work with SPI mode or pin controlled TxAtten mode using the increment/decrement GPIO
6549 * pins. For the readback value to be valid the Tx data path must be powered up. If the Tx data path
6550 * is powered down or radioOff state, the last TxAtten setting while the Tx was powered up will be
6551 * read back.
6552 *
6553 * <B>Dependencies</B>
6554 * - device->spiSettings
6555 * - device->spiSettings->chipSelectIndex
6556 *
6557 * \param device Pointer to the Mykonos device's data structure
6558 * \param tx2Attenuation_mdB The readback value of the Tx2 Attenuation in milli-dB (Range: 0 to 41950 mdB)
6559 *
6560 * \retval MYKONOS_ERR_OK Function completed successfully
6561 * \retval MYKONOS_ERR_GETTX2ATTEN_NULL_PARM tx2Attenuation_mdB return parameter pointer is NULL
6562 */
MYKONOS_getTx2Attenuation(mykonosDevice_t * device,uint16_t * tx2Attenuation_mdB)6563 mykonosErr_t MYKONOS_getTx2Attenuation(mykonosDevice_t *device, uint16_t *tx2Attenuation_mdB)
6564 {
6565 uint8_t txAttenLsb = 0;
6566 uint8_t txAttenMsb = 0;
6567 uint16_t attenStepSizeDiv = 50;
6568
6569 #if (MYKONOS_VERBOSE == 1)
6570 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTx2Attenuation()\n");
6571 #endif
6572
6573 /* check return parameter pointer is not NULL pointer */
6574 if (tx2Attenuation_mdB == NULL)
6575 {
6576 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2ATTEN_NULL_PARM,
6577 getMykonosErrorMessage(MYKONOS_ERR_GETTX2ATTEN_NULL_PARM));
6578 return MYKONOS_ERR_GETTX2ATTEN_NULL_PARM;
6579 }
6580
6581 /* Write TxAtten read back reg to update readback values, then read Tx1Atten */
6582 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_1_READBACK, 0x00);
6583 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_0_READBACK, &txAttenLsb, 0xFF, 0);
6584 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_1_READBACK, &txAttenMsb, 0x03, 0);
6585
6586 /* Readback word always reads back with 0.05dB resolution */
6587 *tx2Attenuation_mdB = (uint16_t)(((uint16_t)(txAttenLsb) | ((uint16_t)(txAttenMsb) << 8)) * attenStepSizeDiv);
6588
6589 return MYKONOS_ERR_OK;
6590 }
6591
6592 /**
6593 * \brief Checks the Tx Filter over-range bit assignments for digital clipping in the Tx data path
6594 *
6595 * <B>Dependencies</B>
6596 * - device->spiSettings
6597 *
6598 * txFilterStatus bit-field assignments are:
6599 * txFilterStatus[0] = TFIR Ch1 Overflow
6600 * txFilterStatus[1] = HB1 Ch1 Overflow
6601 * txFilterStatus[2] = HB2 Ch1 Overflow
6602 * txFilterStatus[3] = QEC Ch1 Overflow
6603 * txFilterStatus[4] = TFIR Ch2 Overflow
6604 * txFilterStatus[5] = HB1 Ch2 Overflow
6605 * txFilterStatus[6] = HB2 Ch2 Overflow
6606 * txFilterStatus[7] = QEC Ch2 Overflow
6607 *
6608 * \param device Pointer to the Mykonos device's data structure
6609 * \param txFilterStatus is an 8-bit Tx filter over-range status bit-field
6610 *
6611 * \retval MYKONOS_ERR_OK Function completed successfully
6612 * \retval MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM Function txFilterStatus parameter pointer is NULL
6613 */
MYKONOS_getTxFilterOverRangeStatus(mykonosDevice_t * device,uint8_t * txFilterStatus)6614 mykonosErr_t MYKONOS_getTxFilterOverRangeStatus(mykonosDevice_t *device, uint8_t *txFilterStatus)
6615 {
6616
6617 #if (MYKONOS_VERBOSE == 1)
6618 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTxFilterOverRangeStatus()\n");
6619 #endif
6620
6621 if (txFilterStatus == NULL)
6622 {
6623 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM,
6624 getMykonosErrorMessage(MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM));
6625 return MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM;
6626 }
6627
6628 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_FILTER_OVERFLOW, txFilterStatus);
6629 return MYKONOS_ERR_OK;
6630 }
6631
6632 /**
6633 * \brief Enables/Disables the Tx NCO test tone
6634 *
6635 * This function enables/disables a digital numerically controlled oscillator
6636 * in the Mykonos Digital to create a test CW tone on Tx1 and Tx2 RF outputs.
6637 *
6638 * The TxAttenuation is forced in this function to max analog output power, but
6639 * the digital attenuation is backed off 6dB to make sure the digital filter
6640 * does not clip and cause spurs in the tx spectrum.
6641 *
6642 * <B>Dependencies</B>
6643 * - device->spiSettings
6644 * - device->profilesValid
6645 * - device->tx->txProfile->iqRate_kHz
6646 *
6647 * \param device Pointer to the Mykonos device's data structure
6648 * \param enable 0 = Disable Tx NCO, 1 = Enable Tx NCO on both transmitters
6649 * \param tx1ToneFreq_kHz Signed frequency in kHz of the desired Tx1 tone
6650 * \param tx2ToneFreq_kHz Signed frequency in kHz of the desired Tx2 tone
6651 *
6652 * \retval MYKONOS_ERR_OK Function completed successfully
6653 * \retval MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID Can not enable Tx NCO when Tx Profile is not enabled/valid
6654 * \retval MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID Tx1 NCO Tone frequency out of range (-IQrate/2 to IQrate/2)
6655 * \retval MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID Tx2 NCO Tone frequency out of range (-IQrate/2 to IQrate/2)
6656 */
MYKONOS_enableTxNco(mykonosDevice_t * device,uint8_t enable,int32_t tx1ToneFreq_kHz,int32_t tx2ToneFreq_kHz)6657 mykonosErr_t MYKONOS_enableTxNco(mykonosDevice_t *device, uint8_t enable, int32_t tx1ToneFreq_kHz, int32_t tx2ToneFreq_kHz)
6658 {
6659 int16_t tx1NcoTuneWord = 0;
6660 int16_t tx2NcoTuneWord = 0;
6661
6662 #if (MYKONOS_VERBOSE == 1)
6663 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableTxNco()\n");
6664 #endif
6665
6666 if (enable > 0)
6667 {
6668 if ((device->profilesValid & TX_PROFILE_VALID) == 0)
6669 {
6670 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID,
6671 getMykonosErrorMessage(MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID));
6672 return MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID;
6673 }
6674
6675 if ((tx1ToneFreq_kHz > ((int32_t)(device->tx->txProfile->iqRate_kHz) / 2)) || (tx1ToneFreq_kHz < ((int32_t)(device->tx->txProfile->iqRate_kHz) * -1 / 2)))
6676 {
6677 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID,
6678 getMykonosErrorMessage(MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID));
6679 return MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID;
6680 }
6681
6682 if ((tx2ToneFreq_kHz > ((int32_t)(device->tx->txProfile->iqRate_kHz) / 2)) || (tx2ToneFreq_kHz < ((int32_t)(device->tx->txProfile->iqRate_kHz) * -1 / 2)))
6683 {
6684 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID,
6685 getMykonosErrorMessage(MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID));
6686 return MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID;
6687 }
6688
6689 /* Force Tx output power to max analog output power, but 6dB digital */
6690 /* backoff to prevent the NCO from clipping the Tx PFIR filter */
6691 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_GAIN_0, 0x78);
6692 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX1_GAIN_1, 0x00, 0x3F, 0);
6693 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_GAIN_2, 0x0);
6694
6695 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_GAIN_0, 0x78);
6696 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX2_GAIN_1, 0x00, 0x3F, 0);
6697 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_GAIN_2, 0x0);
6698
6699 /* Enable manual Tx output power mode */
6700 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x0A, 0x0F, 0);
6701
6702 /* Set Tx NCO tuning words */
6703 tx1NcoTuneWord = (int16_t)(((int64_t)(tx1ToneFreq_kHz) << 16) / device->tx->txProfile->iqRate_kHz * -1);
6704 tx2NcoTuneWord = (int16_t)(((int64_t)(tx2ToneFreq_kHz) << 16) / device->tx->txProfile->iqRate_kHz * -1);
6705
6706 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_I_MSB, (uint8_t)((uint16_t)tx1NcoTuneWord >> 8));
6707 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_I_LSB, (tx1NcoTuneWord & 0xFF));
6708
6709 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_Q_MSB, (uint8_t)((uint16_t)tx2NcoTuneWord >> 8));
6710 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_Q_LSB, (tx2NcoTuneWord & 0xFF));
6711
6712 /* Enable Tx NCO - set [7] = 1 */
6713 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DIGITAL_TEST_BYTE_0, 1, 0x80, 7);
6714 }
6715 else
6716 {
6717 /* Disable Tx NCO - set [7] = 0 */
6718 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DIGITAL_TEST_BYTE_0, 0, 0x80, 7);
6719
6720 /* Enable normal Tx Atten table mode */
6721 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x05, 0x0F, 0);
6722 }
6723
6724 return MYKONOS_ERR_OK;
6725 }
6726
6727 /**
6728 * \brief Writes Mykonos device registers with settings for the PA Protection block.
6729 *
6730 * This function writes register settings for the Mykonos PA Protection Block.
6731 * This function does not enable the PA Protection functionality.
6732 * Note that independent control of PA protection for both Tx channels is not possible.
6733 * The PA Protection block allows for error flags to go high if the accumulated TX power in the data path
6734 * exceeds a programmable threshold level based on samples taken in a programmable duration.
6735 *
6736 * \post After calling this function the user will need to call MYKONOS_enablePaProtection(...)
6737 *
6738 * <B>Dependencies</B>
6739 * - device->spiSettings
6740 * - device->spiSettings->chipSelectIndex
6741 *
6742 * \param device Pointer to the Mykonos device's data structure
6743 * \param powerThreshold PA Protection Threshold sets the power level that, if detected in the TX data path, raises the PA error flags. The range is 0 to 4096.
6744 * To calculate the required setting for the power threshold:
6745 * powerThreshold = MAX_DAC_CODE * (10^((txPowerThresh_dBFS/10)))
6746 * For example: If the required dBFS for the threshold is -10 dBFS, then the powerThreshold passed should be 409.
6747 *
6748 * \param attenStepSize Attenuation Step Size sets the size of the attenuation step when Tx Atten Control is Enabled. The range is 0 to 128 with a resolution is 0.2dB/LSB.
6749 * \param avgDuration Averaging Duration for the TX data path power measurement. The range is 0 to 14 specified in number of cycles of the TX IQ Rate.
6750 * \param stickyFlagEnable "1" Enables the PA Error Flags to stay high after being triggered, even if the power decreases below threshold. "0" disables this functionality.
6751 * \param txAttenControlEnable "1" Enables autonomous attenuation changes in response to PA error flags. "0" disables this functionality.
6752 *
6753 * \retval MYKONOS_ERR_OK Function completed successfully
6754 * \retval MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION avgDuration parameter invalid (valid 0-15)
6755 * \retval MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP attenStepSize function parameter invalid (valid 0-127)
6756 */
MYKONOS_setupPaProtection(mykonosDevice_t * device,uint16_t powerThreshold,uint8_t attenStepSize,uint8_t avgDuration,uint8_t stickyFlagEnable,uint8_t txAttenControlEnable)6757 mykonosErr_t MYKONOS_setupPaProtection(mykonosDevice_t *device, uint16_t powerThreshold, uint8_t attenStepSize, uint8_t avgDuration, uint8_t stickyFlagEnable, uint8_t txAttenControlEnable)
6758 {
6759 uint8_t paProtectConfig = 0;
6760 uint8_t paProtectAttenCntl = 0;
6761
6762 const uint8_t PROTECT_AVG_DUR_MASK = 0x1E;
6763 const uint8_t STICKY_FLAG_EN_MASK = 0x40;
6764 const uint8_t ATT_STEP_MASK = 0xFE;
6765 const uint8_t PROTECT_ATT_EN_MASK = 0x01;
6766 const uint8_t AVG_DUR_MASK = 0x0F;
6767 const uint8_t ATT_STEP_SIZE = 0x7F;
6768
6769 #if (MYKONOS_VERBOSE == 1)
6770 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupPaProtection()\n");
6771 #endif
6772
6773 /* Overwrite PA Protection Config register data with averaging duration and sticky flag. Also performing range check on stickyFlagEnable and avgDuration */
6774 if (avgDuration > AVG_DUR_MASK)
6775 {
6776 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION,
6777 getMykonosErrorMessage(MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION));
6778 return MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION;
6779 }
6780
6781 if (attenStepSize > ATT_STEP_SIZE)
6782 {
6783 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP,
6784 getMykonosErrorMessage(MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP));
6785 return MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP;
6786 }
6787
6788 paProtectConfig = (PROTECT_AVG_DUR_MASK & (avgDuration << 1));
6789
6790 if (stickyFlagEnable > 0)
6791 {
6792 paProtectConfig |= (STICKY_FLAG_EN_MASK);
6793 }
6794
6795 paProtectAttenCntl = ATT_STEP_MASK & (attenStepSize << 1);
6796
6797 if (txAttenControlEnable > 0)
6798 {
6799 paProtectAttenCntl |= (PROTECT_ATT_EN_MASK);
6800 }
6801
6802 /* Clear and write all PA Protection setup registers */
6803 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_ATTEN_CONTROL, 0x00);
6804 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, 0x00);
6805 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_LSB, 0x00);
6806 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_MSB, 0x00);
6807
6808 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_ATTEN_CONTROL, paProtectAttenCntl);
6809 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, paProtectConfig);
6810 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_LSB, (powerThreshold & 0xFF));
6811 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_MSB, ((powerThreshold >> 8) & 0x0F));
6812
6813 return MYKONOS_ERR_OK;
6814 }
6815
6816 /**
6817 * \brief Enables the Mykonos PA Protection block according to the parameters passed in MYKONOS_setupPaProtection(...).
6818 *
6819 * This function enables the PA Protection block according to the parameters passed in MYKONOS_setupPaProtection(...)
6820 * The paProtectEnable signal enables the PA Protection block, allowing usage of the PA protection functions.
6821 *
6822 * \pre Before calling this function the user needs to setup the PA protection by calling MYKONOS_setupPaProtection(...)
6823 *
6824 * <B>Dependencies</B>
6825 * - device->spiSettings
6826 * - device->spiSettings->chipSelectIndex
6827 *
6828 * \param device Pointer to the Mykonos device's data structure
6829 * \param paProtectEnable "1" Enables the PA Protection block. "0" Disables the PA Protection block
6830 *
6831 * \retval MYKONOS_ERR_OK Function completed successfully
6832 */
MYKONOS_enablePaProtection(mykonosDevice_t * device,uint8_t paProtectEnable)6833 mykonosErr_t MYKONOS_enablePaProtection(mykonosDevice_t *device, uint8_t paProtectEnable)
6834 {
6835 uint8_t paProtectEnableReg = 0;
6836
6837 #if (MYKONOS_VERBOSE == 1)
6838 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enablePaProtection()\n");
6839 #endif
6840
6841 paProtectEnableReg = (paProtectEnable > 0) ? 1 : 0;
6842 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, paProtectEnableReg, 0x01, 0);
6843
6844 return MYKONOS_ERR_OK;
6845 }
6846
6847 /**
6848 * \brief Obtains an estimate of a TX channel's accumulated power over the sample duration provided in MYKONOS_setupPaProtection(...)
6849 *
6850 * This function uses the 'avgDuration' parameter provided in MYKONOS_setupPaProtection to set the number of samples to accumulate
6851 * to obtain an estimate for a TX channel specified by the 'channel' parameter.
6852 * A 12-bit field estimating the channel power is returned in the '*channelPower' pointer.
6853 * To obtain the dBFS value of the reading:
6854 * dBFS value = 10*log10(channelPower/MAX_DAC_CODE)
6855 * where MAX_DAC_CODE = 2^12 = 4096
6856 * For example: If channelPower is reading 409 then the channel power in dBFS is -10dBFS.
6857 *
6858 * <B>Dependencies</B>
6859 * - device->spiSettings
6860 * - device->spiSettings->chipSelectIndex
6861 *
6862 * \param device Point to the Mykonos device's data structure
6863 * \param channel Select the channel of interest. Only use TX1 (1) or TX2 (2) of mykonosTxChannels_t
6864 * \param *channelPower A pointer that stores the selected channels power. Read back is provided as a 12 bit value.
6865 *
6866 * \retval MYKONOS_ERR_OK Function completed successfully
6867 * \retval MYKONOS_ERR_GET_DAC_PWR_INV_POINTER Function channelPower parameter is a NULL pointer
6868 * \retval MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL Invalid Tx Channel passed in function channel parameter (TX1 or TX2)
6869 */
MYKONOS_getDacPower(mykonosDevice_t * device,mykonosTxChannels_t channel,uint16_t * channelPower)6870 mykonosErr_t MYKONOS_getDacPower(mykonosDevice_t *device, mykonosTxChannels_t channel, uint16_t *channelPower)
6871 {
6872 uint8_t channelPowerLsb = 0;
6873 uint8_t channelPowerMsb = 0;
6874
6875 const uint8_t CHAN_POWER_MSB_MASK = 0xF;
6876
6877 #if (MYKONOS_VERBOSE == 1)
6878 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDacPower()\n");
6879 #endif
6880
6881 if (channelPower == NULL)
6882 {
6883 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_DAC_PWR_INV_POINTER,
6884 getMykonosErrorMessage(MYKONOS_ERR_GET_DAC_PWR_INV_POINTER));
6885 return MYKONOS_ERR_GET_DAC_PWR_INV_POINTER;
6886 }
6887
6888 /* Set bit D5 to read the appropriate channel power */
6889 switch (channel)
6890 {
6891 case TX1:
6892 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, 0, 0x20, 5);
6893 break;
6894 case TX2:
6895 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, 1, 0x20, 5);
6896 break;
6897 default:
6898 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL,
6899 getMykonosErrorMessage(MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL));
6900 return MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL;
6901 }
6902
6903 /* SPI Write to register PA Protection power readback registers (write strobe) */
6904 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_LSB, 0x00);
6905
6906 /* SPI Read of the PA Protection power readback registers */
6907 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_LSB, &channelPowerLsb);
6908 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_MSB, &channelPowerMsb);
6909
6910 *channelPower = (channelPowerLsb | (((uint16_t)(channelPowerMsb & CHAN_POWER_MSB_MASK)) << 8));
6911
6912 return MYKONOS_ERR_OK;
6913 }
6914
6915 /**
6916 * \brief Returns PA Protection Error Flag Status
6917 *
6918 * This function provides a readback of the PA protection Error Flag Status through the '*errorFlagStatus' pointer
6919 *
6920 * <B>Dependencies</B>
6921 * - device->spiSettings
6922 * - device->spiSettings->chipSelectIndex
6923 *
6924 * \param device Point to the Mykonos device's data structure
6925 * \param errorFlagStatus Pointer to store the error flag status.
6926 * errorFlagStatus | error
6927 * -----------------|------------
6928 * 0 | indicates no PA Error Flags are high
6929 * 1 | indicates TX1 Error Flag
6930 * 2 | indicates TX2 Error Flag
6931 * 3 | indicates TX1 and TX2 Error Flags are high
6932 *
6933 *
6934 * \retval MYKONOS_ERR_OK Function completed successfully
6935 * \retval MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER Function errorFlagStatus parameter has NULL pointer
6936 */
MYKONOS_getPaProtectErrorFlagStatus(mykonosDevice_t * device,uint8_t * errorFlagStatus)6937 mykonosErr_t MYKONOS_getPaProtectErrorFlagStatus(mykonosDevice_t *device, uint8_t *errorFlagStatus)
6938 {
6939
6940 #if (MYKONOS_VERBOSE == 1)
6941 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getPaProtectErrorFlagStatus()\n");
6942 #endif
6943
6944 if (errorFlagStatus == NULL)
6945 {
6946 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER,
6947 getMykonosErrorMessage(MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER));
6948 return MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER;
6949 }
6950
6951 /* SPI Write to register PA Protection power readback registers (write strobe) */
6952 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_LSB, 0x00);
6953
6954 /* SPI Read of the PA Protection power readback registers */
6955 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_MSB, errorFlagStatus, 0x60, 5);
6956
6957 return MYKONOS_ERR_OK;
6958 }
6959
6960 /**
6961 * \brief Manually clears the PA Protection Error Flags.
6962 *
6963 * This function manually clears the PA Error Flags. The user must setup the PA Protection block to enable
6964 * sticky error flags. Sticky error flags require the user to clear the bit manually even if the accumulated power is
6965 * below the power threshold for the PA protection block.
6966 *
6967 * <B>Dependencies</B>
6968 * - device->spiSettings
6969 * - device->spiSettings->chipSelectIndex
6970 *
6971 * \param device Pointer to the Mykonos device's data structure
6972 *
6973 * \retval MYKONOS_ERR_OK Function completed successfully
6974 */
MYKONOS_clearPaErrorFlag(mykonosDevice_t * device)6975 mykonosErr_t MYKONOS_clearPaErrorFlag(mykonosDevice_t *device)
6976 {
6977 uint8_t paProtectConfig = 0;
6978
6979 const uint8_t PA_ERROR_CLEAR_MASK = 0x80;
6980
6981 #if (MYKONOS_VERBOSE == 1)
6982 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_clearPaErrorFlag()\n");
6983 #endif
6984
6985 /* SPI Read of the PA Protection power readback registers */
6986 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, &paProtectConfig);
6987
6988 /* SPI Write to self clear the PA Error Flags */
6989 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, (paProtectConfig | PA_ERROR_CLEAR_MASK));
6990
6991 return MYKONOS_ERR_OK;
6992 }
6993
6994 /**
6995 * \brief Helper function for return of character string based on 32-bit mykonosErr_t enum value
6996 *
6997 * To save codespace, these error strings are ifdef'd out unless the user
6998 * adds a define MYKONOS_VERBOSE to their workspace. This function can be
6999 * useful for debug. Each function also returns unique error codes to
7000 * make it easier to determine where the code broke.
7001 *
7002 * \param errorCode is enumerated error code value
7003 *
7004 * \return Returns character string based on enumerated value
7005 */
getMykonosErrorMessage(mykonosErr_t errorCode)7006 const char* getMykonosErrorMessage(mykonosErr_t errorCode)
7007 {
7008 #ifndef MYKONOS_VERBOSE
7009 return "";
7010
7011 #else
7012
7013 switch (errorCode)
7014 {
7015 case MYKONOS_ERR_OK:
7016 return "";
7017 case MYKONOS_ERR_INV_PARM:
7018 return "Mykonos: Invalid parameter\n";
7019 case MYKONOS_ERR_FAILED:
7020 return "Mykonos: General Failure\n";
7021 case MYKONOS_ERR_WAITFOREVENT_INV_PARM:
7022 return "waitForEvent had invalid parameter.\n";
7023 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT:
7024 return "waitForEvent timed out.\n";
7025 case MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_WAIT:
7026 return "Requested new ENSM state is invalid from the WAIT state.\n";
7027 case MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_ALERT:
7028 return "Requested new ENSM state is invalid from the ALERT state.\n";
7029 case MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_TXRX:
7030 return "Requested new ENSM state is invalid from the TXRX state.\n";
7031 case MYKONOS_ERR_SETENSM_INVALIDSTATE:
7032 return "Current ENSM state is an invalid state or calibration state.\n";
7033 case MYKONOS_ERR_PU_RXPATH_INV_PARAM:
7034 return "Invalid Rx channel was requested to be powered up.\n";
7035 case MYKONOS_ERR_PU_TXPATH_INV_PARAM:
7036 return "Invalid Tx channel was requested to be powered up.\n";
7037 case MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM:
7038 return "Invalid ObsRx channel was requested to be powered up.\n";
7039 case MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT:
7040 return "Invalid default ObsRx channel was requested to be powered up.\n";
7041 case MYKONOS_ERR_INIT_INV_ORXCHAN:
7042 return "Invalid ObsRx channel requested during initialize().\n";
7043 case MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE:
7044 return "Invalid combination for rxsyncb and orxsyncb, if shared syncb they should have the CMOS/LVDS mode\n";
7045 case MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION:
7046 return "Invalid TxFIR interpolation value.(Valid: 1,2,4)\n";
7047 case MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION:
7048 return "Invalid TXHB2 interpolation value.(Valid: 1 or 2)\n";
7049 case MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION:
7050 return "Invalid TXHB1 interpolation value.(Valid: 1 or 2)\n";
7051 case MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION:
7052 return "Invalid RxFIR decimation value.(Valid: 1,2,4)\n";
7053 case MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION:
7054 return "Invalid Rx DEC5 decimation value.(Valid: 4 or 5)\n";
7055 case MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION:
7056 return "Invalid RxHB1 decimation value.(Valid: 1 or 2)\n";
7057 case MYKONOS_ERR_INIT_INV_SNIFFER_RHB1:
7058 return "Invalid Sniffer HB1 decimation value (Valid 1 or 2)\n";
7059 case MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC:
7060 return "Invalid Sniffer RFIR decimation value (Valid 1,2,4)\n";
7061 case MYKONOS_ERR_INIT_INV_ORX_RHB1:
7062 return "Invalid ORx HB1 decimation value (Valid 1 or 2)\n";
7063 case MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC:
7064 return "Invalid ORx RFIR decimation value. (Valid 1,2,4)\n";
7065 case MYKONOS_ERR_INIT_INV_ADCDIV:
7066 return "Invalid Rx ADC divider. (Valid 1 or 2)\n";
7067 case MYKONOS_ERR_INIT_INV_DACDIV:
7068 return "Invalid Tx DAC divider. Use enum DACDIV_2, DACDIV_2p5 or DACDIV_4.\n";
7069 case MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV:
7070 return "Invalid ObsRx ADC div. (Valid 1 or 2)\n";
7071 case MYKONOS_ERR_CLKPLL_INV_HSDIV:
7072 return "Invalid CLKPLL HSDIV. (Valid 4 or 5)\n";
7073 case MYKONOS_ERR_CLKPLL_INV_VCODIV:
7074 return "Invalid CLKPLL VCODIV. Use enum VCODIV_1, VCODIV_1p5, VCODIV_2, VCODIV_3\n";
7075 case MYKONOS_ERR_CLKPLL_INV_RXTXPROFILES:
7076 return "No Rx or Tx profile is specified.\n";
7077 case MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX:
7078 return "CLKPLL VCO frequency out of range.\n";
7079 case MYKONOS_ERR_SETCLKPLL_INV_FRACWORD:
7080 return "CLKPLL fractional word is non zero.\n";
7081 case MYKONOS_ERR_SETRFPLL_INV_PLLNAME:
7082 return "Invalid pllName requested in setRfPllFreuquency()\n";
7083 case MYKONOS_ERR_SETRFPLL_INV_LO_PARM:
7084 return "RF PLL frequency out of range\n";
7085 case MYKONOS_ERR_GETRFPLL_INV_PLLNAME:
7086 return "Invalid pllName requested in getRfPllFrequency()\n";
7087 case MYKONOS_ERR_GETRFPLL_ARMERROR:
7088 return "ARM Command Error in MYKONOS_getRfPllFrequency()\n";
7089 case MYKONOS_ERR_GETRFPLL_NULLPARAM:
7090 return "NULL pointer in function parameter for MYKONOS_setRfPllFrequency()\n";
7091 case MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM:
7092 return "Could not scale device clock into range 40MHz to 80Mhz.\n";
7093 case MYKONOS_ERR_SETRFPLL_INV_VCOINDEX:
7094 return "RFPLL VCO frequency out of range.\n";
7095 case MYKONOS_ERR_SETRFPLL_INV_REFCLK:
7096 return "Unsupported PLL reference clock or refclk out of range.\n";
7097 case MYKONOS_ERR_SETORXGAIN_INV_CHANNEL:
7098 return "Invalid ObsRx channel in setObsRxManualGain().\n";
7099 case MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN:
7100 return "Invalid gain requested in setObsRxManualGain() for ORX1\n";
7101 case MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN:
7102 return "Invalid gain requested in setObsRxManualGain() for ORX2\n";
7103 case MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN:
7104 return "Invalid gain requested in setObsRxManualGain() for Sniffer\n";
7105 case MYKONOS_ERR_GETORX1GAIN_INV_POINTER:
7106 return "Cannot return ORx1 gain to gain control data structure (invalid pointer).\n";
7107 case MYKONOS_ERR_GETORX2GAIN_INV_POINTER:
7108 return "Cannot return ORx2 gain to gain control data structure (invalid pointer).\n";
7109 case MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER:
7110 return "Cannot return Sniffer gain to gain control data structure (invalid pointer).\n";
7111 case MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED:
7112 return "Cannot read ObsRx gain index. ObsRx Channel is disabled.\n";
7113 case MYKONOS_ERR_SETTX1ATTEN_INV_PARM:
7114 return "Tx1 attenuation is out of range (0 - 41950 mdB).\n";
7115 case MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM:
7116 return "Invalid Tx1Atten stepsize. Use enum mykonosTxAttenStepSize_t\n";
7117 case MYKONOS_ERR_SETTX2ATTEN_INV_PARM:
7118 return "Tx2 attenuation is out of range (0 - 41950 mdB).\n";
7119 case MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM:
7120 return "Invalid Tx2Atten stepsize. Use enum mykonosTxAttenStepSize_t\n";
7121 case MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM:
7122 return "Invalid number of FIR taps\n";
7123 case MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM:
7124 return "Invalid number of FIR taps read for the selected Filter\n";
7125 case MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM:
7126 return "Invalid FIR filter name requested. use enum mykonosfirName_t\n";
7127 case MYKONOS_ERR_RXFIR_INV_GAIN_PARM:
7128 return "Rx FIR filter has invalid gain setting\n";
7129 case MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM:
7130 return "ObsRx FIR filter A (ORx) has invalid gain setting\n";
7131 case MYKONOS_ERR_SRXFIR_INV_GAIN_PARM:
7132 return "ObsRx FIR filter B (Sniffer) has invalid gain setting\n";
7133 case MYKONOS_ERR_TXFIR_INV_GAIN_PARM:
7134 return "Tx FIR filter has invalid gain setting\n";
7135 case MYKONOS_ERR_READFIR_NULL_PARM:
7136 return "MYKONOS_readFir() has a null *firFilter parameter\n";
7137 case MYKONOS_ERR_READFIR_COEFS_NULL:
7138 return "MYKONOS_readFir() has a null coef array in *firFilter structure\n";
7139 case MYKONOS_ERR_READFIR_INV_FIRNAME_PARM:
7140 return "Invalid FIR filter name requested. use enum mykonosfirName_t\n";
7141 case MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM:
7142 return "Rx1 manual gain index out of range of gain table\n";
7143 case MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM:
7144 return "Rx2 manual gain index out of range of gain table\n";
7145 case MYKONOS_ERR_INITSER_INV_VCODIV_PARM:
7146 return "Found invalid VCO divider value during setupSerializers()\n";
7147 case MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM:
7148 return "CLKPLL VCO frequency exceeded max(8Ghz) in VCO divider /1 case ()\n";
7149 case MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM:
7150 return "CLKPLL VCO frequency exceeded max(9.216Ghz) in VCO divider /1.5 case ()\n";
7151 case MYKONOS_ERR_INITDES_INV_VCODIV_PARM:
7152 return "Found invalid VCO divider value during setupDeserializers()\n";
7153 case MYKONOS_ERR_SER_INV_M_PARM:
7154 return "Invalid JESD Framer M parameter during setupSerializers()\n";
7155 case MYKONOS_ERR_SER_INV_L_PARM:
7156 return "Invalid JESD Framer L parameter during setupSerializers()\n";
7157 case MYKONOS_ERR_SER_INV_LANERATE_PARM:
7158 return "Invalid Lanerate frequency in setupSerializer()\n";
7159 case MYKONOS_ERR_SER_INV_LANEEN_PARM:
7160 return "Invalid number of JESD204 lanes enabled.\n";
7161 case MYKONOS_ERR_SER_INV_AMP_PARM:
7162 return "Invalid JESD204 serializer amplitude\n";
7163 case MYKONOS_ERR_SER_INV_PREEMP_PARM:
7164 return "Invalid JESD204 serializer preemphasis setting\n";
7165 case MYKONOS_ERR_SER_INV_LANEPN_PARM:
7166 return "Invald JESD204 serializer PN invert setting\n";
7167 case MYKONOS_ERR_SER_LANE_CONFLICT_PARM:
7168 return "Rx framer and ObsRx framer are attempting to use the same physical lanes\n";
7169 case MYKONOS_ERR_SER_INV_TXSER_DIV_PARM:
7170 return "Invalid serializer lane clock divider\n";
7171 case MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM:
7172 return "Rx lane and ObsRx lane rate must match\n";
7173 case MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM:
7174 return "Framer M can only =1 if Real IF data option is enabled\n";
7175 case MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT:
7176 return "Serializer HSCLK and lane clock are not integer multiples\n";
7177 case MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT:
7178 return "Deserializer HSCLK and lane clock are not integer multiples\n";
7179 case MYKONOS_ERR_DESER_INV_M_PARM:
7180 return "Invalid deserializer M value. (Valid 2 or 4)\n";
7181 case MYKONOS_ERR_DESER_INV_L_PARM:
7182 return "Invalid deserializer L value. (Valid 1,2,4)\n";
7183 case MYKONOS_ERR_DESER_INV_HSCLK_PARM:
7184 return "Invalid HSCLK in setupDeserializer()\n";
7185 case MYKONOS_ERR_DESER_INV_LANERATE_PARM:
7186 return "Invalid deserializer lane rate\n";
7187 case MYKONOS_ERR_DESER_INV_LANEEN_PARM:
7188 return "Invalid number of deserializer lanes enabled\n";
7189 case MYKONOS_ERR_DESER_INV_EQ_PARM:
7190 return "Invalid deserializer EQ setting";
7191 case MYKONOS_ERR_DESER_INV_LANEPN_PARM:
7192 return "Invalid deserializer invert Lane PN setting\n";
7193 case MYKONOS_ERR_FRAMER_INV_M_PARM:
7194 return "Invalid Rx framer M setting\n";
7195 case MYKONOS_ERR_FRAMER_INV_BANKID_PARM:
7196 return "Invalid Rx framer Bank ID\n";
7197 case MYKONOS_ERR_FRAMER_INV_LANEID_PARM:
7198 return "Invalid Rx framer Lane ID\n";
7199 case MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM:
7200 return "Invalid Rx framer LMFC offset\n";
7201 case MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM:
7202 return "Invalid Rx framer Real IF setting\n";
7203 case MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM:
7204 return "Invalid ObsRx Framer M value\n";
7205 case MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM:
7206 return "Invalid ObsRx Framer Bank ID\n";
7207 case MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM:
7208 return "Invalid ObsRx framer Lane ID\n";
7209 case MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM:
7210 return "Invalid ObsRx framer LMFC offset\n";
7211 case MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM:
7212 return "Invalid ObsRx framer Real IF setting, M must =1\n";
7213 case MYKONOS_ERR_DEFRAMER_INV_M_PARM:
7214 return "Invalid Deframer M setting\n";
7215 case MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM:
7216 return "Invalid Deframer Bank ID\n";
7217 case MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM:
7218 return "Invalid Deframer Lane ID\n";
7219 case MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM:
7220 return "Invalid Deframer LMFC offset";
7221 case MYKONOS_ERR_DEFRAMER_INV_K_PARAM:
7222 return "Invalid Deframer K setting\n";
7223 case MYKONOS_ERR_DEFRAMER_INV_FK_PARAM:
7224 return "Invalid Deframer F*K value\n";
7225 case MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM:
7226 return "Invalid polyOrder parameter in enableRxFramerPrbs()\n";
7227 case MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM:
7228 return "Invalid polyOrder parameter in enableObsRxFramerPrbs()\n";
7229 case MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM:
7230 return "Invalid enable parameter value in enableDeframerPrbsChecker()\n";
7231 case MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM:
7232 return "Invalid polyOrder parameter in enableDeframerPrbsChecker()\n";
7233 case MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM:
7234 return "Invalid lane counter select in readDeframerPrbsCounters()\n";
7235 case MYKONOS_ERR_INITARM_INV_DATARATE_PARM:
7236 return 0;
7237 case MYKONOS_ERR_INITARM_INV_VCODIV:
7238 return "Invalid ARM VCO divider\n";
7239 case MYKONOS_ERR_INITARM_INV_REGCLK:
7240 return "Invalid ARM SPI register clock rate\n";
7241 case MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM:
7242 return "Invalid ARM clock rate\n";
7243 case MYKONOS_ERR_LOADHEX_INV_CHARCOUNT:
7244 return "LoadHex() char count = 0\n";
7245 case MYKONOS_ERR_LOADHEX_INVALID_FIRSTCHAR:
7246 return "LoadHex() First char is not :\n";
7247 case MYKONOS_ERR_LOADHEX_INVALID_CHKSUM:
7248 return "LoadHex() line checksum is invalid\n";
7249 case MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT:
7250 return "Invalid byte count passed to function MYKONOS_loadArmFromBinary()";
7251 case MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT:
7252 return "Invalid byte count passed to function MYKONOS_loadArmConcurrent()";
7253 case MYKONOS_ERR_ARM_INVALID_BUILDCHKSUM:
7254 return "Verify ARM checksum failed\n";
7255 case MYKONOS_ERR_READARMMEM_INV_ADDR_PARM:
7256 return "ReadArmMem() was given an invalid memory address\n";
7257 case MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM:
7258 return "WriteArmMem() was given an invalid memory address\n";
7259 case MYKONOS_ERR_ARM_INV_ADDR_PARM:
7260 return "Invalid memory address in MYKONOS_loadArmConcurrent()";
7261 case MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM:
7262 return "Invalid ARM opcode given to sendArmCommand()\n";
7263 case MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM:
7264 return "Invalid number of extended data in sendArmCommand()\n";
7265 case MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM:
7266 return "Invalid opcode given to waitArmCmdStatus()\n";
7267 case MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER:
7268 return "Pointer to Mykonos device data structure is NULL\n";
7269 case MYKONOS_ERR_CHECKDEVSTRUCT_SPI:
7270 return "Invalid spiSettings pointer in device data structure\n";
7271 case MYKONOS_ERR_CHECKDEVSTRUCT_RX:
7272 return "Invalid device->rx pointer in device data structure\n";
7273 case MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB:
7274 return "Invalid pointer within device->rx data structure\n";
7275 case MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR:
7276 return "Invalid RXFIR pointer in device data structure\n";
7277 case MYKONOS_ERR_CHECKDEVSTRUCT_TX:
7278 return "Invalid device->tx pointer in device data structure\n";
7279 case MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB:
7280 return "Invalid pointer within device->tx data structure\n";
7281 case MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR:
7282 return "Invalid TXFIR pointer in device data structure\n";
7283 case MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX:
7284 return "Invalid device->obsRx pointer in device data structure\n";
7285 case MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXSUB:
7286 return "Invalid pointer within device->obsRx data structure\n";
7287 case MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR:
7288 return "Invalid Sniffer FIR pointer in device data structure\n";
7289 case MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR:
7290 return "Invalid ORX FIR pointer in device data structure\n";
7291 case MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL:
7292 return "Invalid Orx gain control pointer in device data structure\n";
7293 case MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL:
7294 return "Invalid Sniffer gain control pointer in device data structure\n";
7295 case MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER:
7296 return "Invalid obsRx framer pointer in device data structure\n";
7297 case MYKONOS_ERR_INITSER_INV_PROFILE:
7298 return "Invalid RX profile within device data structure detected in MYKONOS_setupSerializers()\n";
7299 case MYKONOS_ERR_INITDES_INV_TXPROFILE:
7300 return "Invalid TX profile within device data structure detected in MYKONOS_setupDeserializers()\n";
7301 case MYKONOS_ERR_JESD204B_ILAS_MISMATCH:
7302 return "Mismatch detected in MYKONOS_jesd204bIlasCheck()\n";
7303 case MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL:
7304 return "Invalid channel specified in MYKONOS_programRxGainTable()\n";
7305 case MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE:
7306 return "Invalid numGainIndicesinTable greater than possible number of gain indices for channel. \n";
7307 case MYKONOS_ERR_WRITE_CFG_MEMORY_FAILED:
7308 return "Failed write to ARM memory in MYKONOS_writeArmProfile()\n";
7309 case MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM:
7310 return "Invalid PCLKDIV parameter detected in MYKONOS_setupSerializers()\n";
7311 case MYKONOS_ERR_RXFRAMER_INV_FK_PARAM:
7312 return "Invalid FK parameter detected in MYKONOS_setupJesd204bFramer()\n";
7313 case MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM:
7314 return "Invalid FK paramter detected in MYKONOS_setupJesd204bObsRxFramer()\n";
7315 case MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM:
7316 return "Invalid PCLKDIV paramter detected in MYKONOS_setupSerializers()\n";
7317 case MYKONOS_ERR_PU_OBSRXPATH_INV_LOSOURCE_PARAM:
7318 return "Invalid LO Source for OBSRX data path \n";
7319 case MYKONOS_ERR_ARM_RADIOON_FAILED:
7320 return "ARM command to move to radioOn state failed. \n";
7321 case MYKONOS_ERR_ARM_RADIOOFF_FAILED:
7322 return "ARM command to move to radioOff state failed. \n";
7323 case MYKONOS_ERR_INV_RX_GAIN_MODE_PARM:
7324 return "Invalid gain control mode detected in MYKONOS_setRxGainControlMode()\n";
7325 case MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM:
7326 return "Invalid gain control mode detected in MYKONOS_setObsRxGainControlMode()\n";
7327 case MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT:
7328 return "Invalid RX AGC structure detected at &device->rx->rxAgcCtrl in MYKONOS_setupRxAgc()\n";
7329 case MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM:
7330 return "device->rx->rxAgcCtrl->agcPeakWaitTime out of range in MYKONOS_setupRxAgc()\n";
7331 case MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM:
7332 return "device->rx->rxAgcCtrl->agcGainUpdateTime_us out of range in MYKONOS_setupRxAgc()\n";
7333 case MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM:
7334 return "device->rx->rxAgcCtrl->apdHighThresh out of range in MYKONOS_setupRxAgc()\n";
7335 case MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM:
7336 return "device->rx->rxAgcCtrl->apdLowThresh out of range in MYKONOS_setupRxAgc()\n";
7337 case MYKONOS_ERR_INV_AGC_RX_BLOCK_DET_DECAY_PARM:
7338 return "device->rx->rxAgcCtrl->apdDecay out of range in MYKONOS_setupRxAgc()\n";
7339 case MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT:
7340 return "Data structure for peakAgc not initialized when used in MYKONOS_setupRxAgc() \n";
7341 case MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT:
7342 return "Data structure for powerAgc not initialized when used in MYKONOS_setupRxAgc() \n";
7343 case MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX:
7344 return "device->rx->rxAgcCtrl->agcRx1MaxGainIndex out of range in MYKONOS_setupRxAgc() \n";
7345 case MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX:
7346 return "device->rx->rxAgcCtrl->agcRx1MinGainIndex out of range in MYKONOS_setupRxAgc() \n";
7347 case MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX:
7348 return "device->rx->rxAgcCtrl->agcRx2MaxGainIndex out of range in MYKONOS_setupRxAgc() \n";
7349 case MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX:
7350 return "device->rx->rxAgcCtrl->agcRx2MinGainIndex out of range in MYKONOS_setupRxAgc() \n";
7351 case MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY:
7352 return "device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay out of range in MYKONOS_setupRxAgc() \n";
7353 case MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION:
7354 return "device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration out of range in MYKONOS_setupRxAgc() \n";
7355 case MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG:
7356 return "device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig out of range in MYKONOS_setupRxAgc() \n";
7357 case MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC:
7358 return "device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease out of range in MYKONOS_setupRxAgc() \n";
7359 case MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE:
7360 return "device->rx->rxAgcCtrl->agcPeakThresholdMode out of range in MYKONOS_setupRxAgc() \n";
7361 case MYKONOS_ERR_INV_AGC_RX_RESET_ON_RX_ENABLE:
7362 return "device->rx->rxAgcCtrl->agcResetOnRxEnable out of range in MYKONOS_setupRxAgc() \n";
7363 case MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER:
7364 return "device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter out of range in MYKONOS_setupRxAgc() \n";
7365 case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH:
7366 return "device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh out of range in MYKONOS_setupRxAgc() \n";
7367 case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH:
7368 return "device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh out of range in MYKONOS_setupRxAgc() \n";
7369 case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH:
7370 return "device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh out of range in MYKONOS_setupRxAgc() \n";
7371 case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH:
7372 return "device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh out of range in MYKONOS_setupRxAgc() \n";
7373 case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP:
7374 return "device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack out of range in MYKONOS_setupRxAgc() \n";
7375 case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP:
7376 return "device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n";
7377 case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP:
7378 return "device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery out of range in MYKONOS_setupRxAgc() \n";
7379 case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP:
7380 return "device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack out of range in MYKONOS_setupRxAgc() \n";
7381 case MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE:
7382 return "device->rx->rxAgcCtrl->peakAgc->apdFastAttack or hb2FastAttack out of range in MYKONOS_setupRxAgc() \n";
7383 case MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM:
7384 return "device->rx->rxAgcCtrl->peakAgc->hb2HighThresh out of range in MYKONOS_setupRxAgc() \n";
7385 case MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM:
7386 return "device->rx->rxAgcCtrl->peakAgc->hb2LowThresh out of range in MYKONOS_setupRxAgc() \n";
7387 case MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM:
7388 return "device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh out of range in MYKONOS_setupRxAgc() \n";
7389 case MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM:
7390 return "device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack out of range in MYKONOS_setupRxAgc() \n";
7391 case MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM:
7392 return "device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n";
7393 case MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM:
7394 return "device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack out of range in MYKONOS_setupRxAgc() \n";
7395 case MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM:
7396 return "device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n";
7397 case MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM:
7398 return "device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n";
7399 case MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE:
7400 return "device->rx->rxAgcCtrl->peakAgc->hb2OverloadEnable out of range in MYKONOS_setupRxAgc() \n";
7401 case MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT:
7402 return "device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt out of range in MYKONOS_setupRxAgc() \n";
7403 case MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT:
7404 return "device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt out of range in MYKONOS_setupRxAgc() \n";
7405 case MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT:
7406 return "Invalid OBSRX AGC structure detected at &device->obsRx->orxAgcCtrl in MYKONOS_setupObsRxAgc()\n";
7407 case MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT:
7408 return "Data structure for obsRx->orxAgcCtrl->peakAgc not initialized when used in MYKONOS_setupObsRxAgc() \n";
7409 case MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT:
7410 return "Data structure for obsRx->orxAgcCtrl->powerAgc not initialized when used in MYKONOS_setupObsRxAgc() \n";
7411 case MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX:
7412 return "device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex out of range in MYKONOS_setupObsRxAgc() \n";
7413 case MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX:
7414 return "device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex out of range in MYKONOS_setupObsRxAgc() \n";
7415 case MYKONOS_ERR_INV_AGC_OBSRX_SELECT:
7416 return "device->obsRx->orxAgcCtrl->agcObsRxSelect out of range in MYKONOS_setupObsRxAgc() \n";
7417 case MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM:
7418 return "device->obsRx->orxAgcCtrl->agcGainUpdateTime_us out of range in MYKONOS_setupObsRxAgc()\n";
7419 case MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM:
7420 return "device->obsRx->orxAgcCtrl->agcPeakWaitTime out of range in MYKONOS_setupObsRxAgc()\n";
7421 case MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY:
7422 return "device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay out of range in MYKONOS_setupObsRxAgc() \n";
7423 case MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION:
7424 return "device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration out of range in MYKONOS_setupObsRxAgc() \n";
7425 case MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG:
7426 return "device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig out of range in MYKONOS_setupObsRxAgc() \n";
7427 case MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC:
7428 return "device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease out of range in MYKONOS_setupObsRxAgc() \n";
7429 case MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE:
7430 return "device->obsRx->orxAgcCtrl->agcPeakThresholdMode out of range in MYKONOS_setupObsRxAgc() \n";
7431 case MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE:
7432 return "device->obsRx->orxAgcCtrl->agcResetOnRxEnable out of range in MYKONOS_setupObsRxAgc() \n";
7433 case MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER:
7434 return "device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter out of range in MYKONOS_setupObsRxAgc() \n";
7435 case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH:
7436 return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh out of range in MYKONOS_setupObsRxAgc() \n";
7437 case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH:
7438 return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh out of range in MYKONOS_setupObsRxAgc() \n";
7439 case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH:
7440 return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh out of range in MYKONOS_setupObsRxAgc() \n";
7441 case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH:
7442 return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh out of range in MYKONOS_setupObsRxAgc() \n";
7443 case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP:
7444 return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n";
7445 case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP:
7446 return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n";
7447 case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP:
7448 return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n";
7449 case MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE:
7450 return "device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack or hb2FastAttack out of range in MYKONOS_setupObsRxAgc() \n";
7451 case MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM:
7452 return "device->obsRx->orxAgcCtrl->apdHighThresh out of range in MYKONOS_setupObsRxAgc()\n";
7453 case MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM:
7454 return "device->obsRx->orxAgcCtrl->apdLowThresh out of range in MYKONOS_setupObsRxAgc()\n";
7455 case MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM:
7456 return "device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh out of range in MYKONOS_setupObsRxAgc() \n";
7457 case MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM:
7458 return "device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh out of range in MYKONOS_setupObsRxAgc() \n";
7459 case MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM:
7460 return "device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh out of range in MYKONOS_setupObsRxAgc() \n";
7461 case MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM:
7462 return "device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n";
7463 case MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM:
7464 return "device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n";
7465 case MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM:
7466 return "device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n";
7467 case MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM:
7468 return "device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n";
7469 case MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM:
7470 return "device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n";
7471 case MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE:
7472 return "device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadEnable out of range in MYKONOS_setupObsRxAgc() \n";
7473 case MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT:
7474 return "device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt out of range in MYKONOS_setupObsRxAgc() \n";
7475 case MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT:
7476 return "device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThresholdCnt out of range in MYKONOS_setupObsRxAgc() \n";
7477 case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP:
7478 return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n";
7479 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CALPLL_LOCK:
7480 return "CAL PLL Lock event timed out in MYKONOS_waitForEvent()\n";
7481 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLLCP:
7482 return "Clock PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n";
7483 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLL_LOCK:
7484 return "Clock PLL Lock event timed out in MYKONOS_waitForEvent()\n";
7485 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLLCP:
7486 return "RX PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n";
7487 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLL_LOCK:
7488 return "RX PLL Lock event timed out in MYKONOS_waitForEvent()\n";
7489 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLLCP:
7490 return "TX PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n";
7491 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLL_LOCK:
7492 return "TX PLL Lock event timed out in MYKONOS_waitForEvent()\n";
7493 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLLCP:
7494 return "Sniffer PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n";
7495 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLL_LOCK:
7496 return "Sniffer PLL Lock event timed out in MYKONOS_waitForEvent()\n";
7497 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXBBFCALDONE:
7498 return "RX Baseband Filter Cal event timed out in MYKONOS_waitForEvent()\n";
7499 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXBBFCALDONE:
7500 return "TX Baseband Filter Cal timed out in MYKONOS_waitForEvent()\n";
7501 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RFDCCALDONE:
7502 return "RF DC Offset Cal event timed out in MYKONOS_waitForEvent()\n";
7503 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ADCTUNECALDONE:
7504 return "ADC Tuner Cal event timed out in MYKONOS_waitForEvent()\n";
7505 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX1ADCPROFILE:
7506 return "Rx1 ADC Profile Loading event timed out in MYKONOS_waitForEvent()\n";
7507 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX2ADCPROFILE:
7508 return "Rx2 ADC Profile Loading event timed out in MYKONOS_waitForEvent()\n";
7509 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ORXADCPROFILE:
7510 return "ObsRx ADC Profile Loading event timed out in MYKONOS_waitForEvent()\n";
7511 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RCALDONE:
7512 return "Resistor Cal event timed out in MYKONOS_waitForEvent()\n";
7513 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ARMBUSY:
7514 return "ARM Busy event timed out in MYKONOS_waitForEvent()\n";
7515 case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_INITARMDONE:
7516 return "Initialize ARM event timed out in MYKONOS_waitForEvent()\n";
7517 case MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY:
7518 return "ARM Mailbox Busy. Command not executed in MYKONOS_sendArmCommand()\n";
7519 case MYKONOS_ERR_PU_OBSRXPATH_ARMERROR:
7520 return "ARM Command Error in MYKONOS_setObsRxPathSource()\n";
7521 case MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR:
7522 return "Device not in radioOff/IDLE state. Error in MYKONOS_enableTrackingCals()\n";
7523 case MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR:
7524 return "ARM command Error in MYKONOS_setRadioControlPinMode()\n";
7525 case MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR:
7526 return "ARM Command Error in MYKONOS_enableTrackingCals()\n";
7527 case MYKONOS_ERR_SETRFPLL_ARMERROR:
7528 return "ARM Command Error in MYKONOS_setRfPllFrequency()\n";
7529 case MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM:
7530 return "device->tx->txProfile->txInputHbInterpolation out of range in MYKONOS_initialize(): valid = 1,2 or 4\n";
7531 case MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV:
7532 return "device->clocks->clkPllVcoDiv value not supported in MYKONOS_loadAdcProfiles\n";
7533 case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED:
7534 return "Custom RX ADC Profile required\n";
7535 case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED:
7536 return "Custom ORX ADC Profile required\n";
7537 case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED:
7538 return "Custom SNRX ADC Profile required\n";
7539 case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED:
7540 return "Custom Loopback ADC profile required\n";
7541 case MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED:
7542 return "WriteArmMemory call failed while writing the Loopback ADC profile into ARM memory\n";
7543 case MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED:
7544 return "WriteArmMemory call failed while writing the Sniffer ADC profile into ARM memory\n";
7545 case MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED:
7546 return "WriteArmMemory call failed while writing the ObsRx ADC profile into ARM memory\n";
7547 case MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED:
7548 return "WriteArmMemory call failed while writing the RX ADC profile into ARM memory\n";
7549 case MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO:
7550 return "SnRx profile has invalid ADC divider of 0, causing a divide by zero\n";
7551 case MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO:
7552 return "ORx profile has invalid ADC divider of 0, causing a divide by zero\n";
7553 case MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO:
7554 return "Rx profile has invalid ADC divider of 0, causing a divide by zero\n";
7555 case MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE:
7556 return "If Tx Profile is valid, a matching ORx profile must be provided to set ADC divider and digital filtering for loopback calibrations\n";
7557 case MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION:
7558 return "Invalid setting for avgDuration in MYKONOS_setupPaProtection(...)\n";
7559 case MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP:
7560 return "Invalid setting for attenStepSize in MYKONOS_setupPaProtection(...)\n";
7561 case MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_ENABLE:
7562 return "Invalid setting for txAttenControlEnable in MYKONOS_setupPaProtection(...)\n";
7563 case MYKONOS_ERR_SETUP_PA_PROT_INV_POWER_THRESH:
7564 return "Invalid setting for powerThreshold in MYKONOS_setupPaProtection(...)\n";
7565 case MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL:
7566 return "Invalid TX channel selected for MYKONOS_getDacPower(...)\n";
7567 case MYKONOS_ERR_GET_DAC_PWR_INV_POINTER:
7568 return "Cannot return DAC Power information (invalid pointer)\n";
7569 case MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER:
7570 return "Cannot return PA Protection Flag Status information (invalid pointer)\n";
7571 case MYKONOS_ERR_GET_OBSRX_OVERLOADS_NULL_PARM:
7572 return "MYKONOS_getObsRxPathOverloads() has null *obsRxOverloads parameter\n";
7573 case MYKONOS_ERR_GET_RX1_OVERLOADS_NULL_PARM:
7574 return "MYKONOS_getRxPathOverloads() has null *rx1Overloads parameter\n";
7575 case MYKONOS_ERR_GET_RX2_OVERLOADS_NULL_PARM:
7576 return "MYKONOS_getRxPathOverloads() has null *rx2Overloads parameter\n";
7577 case MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM:
7578 return "MYKONOS_getRadioState() has null *radioStatus parameter\n";
7579 case MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM:
7580 return "MYKONOS_abortInitCals() has null *calsCompleted parameter\n";
7581 case MYKONOS_ERR_WAIT_INITCALS_ARMERROR:
7582 return "MYKONOS_waitInitCals() returned an ARM error\n";
7583 case MYKONOS_ERR_WAIT_INITCALS_NULL_PARAM:
7584 return "MYKONOS_waitInitCals() has one or more null parameters\n";
7585 case MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM:
7586 return "MYKONOS_checkPllsLockStatus() has a null *pllLockStatus parameter\n";
7587 case MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM:
7588 return "MYKONOS_getTxFilterOverRangeStatus() has a null *txFilterStatus parameter\n";
7589 case MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM:
7590 return "MYKONOS_programRxGainTable() has a null *gainTablePtr parameter\n";
7591 case MYKONOS_ERR_PROGRAMFIR_NULL_PARM:
7592 return "MYKONOS_programFir() has a null *firFilter parameter\n";
7593 case MYKONOS_ERR_PROGRAMFIR_COEFS_NULL:
7594 return "MYKONOS_programFir() has a null coef array in *firFilter structure\n";
7595 case MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM:
7596 return "MYKONOS_readDeframerStatus() has a null *deframerStatus parameter\n";
7597 case MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM:
7598 return "MYKONOS_readDeframerPrbscounters() has a null *prbsErrorCount parameter\n";
7599 case MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM:
7600 return "MYKONOS_readOrxFramerStatus() has a null *obsFramerStatus parameter\n";
7601 case MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM:
7602 return "MYKONOS_readRxFramerStatus() has a null *framerStatus parameter\n";
7603 case MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM:
7604 return "MYKONOS_waitArmCmdStatus() has a null *cmdStatByte parameter\n";
7605 case MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM:
7606 return "MYKONOS_readArmCmdStatus() has one or more null pointer parameters\n";
7607 case MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM:
7608 return "MYKONOS_readArmCmdStatusByte() has an invalid opcode parameter\n";
7609 case MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM:
7610 return "MYKONOS_readArmCmdStatusByte() has a null *cmdStatByte parameter\n";
7611 case MYKONOS_ERR_ARMCMD_NULL_PARM:
7612 return "MYKONOS_sendArmCommand() has a null *extendedData parameter\n";
7613 case MYKONOS_ERR_WRITEARMMEM_NULL_PARM:
7614 return "MYKONOS_writeArmMem() has a null *data parameter\n";
7615 case MYKONOS_ERR_LOADBIN_NULL_PARAM:
7616 return "MYKONOS_loadArmFromBinary() has a null *binary parameter\n";
7617 case MYKONOS_ERR_LOADARMCON_NULL_PARAM:
7618 return "MYKONOS_loadArmConcurrent() has a null *binary parameter\n";
7619 case MYKONOS_ERR_GETTX1ATTEN_NULL_PARM:
7620 return "MYKONOS_getTx1Attenuation() has NULL tx1Attenuation_mdB parameter\n";
7621 case MYKONOS_ERR_GETTX2ATTEN_NULL_PARM:
7622 return "MYKONOS_getTx2Attenuation() has NULL tx2Attenuation_mdB parameter\n";
7623 case MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM:
7624 return "Invalid serializer Lanes Enable parameter in Rx framer structure\n";
7625 case MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM:
7626 return "Invalid serializer Lanes Enable parameter in ObsRx framer structure\n";
7627 case MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID:
7628 return "Can not enable Tx NCO when Tx Profile is invalid\n";
7629 case MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID:
7630 return "Invalid Tx1 NCO frequency\n";
7631 case MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID:
7632 return "Invalid Tx2 NCO frequency\n";
7633 case MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM:
7634 return "Function parameter has NULL pointer in MYKONOS_jesd204bIlasCheck()\n";
7635 case MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV:
7636 return "CLKPLL refclk divider was read back as an invalid setting in MYKONOS_getRfPllFrequency()\n";
7637 case MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV:
7638 return "CLKPLL HSDIV divider was read back as an invalid setting in MYKONOS_getRfPllFrequency()\n";
7639 case MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV:
7640 return "CLKPLL VCODIV divider was read back as an invalid setting in MYKONOS_getRfPllFrequency()\n";
7641 case MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM:
7642 return "MYKONOS_getRx1DecPower() has a null *rx1DecPower_mdBFS parameter\n";
7643 case MYKONOS_ERR_GET_RX1_DEC_POWER_NUM_SAMPLES:
7644 return "MYKONOS_getRx1DecPower() numSamples greater than agcGainUpdateCounter\n";
7645 case MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM:
7646 return "MYKONOS_getRx2DecPower() has a null *rx2DecPower_mdBFS parameter\n";
7647 case MYKONOS_ERR_GET_RX2_DEC_POWER_NUM_SAMPLES:
7648 return "MYKONOS_getRx2DecPower() numSamples greater than agcGainUpdateCounter\n";
7649 case MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM:
7650 return "MYKONOS_getObsRxDecPower() has a null *obsRxDecPower_mdBFS parameter\n";
7651 case MYKONOS_ERR_GET_OBSRX_DEC_POWER_NUM_SAMPLES:
7652 return "MYKONOS_getObsRxDecPower() numSamples greater than agcGainUpdateCounter\n";
7653 case MYKONOS_ERR_GETARMVER_NULL_PARM:
7654 return "MYKONOS_getArmVersion() has a NULL pointer in one of the function parameters\n";
7655 case MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR:
7656 return "ARM is not in the RadioOff state before MYKONOS_enableDpdTracking(), call MYKONOS_radioOff()\n";
7657 case MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE:
7658 return "MYKONOS_restoreDpdModel() supplied DPD Model Data Buffer is incorrect size\n";
7659 case MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG:
7660 return "The ARM reported a error while in MYKONOS_restoreDpdModel().\n";
7661 case MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL:
7662 return "MYKONOS_restoreDpdModel() invalid txChannel specified\n";
7663 case MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE:
7664 return "MYKONOS_saveDpdModel() supplied DPD Model Data Buffer is incorrect size\n";
7665 case MYKONOS_ERR_SAVDPDMOD_ARMSTATE:
7666 return "ARM is not in the RadioOff state before MYKONOS_saveDpdModel(), call MYKONOS_radioOff()\n";
7667 case MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL:
7668 return "MYKONOS_saveDpdModel() invalid txChannel specified\n";
7669 case MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR:
7670 return "ARM is not in the RadioOff state before MYKONOS_enableClgcTracking(), call MYKONOS_radioOff()\n";
7671 case MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV:
7672 return "Tx or ORx profile is not valid, both are necessary for DPD features in MYKONOS_configDpd()\n";
7673 case MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT:
7674 return "device->tx->dpdConfig structure has NULL pointer in MYKONOS_configDpd()\n";
7675 case MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG:
7676 return "The ARM reported a error while writing to an ARM config structure in MYKONOS_writeArmCfgStruct()\n";
7677 case MYKONOS_ERR_CFGDPD_INV_DPDDAMPING:
7678 return "ERROR: device->tx->dpdConfig->damping parameter is out of range (0-15)\n";
7679 case MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES:
7680 return "ERROR: device->tx->dpdConfig->samples parameter is out of range (64 - 32768)\n";
7681 case MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS:
7682 return "ERROR: device->tx->dpdConfig->numWeights parameter is out of range (0-3)\n";
7683 case MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH:
7684 return "ERROR: device->tx->dpdConfig->outlierThreshold parameter is out of range\n";
7685 case MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT:
7686 return "ERROR: device->tx->dpdConfig->modelPriorWeight parameter is out of range (Valid 0-32)\n";
7687 case MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN:
7688 return "ERROR: device->tx->clgcConfig->tx1DesiredGain or tx2DesiredGain parameter is out of range\n";
7689 case MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT:
7690 return "ERROR: device->tx->clgcConfig->tx1AttenLimit or tx2AttenLimit parameter is out of range\n";
7691 case MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO:
7692 return "ERROR: device->tx->clgcConfig->tx1ControlRatio or tx2ControlRatio parameter is out of range\n";
7693 case MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY:
7694 return "ERROR: device->tx->dpdConfig->additionalDelayOffset parameter is out of range\n";
7695 case MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL:
7696 return "ERROR: device->tx->dpdConfig->pathDelayPnSeqLevel parameter is out of range\n";
7697 case MYKONOS_ERR_CFGDPD_INV_MODELVERSION:
7698 return "ERROR: device->tx->dpdConfig->modelVersion parameter is out of range\n";
7699 case MYKONOS_ERR_READARMCFG_ARMERRFLAG:
7700 return "ERROR: MYKONOS_readArmConfig failed due to an ARM error\n";
7701 case MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM:
7702 return "MYKONOS_getPendingTrackingCals() has NULL function parameter\n";
7703 case MYKONOS_ERR_ARMCMDSTATUS_ARMERROR:
7704 return "MYKONOS_waitArmCmdStatus() exited due to ARM error for the desired ARM opcode\n";
7705 case MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT:
7706 return "MYKONOS_waitArmCmdStatus() timed out waiting for the ARM to complete the requested command\n";
7707 case MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR:
7708 return "ARM returned an error while trying to get the ObsRx Path source in MYKONOS_getObsRxPathSource()\n";
7709 case MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT:
7710 return "MYKONOS_getDpdConfig() could not complete due to a NULL pointer to device->tx->dpdConfig structure\n";
7711 case MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV:
7712 return "The Tx and ORx profiles must be valid for DPD related functions\n";
7713 case MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG:
7714 return "MYKONOS_getDpdStatus() reported an ARM error with the ARM Get command\n";
7715 case MYKONOS_ERR_GETDPDSTATUS_NULLPARAM:
7716 return "MYKONOS_getDpdStatus() has NULL pointer in the function parameter\n";
7717 case MYKONOS_ERR_SETDEFOBSRXPATH_NULL_OBSRX_STRUCT:
7718 return "Observation profile not valid, device->obsRx structure is NULL in MYKONOS_setDefaultObsRxPath()\n";
7719 case MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM:
7720 return "MYKONOS_getClgcStatus() has NULL clgcStatus parameter\n";
7721 case MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG:
7722 return "ARM reported an error with the ARM GET command during MYKONOS_getClgcStatus()\n";
7723 case MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM:
7724 return "MYKONOS_getDeframerFifoDepth() function parameter fifoDepth is a NULL pointer\n";
7725 case MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM:
7726 return "MYKONOS_getDeframerFifoDepth() function parameter readEnLmfcCount is a NULL pointer\n";
7727 case MYKONOS_ERR_GETDPDSTATUS_INV_CH:
7728 return "MYKONOS_getDpdStatus() txChannel parameter is not valid (TX1 and TX2 are the only valid options)\n";
7729 case MYKONOS_ERR_GETCLGCSTATUS_INV_CH:
7730 return "MYKONOS_getClgcStatus() txChannel parameter is not valid (TX1 and TX2 are the only valid options)\n";
7731 case MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE:
7732 return "Invalid Tx profile: When using Tx Input halfband, IQ rate must not exceed 160MSPS\n";
7733 case MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE:
7734 return "Invalid Tx profile: When using Tx Input halfband 0, IQ rate must not exceed 80MSPS\n";
7735 case MYKONOS_ERR_RXFIR_TAPSEXCEEDED:
7736 return "Rx PFIR can not be clocked fast enough to handle the number of FIR coefficents provided\n";
7737 case MYKONOS_ERR_ORXFIR_TAPSEXCEEDED:
7738 return "ORx PFIR can not be clocked fast enough to handle the number of FIR coefficents provided\n";
7739 case MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED:
7740 return "Sniffer Rx PFIR can not be clocked fast enough to handle the number of FIR coefficents provided\n";
7741 case MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM:
7742 return "Invalid number of Tx FIR coefficients\n";
7743 case MYKONOS_ERR_TXFIR_INV_NUMROWS:
7744 return "Invalid number of PFIR coefficient rows\n";
7745 case MYKONOS_ERR_TXFIR_TAPSEXCEEDED:
7746 return "Too many Tx PFIR taps for the IQ sample rate. FIR processing clock can not run fast enough to handle the number of taps\n";
7747 case MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM:
7748 return "MYKONOS_getInitCalStatus() has a null pointer in parameter list\n";
7749 case MYKONOS_ERR_GETINITCALSTATUS_ARMERROR:
7750 return "MYKONOS_getInitCalStatus() returned an ARM error while getting the init cal status information";
7751 case MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV:
7752 return "Tx and ObsRx profiles must be valid to use the CLGC feature in MYKONOS_configClgc()\n";
7753 case MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT:
7754 return "CLGC config structure is NULL in device->tx->clgcConfig in MYKONOS_configClgc()\n";
7755 case MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV:
7756 return "Could not read back CLGC status because Tx and ORx profiles are not valid\n";
7757 case MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT:
7758 return "Could not read back CLGC status because return structure device->tx->clgcConfig pointer is NULL\n";
7759 case MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM:
7760 return "device structure pointer is NULL in MYKONOS_calculateDigitalClocks()\n";
7761 case MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT:
7762 return "device->clocks structure pointer is NULL in MYKONOS_calculateDigitalClocks()\n";
7763 case MYKONOS_ERR_NULL_DEVICE_PARAM:
7764 return "The device pointer in the calling function's parameter list is a NULL pointer\n";
7765 case MYKONOS_ERR_CALCDEVCLK_NULLPARAM:
7766 return "MYKONOS_calculateScaledDeviceClk_kHz() has a NULL pointer in one of the function parameters\n";
7767 case MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY:
7768 return "CLGC Additional Delay parameter is out of range in MYKONOS_configClgc\n";
7769 case MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL:
7770 return "CLGC PN Sequence level parameter is out of range in MYKONOS_configClgc\n";
7771 case MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV:
7772 return "The Tx and ORx profiles must be valid to use the VSWR feature in MYKONOS_configVswr()\n";
7773 case MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR:
7774 return "ARM must be in radioOff state to configure the VSWR config parameters in MYKONOS_configVswr()\n";
7775 case MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN:
7776 return "VSWR 3.3v GPIO pin selection is out of range (0-11) in MYKONOS_configVswr()\n";
7777 case MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL:
7778 return "VSWR init PN sequence level is out of range in MYKONOS_configVswr()\n";
7779 case MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY:
7780 return "VSWR additionalDelay member is out of range in MYKONOS_configVswr()\n";
7781 case MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT:
7782 return "device->tx->vswrConfig pointer is null in MYKONOS_confgiVswr()\n";
7783 case MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT:
7784 return "device->tx->vswrConfig pointer is null in MYKONOS_getVswrConfig()\n";
7785 case MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV:
7786 return "Tx and ORx profiles must be valid in MYKONOS_getVswrConfig()\n";
7787 case MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG:
7788 return "ARM returned an error while attempting to read the VSWR status structure\n";
7789 case MYKONOS_ERR_GETVSWRSTATUS_INV_CH:
7790 return "Invalid Tx channel parameter passed to MYKONOS_getVswrStatus()\n";
7791 case MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM:
7792 return "vswrStatus function parameter is null in MYKONOS_getVswrStatus\n";
7793 case MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX:
7794 return "Max gain index bigger than max gain index loaded table in MYKONOS_setRxAgcMinMaxGainIndex().\n";
7795 case MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX:
7796 return "Min gain index lower than min gain index loaded table in MYKONOS_setRxAgcMinMaxGainIndex().\n";
7797 case MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL:
7798 return "Wrong RX channel selected in MYKONOS_setRxAgcMinMaxGainIndex().\n";
7799 case MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL:
7800 return "Wrong read back channel in MYKONOS_setObsRxAgcMinMaxGainIndex().\n";
7801 case MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX:
7802 return "Max gain index bigger than max gain index loaded table in MYKONOS_setObsRxAgcMinMaxGainIndex().\n";
7803 case MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX:
7804 return "Min gain index lower than min gain index loaded table in MYKONOS_setObsRxAgcMinMaxGainIndex().\n";
7805 case MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL:
7806 return "Wrong observation channel selected in MYKONOS_setObsRxAgcMinMaxGainIndex().\n";
7807 case MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE:
7808 return "The temp gain compensation is outside range (-3000mdB to 3000mdB) in MYKONOS_setRx1TempGainComp().\n";
7809 case MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP:
7810 return "Not valid temp gain compensation, step size is 250mdB in MYKONOS_setRx1TempGainComp().\n";
7811 case MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE:
7812 return "The temp gain compensation is outside range (-3000mdB to 3000mdB) in MYKONOS_setRx2TempGainComp().\n";
7813 case MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP:
7814 return "Not valid temp gain compensation, step size is 250mdB in MYKONOS_setRx2TempGainComp().\n";
7815 case MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE:
7816 return "The temp gain compensation is outside range (-3000mdB to 3000mdB) in MYKONOS_setObsRxTempGainComp().\n";
7817 case MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP:
7818 return "Not valid temp gain compensation, step size is 250mdB in MYKONOS_setObsRxTempGainComp().\n";
7819 case MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL:
7820 return "rx1TempCompGain_mdB pointer is null MYKONOS_getRx1TempGainComp().\n";
7821 case MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL:
7822 return "rx2TempCompGain_mdB pointer is null MYKONOS_getRx2TempGainComp().\n";
7823 case MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL:
7824 return "obsRxTempCompGain_mdB pointer is null MYKONOS_getObsRxTempGainComp().\n";
7825 case MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM:
7826 return "Function parameter mykonosOrxQecStatus_t is a NULL pointer in MYKONOS_getOrxQecStatus().\n";
7827 case MYKONOS_ERR_GETORXQECSTATUS_INV_CH:
7828 return "Channel selection not valid in MYKONOS_getOrxQecStatus().\n";
7829 case MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG:
7830 return "ARM command error in MYKONOS_getOrxQecStatus().\n";
7831 case MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM:
7832 return "Function parameter mykonosRxQecStatus_t is a NULL pointer in MYKONOS_getRxQecStatus().\n";
7833 case MYKONOS_ERR_GETRXQECSTATUS_INV_CH:
7834 return "Channel selection not valid in MYKONOS_getRxQecStatus().\n";
7835 case MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG:
7836 return "ARM command error in MYKONOS_getRxQecStatus().\n";
7837 case MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM:
7838 return "Function parameter mykonosTxQecStatus_t is a NULL pointer in MYKONOS_getRxQecStatus().\n";
7839 case MYKONOS_ERR_GETTXQECSTATUS_INV_CH:
7840 return "Channel selection not valid in MYKONOS_getTxQecStatus().\n";
7841 case MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG:
7842 return "ARM command error in MYKONOS_getTxQecStatus().\n";
7843 case MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM:
7844 return "Function parameter mykonosTxLolStatus_t is a NULL pointer in MYKONOS_getTLolStatus().\n";
7845 case MYKONOS_ERR_GETTXLOLSTATUS_INV_CH:
7846 return "Channel selection not valid in MYKONOS_getTLolStatus().\n";
7847 case MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG:
7848 return "ARM command error in MYKONOS_getTLolStatus().\n";
7849 case MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV:
7850 return "Not valid calibration passed to MYKONOS_rescheduleTrackingCal().\n";
7851 case MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG:
7852 return "ARM error in MYKONOS_rescheduleTrackingCal().\n";
7853 case MYKONOS_ERR_ARMSTATE_EXCEPTION:
7854 return "ARM system problem has been detected.\n";
7855 case MYKONOS_ERR_ARMSTATE_CAL_ERROR:
7856 return "ARM has detected an error in the tracking calibrations.\n";
7857 case MYKONOS_ERR_ARMSTATE_PROFILE_ERROR:
7858 return "ARM has detected an illegal profile.\n";
7859 case MYKONOS_ERR_WAITARMCSTATE_TIMEOUT:
7860 return "Timeout occurred in MYKONOS_checkArmState().\n";
7861 case MYKONOS_ERR_GET_API_VERSION_NULL_PARAM:
7862 return "Null parameter passed to the function MYKONOS_getApiVersion().\n";
7863 case MYKONOS_ERR_GETPRODUCTID_NULL_PARAM:
7864 return "Null parameter passed to the function MYKONOS_getProductId().\n";
7865 case MYKONOS_ERR_TXPROFILE_IQRATE:
7866 return "Tx Profile IQ rate out of range.\n";
7867 case MYKONOS_ERR_TXPROFILE_RFBW:
7868 return "Tx Profile RF bandwidth out of range.\n";
7869 case MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION:
7870 return "Tx Filter interpolation not valid.\n";
7871 case MYKONOS_ERR_TXPROFILE_FIR_COEFS:
7872 return "Tx FIR filter not valid.\n";
7873 case MYKONOS_ERR_RXPROFILE_RXCHANNEL:
7874 return " Rx channel is not valid.\n";
7875 case MYKONOS_ERR_RXPROFILE_IQRATE:
7876 return "Receiver profile out of range IQ rate.\n";
7877 case MYKONOS_ERR_RXPROFILE_RFBW:
7878 return "Receiver profile out of range RF bandwidth.\n";
7879 case MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION:
7880 return "Receiver profile not valid filter decimation setting.\n";
7881 case MYKONOS_ERR_RXPROFILE_FIR_COEFS:
7882 return "Receiver profile FIR filter not valid.\n";
7883 case MYKONOS_ERR_RXPROFILE_ADCDIV:
7884 return "Receiver profile not valid ADC divider.\n";
7885 case MYKONOS_ERR_PROFILES_HSDIGCLK:
7886 return "Profile combinations loaded are not valid.\n";
7887 case MYKONOS_ERR_RESET_TXLOL_INV_PARAM:
7888 return "Selected channel is not valid.\n";
7889 case MYKONOS_ERR_RESET_TXLOL_ARMERROR:
7890 return "ARM command error in MYKONOS_resetExtTxLolChannel().\n";
7891 case MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV:
7892 return "Not valid calibration mask passed for trackCals.\n";
7893 case MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG:
7894 return "ARM error flag set.\n";
7895 case MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG:
7896 return "ARM error flag set.\n";
7897 case MYKONOS_ERR_GETSTATEALL_TRACK_ARMERROR:
7898 return "ARM command error.\n";
7899 case MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM:
7900 return "Null parameter passed for trackCals.\n";
7901 case MYKONOS_ERR_SETSTATE_TRACK_CAL_INV:
7902 return "Not valid calibration passed.\n";
7903 case MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG:
7904 return "ARM command error.\n";
7905 case MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM:
7906 return "Null parameter passed to trackCalState.\n";
7907 case MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG:
7908 return "ARM command error flag set.\n";
7909 case MYKONOS_ERR_GETSTATE_TRACK_ARMERROR:
7910 return "ARM command error.\n";
7911 case MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL:
7912 return "Tx channel is not valid (Valid ENUM values: TX1 or TX2 only).\n";
7913 case MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG:
7914 return "ARM command flag error set.\n";
7915 case MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN:
7916 return "CLGC gain parameter is out of range, valid range is from -10000 to 10000.\n";
7917 case MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL:
7918 return "Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2).\n";
7919 case MYKONOS_ERR_SETDPDACT_INV_STATE:
7920 return "Invalid Actuator state, valid states are 0-disable and 1-enable.\n";
7921 case MYKONOS_ERR_SETDPDACT_ARMERRFLAG:
7922 return "ARM command flag error set.\n";
7923 case MYKONOS_ERR_SETRFPLL_LF_PLLNAME:
7924 return "Invalid pllName requested in MYKONOS_setRfPllLoopFilter()\n";
7925 case MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY:
7926 return "Invalid stability value requested in MYKONOS_setRfPllLoopFilter()\n";
7927 case MYKONOS_ERR_SETRFPLL_LF_ARMERROR:
7928 return "ARM Command Error in MYKONOS_setRfPllLoopFilter()\n";
7929 case MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH:
7930 return "Invalid Tx/Rx value bandwith requested in MYKONOS_setRfPllLoopFilter()\n";
7931 case MYKONOS_ERR_SETRFPLL_LF_INV_SNF_LOOPBANDWIDTH:
7932 return "Invalid Sniffer value bandwith in MYKONOS_setRfPllLoopFilter()\n";
7933 case MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME:
7934 return "Invalid pllName requested in MYKONOS_getRfPllLoopFilter()\n";
7935 case MYKONOS_ERR_GETRFPLL_LF_ARMERROR:
7936 return "ARM Command Error in MYKONOS_getRfPllLoopFilter()\n";
7937 case MYKONOS_ERR_GETRFPLL_LF_NULLPARAM:
7938 return "NULL pointer in function parameter for MYKONOS_getRfPllLoopFilter()\n";
7939 case MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT:
7940 return "Invalid value passed as parameter for measureCount to function MYKONOS_setRfDcOffsetCnt().\n";
7941 case MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT:
7942 return "The measureCount value passed to function MYKONOS_setRfDcOffsetCnt() is less than the minimum limit allowed.\n";
7943 case MYKONOS_ERR_DC_OFFSET_INV_CHAN:
7944 return "Invalid channel passed as parameter, for valid channel refer mykonosDcOffsetChannels_t enum.\n";
7945 case MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT:
7946 return "Null parameter passed for measureCount MYKONOS_getRfDcOffsetCnt().\n";
7947 case MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT:
7948 return "Invalid MShift value passed as parameter to function MYKONOS_setDigDcOffsetMShift().\n";
7949 case MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT:
7950 return "MShift passed to the function MYKONOS_getDigDcOffsetMShift() is NULL.\n";
7951 case MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK:
7952 return "Invalid enable mask passed to the function MYKONOS_setDigDcOffsetEn().\n";
7953 case MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK:
7954 return "Enable mask passed to the function MYKONOS_getDigDcOffsetEn() is NULL.\n";
7955 case MYKONOS_ERR_RESETDPD_WRONG_PARAM:
7956 return "reset parameter passed to function MYKONOS_resetDpd() is not valid, possible values are: MYK_DPD_RESET_FULL, MYK_DPD_RESET_PRIOR or MYK_DPD_RESET_CORRELATOR \n";
7957 case MYKONOS_ERR_RESETDPD_ARMERRFLAG:
7958 return "ARM command flag error set in function MYKONOS_resetDpd().\n";
7959 case MYKONOS_ERR_CFGCLGC_INV_THRESHOLD:
7960 return "tx1RelThreshold or tx2RelThreshold parameter is out of range in function MYKONOS_configClgc().\n";
7961 case MYKONOS_ERR_RESETDPD_INV_TXCHANNEL:
7962 return "Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2 in function MYKONOS_resetDpd().\n";
7963 case MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM:
7964 return "pathDelay structure is null in function MYKONOS_setPathDelay().\n";
7965 case MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE:
7966 return "path delay not valid range in MYKONOS_setPathDelay(), valid ranges are from 0 to 4095 at 1/16 sample resolution of ORx sample rate.\n";
7967 case MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM:
7968 return "pathDelay structure is null in function MYKONOS_getPathDelay().\n";
7969 case MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION:
7970 return "invalid selection for getting the path delay, valid selections are given by mykonosPathDelaySel_t.\n";
7971 case MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG:
7972 return "Arm error while reading path delay for the selected calibration status.\n";
7973 case MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM:
7974 return "dpdErrCnt is null in function MYKONOS_getDpdErrorCounters().\n";
7975 case MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH:
7976 return "invalid selection for getting the error counters tx channel in MYKONOS_getDpdErrorCounters().\n";
7977 case MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG:
7978 return "Arm error while reading the error counters for the DPD status MYKONOS_getDpdErrorCounters().\n";
7979 case MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT:
7980 return "Passed structure is null in MYKONOS_setDpdBypassConfig().\n";
7981 case MYKONOS_ERR_SETDPDACT_INV_ACTMODE:
7982 return "Invalid mode passed detected in MYKONOS_setDpdBypassConfig(), actConfig->bypassActuatorMode for valid modes mykonosDpdResetMode_t.\n";
7983 case MYKONOS_ERR_SETDPDACT_INV_LEVEL:
7984 return "Passed actConfig->bypassActuatorLevel outside the range in MYKONOS_setDpdBypassConfig().\n";
7985 case MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT:
7986 return "Passed structure is null in MYKONOS_getDpdBypassConfig().\n";
7987 case MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT:
7988 return "Passed structure is null in MYKONOS_setDpdActuatorCheck().\n";
7989 case MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE:
7990 return "Invalid mode detected in MYKONOS_setDpdActuatorCheck(), actCheck->actuatorGainCheckMode for valid modes mykonosDpdResetMode_t.\n";
7991 case MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL:
7992 return "Passed actCheck->actuatorGainCheckLevel outside the range in MYKONOS_setDpdActuatorCheck().\n";
7993 case MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT:
7994 return "Passed structure is null in MYKONOS_getDpdActuatorCheck().\n";
7995 case MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT:
7996 return "Passed structure is null in MYKONOS_setClgcAttenTuningConfig().\n";
7997 case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE:
7998 return "Invalid mode detected for attRangeCfg member in MYKONOS_getClgcAttenTuningConfig(), for valid modes ::mykonosClgcAttenTuningMode_t.\n";
7999 case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET:
8000 return "Invalid AttenTuningPreset detected for attRangeCfg member in MYKONOS_getClgcAttenTuningConfig(), valid range is from 0 to 839 (0 to 41.95dB).\n";
8001 case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE:
8002 return "Invalid AttenTuningRange detected for attRangeCfg member in MYKONOS_getClgcAttenTuningConfig(), valid range is from 0 to 420 (0 to 21dB).\n";
8003 case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS:
8004 return "Invalid Tx1 AttenTuningRange and AttenTuningPreset combination in MYKONOS_getClgcAttenTuningConfig().\n";
8005 case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS:
8006 return "Invalid Tx2 AttenTuningRange and AttenTuningPreset combination in MYKONOS_getClgcAttenTuningConfig().\n";
8007 case MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT:
8008 return "Passed structure is null in MYKONOS_getClgcAttenTuningConfig().\n";
8009
8010 default:
8011 return "Unknown error was encountered.\n";
8012 }
8013
8014 #endif
8015 }
8016
8017 /**
8018 * \brief Calculates the scaled device clock frequency at the input of the
8019 * CLKPLL or RFPLL
8020 *
8021 * Use this helper function any time the scaled device clock frequency is needed.
8022 *
8023 * <B>Dependencies</B>
8024 * - device->clocks->deviceClock_kHz
8025 * - device->spiSettings->chipSelectIndex
8026 *
8027 * \param device is structure pointer to the Mykonos data structure containing settings
8028 * \param scaledRefClk_kHz Output: The returned scaled reference clock for the device's PLLs
8029 * \param deviceClkDiv Output: The device clock divider setting that gets set in the devices SPI register.
8030 *
8031 * \retval MYKONOS_ERR_OK Function completed successfully
8032 * \retval MYKONOS_ERR_NULL_DEVICE_PARAM Function parameter device pointer is NULL
8033 * \retval MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM The scaled PLL refclk frequency is out of range (40MHz to 80MHz)
8034 * \retval MYKONOS_ERR_CALCDEVCLK_NULLPARAM Function parameter scaledRefClk_kHz or deviceClkDiv has a NULL pointer
8035 */
MYKONOS_calculateScaledDeviceClk_kHz(mykonosDevice_t * device,uint32_t * scaledRefClk_kHz,uint8_t * deviceClkDiv)8036 static mykonosErr_t MYKONOS_calculateScaledDeviceClk_kHz(mykonosDevice_t *device, uint32_t *scaledRefClk_kHz, uint8_t *deviceClkDiv)
8037 {
8038 uint32_t deviceClock_kHz = 0;
8039
8040 if ((device == NULL) || (device->clocks == NULL))
8041 {
8042 CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_NULL_DEVICE_PARAM, getMykonosErrorMessage(MYKONOS_ERR_NULL_DEVICE_PARAM));
8043 return MYKONOS_ERR_NULL_DEVICE_PARAM;
8044 }
8045
8046 #if (MYKONOS_VERBOSE == 1)
8047 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_calculateScaledDeviceClk_kHz()\n");
8048 #endif
8049
8050 deviceClock_kHz = device->clocks->deviceClock_kHz;
8051
8052 if ((scaledRefClk_kHz == NULL) || (deviceClkDiv == NULL))
8053 {
8054 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CALCDEVCLK_NULLPARAM,
8055 getMykonosErrorMessage(MYKONOS_ERR_CALCDEVCLK_NULLPARAM));
8056 return MYKONOS_ERR_CALCDEVCLK_NULLPARAM;
8057 }
8058
8059 /* scaled Ref Clock at input to CLKPLL must be in range 40-80MHz. */
8060 if (deviceClock_kHz > 20000 && deviceClock_kHz <= 40000)
8061 {
8062 *scaledRefClk_kHz = deviceClock_kHz << 1;
8063 *deviceClkDiv = 3;
8064 } /* x2 */
8065 else if (deviceClock_kHz > 40000 && deviceClock_kHz <= 80000)
8066 {
8067 *scaledRefClk_kHz = deviceClock_kHz;
8068 *deviceClkDiv = 0;
8069 } /* x1 */
8070 else if (deviceClock_kHz > 80000 && deviceClock_kHz <= 160000)
8071 {
8072 *scaledRefClk_kHz = deviceClock_kHz >> 1;
8073 *deviceClkDiv = 1;
8074 } /* div2 */
8075 else if (deviceClock_kHz > 160000 && deviceClock_kHz <= 320000)
8076 {
8077 *scaledRefClk_kHz = deviceClock_kHz >> 2;
8078 *deviceClkDiv = 2;
8079 } /* div4 */
8080 else
8081 {
8082 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM,
8083 getMykonosErrorMessage(MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM));
8084 return MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM;
8085 }
8086 return MYKONOS_ERR_OK;
8087 }
8088
8089 /**
8090 * \brief Resets the JESD204B Deframer
8091 *
8092 * <B>Dependencies</B>
8093 * - device->spiSettings
8094 *
8095 * \param device is a pointer to the device settings structure
8096 *
8097 * \retval MYKONOS_ERR_OK Function completed successfully
8098 */
MYKONOS_resetDeframer(mykonosDevice_t * device)8099 mykonosErr_t MYKONOS_resetDeframer(mykonosDevice_t *device)
8100 {
8101
8102 #if (MYKONOS_VERBOSE == 1)
8103 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetDeframer()\n");
8104 #endif
8105
8106 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_RESET, 0x03);
8107 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_RESET, 0x00);
8108
8109 return MYKONOS_ERR_OK;
8110 }
8111
8112 /**
8113 * \brief Sets up the JESD204B Serializers
8114 *
8115 * This function uses the Rx framer and ObsRx framer structures to setup the 4
8116 * serializer lanes that are shared between the two framers. If the Rx profile is valid
8117 * the serializer amplitude and preEmphasis are used from the Rx framer. If only the ObsRx
8118 * profile is valid, the obsRx framer settings are used.
8119 *
8120 * <B>Dependencies</B>
8121 * - device->spiSettings
8122 * - device->spiSettings->chipSelectIndex
8123 * - device->rx->framer->M
8124 * - device->rx->framer->serializerAmplitude
8125 * - device->rx->framer->preEmphasis
8126 * - device->rx->framer->serializerLanesEnabled
8127 * - device->rx->framer->invertLanePolarity
8128 * - device->obsRx->framer->serializerLanesEnabled
8129 * - device->obsRx->framer->invertLanePolarity
8130 * - device->obsRx->framer->M
8131 * - device->obsRx->framer->serializerLanesEnabled
8132 * - device->obsRx->framer->serializerAmplitude
8133 * - device->obsRx->framer->preEmphasis
8134 *
8135 * \param device Pointer to the device settings structure
8136 *
8137 * \retval MYKONOS_ERR_OK Function completed successfully
8138 * \retval MYKONOS_ERR_INITSER_INV_VCODIV_PARM Mykonos CLKPLL has invalid VCO divider, verify CLKPLL config
8139 * \retval MYKONOS_ERR_SER_LANE_CONFLICT_PARM When both Rx and ObsRx framers are enabled, framers can not share the same physical lane.
8140 * \retval MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM Rx Framer M can only = 1 when Real IF mode is enabled
8141 * \retval MYKONOS_ERR_SER_INV_M_PARM Invalid Rx Framer M (valid 1,2,4)
8142 * \retval MYKONOS_ERR_SER_INV_LANEEN_PARM Invalid Rx framer serializerLanesEnabled (valid 0-15)
8143 * \retval MYKONOS_ERR_SER_INV_AMP_PARM Invalid Rx serializer amplitude (valid 0-31)
8144 * \retval MYKONOS_ERR_SER_INV_PREEMP_PARM Invalid Rx serializer pre-emphesis (valid 0-7)
8145 * \retval MYKONOS_ERR_SER_INV_LANEPN_PARM Invalid Rx serializer PN invert setting (valid 0-15)
8146 * \retval MYKONOS_ERR_SER_INV_L_PARM Invalid Rx serializer lanes enabled (must use 1, 2 or 4 lanes)
8147 * \retval MYKONOS_ERR_SER_INV_LANERATE_PARM Invalid Rx serializer lane rate (valid 614.4Mbps - 6144Mbps)
8148 *
8149 * \retval MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM
8150 * \retval MYKONOS_ERR_SER_INV_LANEEN_PARM
8151 * \retval MYKONOS_ERR_SER_INV_AMP_PARM
8152 * \retval MYKONOS_ERR_SER_INV_PREEMP_PARM
8153 * \retval MYKONOS_ERR_SER_INV_LANEPN_PARM
8154 * \retval MYKONOS_ERR_SER_INV_L_PARM
8155 * \retval MYKONOS_ERR_SER_INV_LANERATE_PARM
8156 *
8157 * \retval MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM Necessary lane rates for Rx and ObsRx framer can not be obtained with possible divider settings
8158 * \retval MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT HSCLK is not an integer multiple of the lane clock rate
8159 * \retval MYKONOS_ERR_SER_INV_TXSER_DIV_PARM No valid Tx serializer divider to obtain desired lane rates
8160 * \retval MYKONOS_ERR_INITSER_INV_PROFILE Rx/ObsRx and sniffer profiles are not valid - can not config serializers
8161 * \retval MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM Invalid Rx framer PCLK divider
8162 * \retval MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM Invalid ORx/Sniffer framer PCLK divider
8163 *
8164 */
MYKONOS_setupSerializers(mykonosDevice_t * device)8165 mykonosErr_t MYKONOS_setupSerializers(mykonosDevice_t *device)
8166 {
8167 uint8_t serializerHalfRateReg = 0;
8168 uint8_t txser_div = 0;
8169 uint8_t txser_div_reg = 0;
8170 uint32_t clkPllVcoFrequency_kHz = 0;
8171 uint32_t hsclkRate_kHz = 0;
8172 uint32_t rxLaneRate_kHz = 0;
8173 uint32_t obsRxLaneRate_kHz = 0;
8174 uint32_t fasterLaneRate_kHz = 0;
8175 uint32_t slowerLaneRate_kHz = 0;
8176 uint8_t modHsLaneRate = 0;
8177 uint8_t rxL = 0;
8178 uint8_t obsRxL = 0;
8179 uint8_t i = 0;
8180 uint8_t amplitudeEmphasis = 0;
8181 uint8_t lanePowerDown = 0x00;
8182 mykonosVcoDiv_t vcoDiv = VCODIV_1;
8183 uint8_t rxLanePn = 0;
8184 uint8_t obsRxLanePn = 0;
8185
8186 uint32_t hsDigClkdiv4_5_kHz = 0;
8187 uint32_t rxPclkDiv = 0;
8188 uint32_t obsRxPclkDiv = 0;
8189 uint32_t tempPclkDiv = 0;
8190 uint32_t rxFramerPclk_kHz = 0;
8191 uint32_t obsRxFramerPclk_kHz = 0;
8192 uint8_t rxSyncbSelect = 0;
8193 uint8_t obsRxSyncbSelect = 0;
8194
8195 static const uint32_t MAX_HSCLK_KHZ_IF_VCODIV1P5 = 6144000; /* max VCO /1.5 output is 6144Mhz. This limits VCO to 9216MHz */
8196 static const uint32_t MAX_HSCLK_KHZ_IF_VCODIV1 = 8000000; /* max VCO div1 output is 8000Mhz. This limits VCO to 8000MHz */
8197 static const uint32_t MIN_SERIALIZER_RATE_KHZ = 614400; /* max serializer lane rate = 0.6144 Gbps */
8198 static const uint32_t MAX_SERIALIZER_RATE_KHZ = 6144000; /* max serializer lane rate = 6.144 Gbps */
8199 #if (MYKONOS_VERBOSE == 1)
8200 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupSerializers()\n");
8201 #endif
8202
8203 vcoDiv = device->clocks->clkPllVcoDiv;
8204 clkPllVcoFrequency_kHz = device->clocks->clkPllVcoFreq_kHz;
8205
8206 switch (vcoDiv)
8207 {
8208 case VCODIV_1:
8209 hsclkRate_kHz = clkPllVcoFrequency_kHz;
8210
8211 /* max VCO /1 output is 8000Mhz. This limits VCO to 8000MHz */
8212 if (hsclkRate_kHz > MAX_HSCLK_KHZ_IF_VCODIV1)
8213 {
8214 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM,
8215 getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM));
8216 return MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM;
8217 }
8218
8219 break;
8220
8221 case VCODIV_1p5:
8222 hsclkRate_kHz = (clkPllVcoFrequency_kHz / 15) * 10;
8223
8224 /* max VCO /1.5 output is 6144Mhz. This limits VCO to 9216MHz */
8225 if (hsclkRate_kHz > MAX_HSCLK_KHZ_IF_VCODIV1P5)
8226 {
8227 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM,
8228 getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM));
8229 return MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM;
8230 }
8231
8232 break;
8233
8234 case VCODIV_2:
8235 hsclkRate_kHz = clkPllVcoFrequency_kHz >> 1;
8236 break;
8237
8238 case VCODIV_3:
8239 hsclkRate_kHz = (clkPllVcoFrequency_kHz / 30) * 10;
8240 break;
8241
8242 default:
8243 {
8244 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_VCODIV_PARM,
8245 getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_VCODIV_PARM));
8246 return MYKONOS_ERR_INITSER_INV_VCODIV_PARM;
8247 }
8248 }
8249
8250 if ((device->profilesValid & RX_PROFILE_VALID) && (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)))
8251 {
8252 if (device->rx->framer->serializerLanesEnabled & device->obsRx->framer->serializerLanesEnabled)
8253 {
8254 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_LANE_CONFLICT_PARM,
8255 getMykonosErrorMessage(MYKONOS_ERR_SER_LANE_CONFLICT_PARM));
8256 return MYKONOS_ERR_SER_LANE_CONFLICT_PARM;
8257 }
8258 }
8259
8260 lanePowerDown = 0x9F;
8261 if (device->profilesValid & RX_PROFILE_VALID)
8262 {
8263 if (device->rx->framer->M == 1 && !(device->rx->realIfData))
8264 {
8265 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM,
8266 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM));
8267 return MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM;
8268 }
8269
8270 if (device->rx->framer->M != 1 && device->rx->framer->M != 2 && device->rx->framer->M != 4)
8271 {
8272 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_M_PARM));
8273 return MYKONOS_ERR_SER_INV_M_PARM;
8274 }
8275
8276 for (i = 0; i < 4; i++)
8277 {
8278 rxL += ((device->rx->framer->serializerLanesEnabled >> i) & 0x01);
8279 }
8280
8281 if (device->rx->framer->serializerLanesEnabled > 15)
8282 {
8283 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEEN_PARM,
8284 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEEN_PARM));
8285 return MYKONOS_ERR_SER_INV_LANEEN_PARM;
8286 }
8287
8288 if (device->rx->framer->serializerAmplitude > 31)
8289 {
8290 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_AMP_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_AMP_PARM));
8291 return MYKONOS_ERR_SER_INV_AMP_PARM;
8292 }
8293
8294 if (device->rx->framer->preEmphasis > 7)
8295 {
8296 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_PREEMP_PARM,
8297 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_PREEMP_PARM));
8298 return MYKONOS_ERR_SER_INV_PREEMP_PARM;
8299 }
8300
8301 if (device->rx->framer->invertLanePolarity > 15)
8302 {
8303 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEPN_PARM,
8304 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEPN_PARM));
8305 return MYKONOS_ERR_SER_INV_LANEPN_PARM;
8306 }
8307 if ((rxL != 1) && (rxL != 2) && (rxL != 4))
8308 {
8309 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_L_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_L_PARM));
8310 return MYKONOS_ERR_SER_INV_L_PARM;
8311 }
8312
8313 rxLaneRate_kHz = device->rx->rxProfile->iqRate_kHz * 20 * device->rx->framer->M / rxL;
8314 lanePowerDown &= (~(device->rx->framer->serializerLanesEnabled));
8315
8316 if ((rxLaneRate_kHz < MIN_SERIALIZER_RATE_KHZ) || (rxLaneRate_kHz > MAX_SERIALIZER_RATE_KHZ))
8317 {
8318 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANERATE_PARM,
8319 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANERATE_PARM));
8320 return MYKONOS_ERR_SER_INV_LANERATE_PARM;
8321 }
8322 }
8323
8324 if ((device->obsRx->framer != NULL) && (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)))
8325 {
8326 if ((device->obsRx->framer->M == 1) && !(device->obsRx->realIfData))
8327 {
8328 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM,
8329 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM));
8330 return MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM;
8331 }
8332
8333 for (i = 0; i < 4; i++)
8334 {
8335 obsRxL += ((device->obsRx->framer->serializerLanesEnabled >> i) & 0x01);
8336 }
8337
8338 if (device->obsRx->framer->serializerLanesEnabled > 15)
8339 {
8340 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEEN_PARM,
8341 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEEN_PARM));
8342 return MYKONOS_ERR_SER_INV_LANEEN_PARM;
8343 }
8344
8345 if (device->obsRx->framer->serializerAmplitude > 31)
8346 {
8347 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_AMP_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_AMP_PARM));
8348 return MYKONOS_ERR_SER_INV_AMP_PARM;
8349 }
8350
8351 if (device->obsRx->framer->preEmphasis > 7)
8352 {
8353 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_PREEMP_PARM,
8354 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_PREEMP_PARM));
8355 return MYKONOS_ERR_SER_INV_PREEMP_PARM;
8356 }
8357
8358 if (device->obsRx->framer->invertLanePolarity > 15)
8359 {
8360 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEPN_PARM,
8361 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEPN_PARM));
8362 return MYKONOS_ERR_SER_INV_LANEPN_PARM;
8363 }
8364
8365 if ((obsRxL != 0) && (obsRxL != 1) && (obsRxL != 2) && (obsRxL != 4))
8366 {
8367 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_L_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_L_PARM));
8368 return MYKONOS_ERR_SER_INV_L_PARM;
8369 }
8370
8371 /* check for valid pointer */
8372 if (obsRxL == 0)
8373 {
8374 /* Allow ORx receiver to work but disable Obs Rx framer link - valid on a DPD-enabled transceiver */
8375 obsRxLaneRate_kHz = 0;
8376 }
8377 else if (device->profilesValid & ORX_PROFILE_VALID)
8378 {
8379 obsRxLaneRate_kHz = device->obsRx->orxProfile->iqRate_kHz * 20 * device->obsRx->framer->M / obsRxL;
8380 }
8381 else if (device->profilesValid & SNIFF_PROFILE_VALID)
8382 {
8383 obsRxLaneRate_kHz = device->obsRx->snifferProfile->iqRate_kHz * 20 * device->obsRx->framer->M / obsRxL;
8384 }
8385
8386 lanePowerDown &= (~(device->obsRx->framer->serializerLanesEnabled));
8387
8388 if ((obsRxLaneRate_kHz != 0) && ((obsRxLaneRate_kHz < MIN_SERIALIZER_RATE_KHZ) || (obsRxLaneRate_kHz > MAX_SERIALIZER_RATE_KHZ)))
8389 {
8390 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANERATE_PARM,
8391 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANERATE_PARM));
8392 return MYKONOS_ERR_SER_INV_LANERATE_PARM;
8393 }
8394 }
8395
8396 /* checking for RX and OBSRX effective lane rates match */
8397 /* Need to account for oversampling, verify that the 2 lane rate are integer related */
8398
8399 if ((rxLaneRate_kHz > 0) && (obsRxLaneRate_kHz > 0))
8400 {
8401 fasterLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (rxLaneRate_kHz) : (obsRxLaneRate_kHz);
8402 slowerLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (obsRxLaneRate_kHz) : (rxLaneRate_kHz);
8403
8404 /* Verify that lane rates are integer multiples of each other */
8405 if ((fasterLaneRate_kHz % slowerLaneRate_kHz) != 0)
8406 {
8407 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM,
8408 getMykonosErrorMessage(MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM));
8409 return MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM;
8410 }
8411 }
8412 else
8413 {
8414 fasterLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (rxLaneRate_kHz) : (obsRxLaneRate_kHz);
8415 }
8416
8417 /* performing integer multiple check on HS clock and lane rate clock */
8418 if (fasterLaneRate_kHz == 0)
8419 {
8420 /* All serializer lanes are disabled */
8421 txser_div = 1;
8422 txser_div_reg = 0;
8423 serializerHalfRateReg = 0;
8424 }
8425 else
8426 {
8427 if ((fasterLaneRate_kHz > hsclkRate_kHz) ||
8428 (fasterLaneRate_kHz > MAX_SERIALIZER_RATE_KHZ))
8429 {
8430 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANERATE_PARM,
8431 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANERATE_PARM));
8432 return MYKONOS_ERR_SER_INV_LANERATE_PARM;
8433 }
8434
8435 modHsLaneRate = (uint8_t)(hsclkRate_kHz % fasterLaneRate_kHz);
8436 if (modHsLaneRate != 0)
8437 {
8438 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT,
8439 getMykonosErrorMessage(MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT));
8440 return MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT;
8441 }
8442
8443 txser_div = (uint8_t)(hsclkRate_kHz / fasterLaneRate_kHz); /* Total serializer Divider (1,2,4,8) */
8444 switch (txser_div)
8445 {
8446 case 1:
8447 txser_div_reg = 0; /* Divide hsclk by 1 */
8448 serializerHalfRateReg = 0; /* 0 = divide serializer clock by 1 */
8449 break;
8450 case 2:
8451 txser_div_reg = 1; /* Divide hsclk by 2 */
8452 serializerHalfRateReg = 0; /* 0 = divide serializer clock by 1 */
8453 break;
8454 case 4:
8455 txser_div_reg = 2; /* Divide hsclk by 4 */
8456 serializerHalfRateReg = 0; /* 0 = divide serializer clock by 1 */
8457 break;
8458 case 8:
8459 txser_div_reg = 2; /* Divide hsclk by 4 */
8460 serializerHalfRateReg = 1; /* 1 = divide serializer clock by 2 */
8461 break;
8462 default:
8463 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_TXSER_DIV_PARM,
8464 getMykonosErrorMessage(MYKONOS_ERR_SER_INV_TXSER_DIV_PARM));
8465 return MYKONOS_ERR_SER_INV_TXSER_DIV_PARM;
8466 }
8467 }
8468
8469 if (device->profilesValid & RX_PROFILE_VALID)
8470 {
8471 amplitudeEmphasis = ((device->rx->framer->serializerAmplitude & 0x1f) << 3) | (device->rx->framer->preEmphasis & 0x07);
8472 }
8473 else if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))
8474 {
8475 amplitudeEmphasis = ((device->obsRx->framer->serializerAmplitude & 0x1f) << 3) | (device->obsRx->framer->preEmphasis & 0x07);
8476 }
8477 else
8478 {
8479 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_PROFILE, getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_PROFILE));
8480 return MYKONOS_ERR_INITSER_INV_PROFILE;
8481 }
8482
8483 if (device->profilesValid & RX_PROFILE_VALID)
8484 {
8485 rxSyncbSelect = (device->rx->framer->obsRxSyncbSelect > 0) ? 1 : 0;
8486 rxLanePn = (uint8_t)(rxSyncbSelect << 7) | (device->rx->framer->invertLanePolarity & 0xF);
8487 }
8488
8489 if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))
8490 {
8491 obsRxSyncbSelect = (device->obsRx->framer->obsRxSyncbSelect > 0) ? 1 : 0;
8492 obsRxLanePn = (uint8_t)(obsRxSyncbSelect << 7) | (device->obsRx->framer->invertLanePolarity & 0xF);
8493 }
8494
8495 /* Serializer lane clock frequency */
8496 /* serLaneClock_kHz = fasterLaneRate_kHz / txser_div / 20; */
8497 if (device->profilesValid & RX_PROFILE_VALID)
8498 {
8499 /* calculate manual PCLK frequency for Rx framer = Rx IQrate * F, where F = (2*M/L) or PCLK = lanerate /10 */
8500 if (device->rx->framer->overSample)
8501 {
8502 rxFramerPclk_kHz = fasterLaneRate_kHz / 10;
8503 }
8504 else
8505 {
8506 rxFramerPclk_kHz = rxLaneRate_kHz / 10;
8507 }
8508
8509 hsDigClkdiv4_5_kHz = hsclkRate_kHz / device->clocks->clkPllHsDiv / device->rx->rxProfile->rxDec5Decimation;
8510
8511 /* PCLKDiv: 0=4x, 1=2x, 2=1x, 3=/2, 4=/4, 5=/8, 6=/16 */
8512 if (hsDigClkdiv4_5_kHz == rxFramerPclk_kHz)
8513 {
8514 rxPclkDiv = 2;
8515 }
8516 else if (hsDigClkdiv4_5_kHz > rxFramerPclk_kHz)
8517 {
8518 if (rxFramerPclk_kHz == 0)
8519 {
8520 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM,
8521 getMykonosErrorMessage(MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM));
8522 return MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM;
8523 }
8524
8525 tempPclkDiv = hsDigClkdiv4_5_kHz / rxFramerPclk_kHz;
8526 switch (tempPclkDiv)
8527 {
8528 case 2:
8529 rxPclkDiv = 3;
8530 break;
8531 case 4:
8532 rxPclkDiv = 4;
8533 break;
8534 case 8:
8535 rxPclkDiv = 5;
8536 break;
8537 case 16:
8538 rxPclkDiv = 6;
8539 break;
8540 default:
8541 {
8542 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM,
8543 getMykonosErrorMessage(MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM));
8544 return MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM;
8545 }
8546 }
8547 }
8548 else if (hsDigClkdiv4_5_kHz < rxFramerPclk_kHz)
8549 {
8550 tempPclkDiv = rxFramerPclk_kHz / hsDigClkdiv4_5_kHz;
8551 switch (tempPclkDiv)
8552 {
8553 case 2:
8554 rxPclkDiv = 1;
8555 break;
8556 case 4:
8557 rxPclkDiv = 0;
8558 break;
8559 default:
8560 {
8561 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM,
8562 getMykonosErrorMessage(MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM));
8563 return MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM;
8564 }
8565 }
8566 }
8567 }
8568
8569 if (obsRxL == 0)
8570 {
8571 /* Make sure PCLK is set as low as possible because it interacts with Rx Framer logic, */
8572 /* even though ObsRx Framer disabled */
8573 obsRxPclkDiv = 6;
8574 }
8575 else if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))
8576 {
8577 /* calculate manual PCLK frequency for obsRx framer = obsRx IQrate * F, where F = (2*M/L) */
8578 if (device->profilesValid & ORX_PROFILE_VALID)
8579 {
8580 if (device->obsRx->framer->overSample)
8581 {
8582 obsRxFramerPclk_kHz = fasterLaneRate_kHz / 10;
8583 }
8584 else
8585 {
8586 obsRxFramerPclk_kHz = obsRxLaneRate_kHz / 10;
8587 }
8588
8589 hsDigClkdiv4_5_kHz = hsclkRate_kHz / device->clocks->clkPllHsDiv / device->obsRx->orxProfile->rxDec5Decimation;
8590 }
8591 else if (device->profilesValid & SNIFF_PROFILE_VALID)
8592 {
8593 if (device->obsRx->framer->overSample)
8594 {
8595 obsRxFramerPclk_kHz = fasterLaneRate_kHz / 10;
8596 }
8597 else
8598 {
8599 obsRxFramerPclk_kHz = obsRxLaneRate_kHz / 10;
8600 }
8601
8602 hsDigClkdiv4_5_kHz = hsclkRate_kHz / device->clocks->clkPllHsDiv / device->obsRx->snifferProfile->rxDec5Decimation;
8603 }
8604
8605 /* PCLKDiv: 0=4x, 1=2x, 2=1x, 3=/2, 4=/4, 5=/8, 6=/16 */
8606 if (hsDigClkdiv4_5_kHz == obsRxFramerPclk_kHz)
8607 {
8608 obsRxPclkDiv = 2;
8609 }
8610 else if ((hsDigClkdiv4_5_kHz > obsRxFramerPclk_kHz) && (obsRxFramerPclk_kHz != 0))
8611 {
8612 tempPclkDiv = hsDigClkdiv4_5_kHz / obsRxFramerPclk_kHz;
8613 switch (tempPclkDiv)
8614 {
8615 case 2:
8616 obsRxPclkDiv = 3;
8617 break;
8618 case 4:
8619 obsRxPclkDiv = 4;
8620 break;
8621 case 8:
8622 obsRxPclkDiv = 5;
8623 break;
8624 case 16:
8625 obsRxPclkDiv = 6;
8626 break;
8627 default:
8628 {
8629 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM,
8630 getMykonosErrorMessage(MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM));
8631 return MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM;
8632 }
8633 }
8634 }
8635 else if (hsDigClkdiv4_5_kHz < obsRxFramerPclk_kHz)
8636 {
8637 if (hsDigClkdiv4_5_kHz == 0)
8638 {
8639 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM,
8640 getMykonosErrorMessage(MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM));
8641 return MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM;
8642 }
8643
8644 tempPclkDiv = obsRxFramerPclk_kHz / hsDigClkdiv4_5_kHz;
8645 switch (tempPclkDiv)
8646 {
8647 case 2:
8648 obsRxPclkDiv = 1;
8649 break;
8650 case 4:
8651 obsRxPclkDiv = 0;
8652 break;
8653 default:
8654 {
8655 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM,
8656 getMykonosErrorMessage(MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM));
8657 return MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM;
8658 }
8659 }
8660 }
8661 }
8662
8663 /* set lane rate divide setting */
8664 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_3, txser_div_reg, 0x03, 0);
8665
8666 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_2, amplitudeEmphasis);
8667
8668 /* Serializer: Release Reset */
8669 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_SPECIAL, 0x03);
8670
8671 /* Serializer: txser clk enable */
8672 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_HS_DIV_TXSER_CLK_EN, 0x01);
8673
8674 /* Serializer: Enable 2 to 1 serializer */
8675 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_3, 0x20 | serializerHalfRateReg);
8676
8677 /* power up desired serializer lanes */
8678 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, lanePowerDown);
8679
8680 /* apply desired lane PN inversions to the TX and OBSRX framers */
8681 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LANE_DATA_CTL, rxLanePn);
8682 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_DATA_CTL, obsRxLanePn);
8683
8684 /* set Rx framer manual PCLK frequency based on lane rate of the serializers */
8685 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, (uint8_t)rxPclkDiv, 0x70, 4);
8686
8687 /* enable bit repeat mode in Rx framer - since manual PCLK, oversample will still work */
8688 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 0, 0x80, 7);
8689
8690 /* enable manual PCLK mode in Rx framer */
8691 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 1, 0x04, 2);
8692
8693 /* set obsRx framer manual PCLK frequency based on lane rate of the serializers */
8694 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, (uint8_t)obsRxPclkDiv, 0x70, 4);
8695
8696 /* enable bit repeat mode in ObsRx framer - since manual PCLK, oversample will still work */
8697 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0, 0x80, 7);
8698
8699 /* enable manual PCLK mode in ObsRx framer */
8700 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 1, 0x04, 2);
8701
8702 return MYKONOS_ERR_OK;
8703 }
8704
8705 /**
8706 * \brief Sets up the JESD204B Deserializers
8707 *
8708 * This function enables the necessary deserializer lanes, sets the deserializer clocks
8709 * PN inversion settings, and EQ settings based on the info found in the device data structure.
8710 *
8711 * <B>Dependencies</B>
8712 * - device->spiSettings
8713 * - device->spiSettings->chipSelectIndex
8714 * - device->tx->txProfile->clkPllVcoDiv
8715 * - device->tx->txProfile->vcoFreq_kHz
8716 * - device->tx->txProfile->txIqRate_kHz
8717 * - device->tx->deframer->M
8718 * - device->tx->deframer->deserializerLanesEnabled
8719 * - device->tx->deframer->invertLanePolarity
8720 * - device->tx->deframer->EQSetting
8721 *
8722 * \param device Pointer to the device settings structure
8723
8724 * \retval MYKONOS_ERR_OK Function completed successfully
8725 * \retval MYKONOS_ERR_INITDES_INV_TXPROFILE Tx Profile is not valid in data structure - can not setup deserializer
8726 * \retval MYKONOS_ERR_INITDES_INV_VCODIV_PARM Mykonos CLKPLL VCO divider is invalid
8727 * \retval MYKONOS_ERR_DESER_INV_M_PARM Invalid M (valid 2 or 4)
8728 * \retval MYKONOS_ERR_DESER_INV_L_PARM Invalid L (valid 1,2,4)
8729 * \retval MYKONOS_ERR_DESER_INV_HSCLK_PARM Invalid HSCLK, must be 6.144G or less after CLKPLL VCO divider - verify CLKPLL config
8730 * \retval MYKONOS_ERR_DESER_INV_LANERATE_PARM Invalid lanerate, must be between 614.4 Mbps to 6144 Mbps
8731 * \retval MYKONOS_ERR_DESER_INV_LANEEN_PARM Invalid deserializerLanesEnabled (valid 0-15 in 1,2,4 lane combinations)
8732 * \retval MYKONOS_ERR_DESER_INV_EQ_PARM Invalid EQ parameter (valid 0-4)
8733 * \retval MYKONOS_ERR_DESER_INV_LANEPN_PARM Invalid PN invert setting, (valid 0-15, invert bit per lane)
8734 * \retval MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT Invalid clock settings, HSCLK is not an integer multiple of lane rate
8735 *
8736 */
MYKONOS_setupDeserializers(mykonosDevice_t * device)8737 mykonosErr_t MYKONOS_setupDeserializers(mykonosDevice_t *device)
8738 {
8739 uint8_t lanePowerDown = 0xF;
8740 uint8_t des_div = 0;
8741 uint8_t des_div_bitfield = 0;
8742 uint8_t rxcdr_div = 0;
8743 uint8_t rxcdr_div_bitfield = 0;
8744 uint32_t hsclkRate_kHz = 0;
8745 uint8_t i = 0;
8746 uint8_t L = 0;
8747 uint32_t laneRate_kHz = 0;
8748 uint8_t invertLanePolarity = 0;
8749 uint8_t modHsLaneRate = 0;
8750
8751 const uint32_t MAX_HSCLKRATE_KHZ = 12288000;
8752
8753 #if (MYKONOS_VERBOSE == 1)
8754 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupDeserializers()\n");
8755 #endif
8756
8757 if ((device->profilesValid & TX_PROFILE_VALID) == 0)
8758 {
8759 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITDES_INV_TXPROFILE,
8760 getMykonosErrorMessage(MYKONOS_ERR_INITDES_INV_TXPROFILE));
8761 return MYKONOS_ERR_INITDES_INV_TXPROFILE;
8762 }
8763
8764 if (device->tx->deframer->M != 2 && device->tx->deframer->M != 4)
8765 {
8766 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_M_PARM));
8767 return MYKONOS_ERR_DESER_INV_M_PARM;
8768 }
8769
8770 for (i = 0; i < 4; i++)
8771 {
8772 L += ((device->tx->deframer->deserializerLanesEnabled >> i) & 0x01);
8773 }
8774
8775 if ((L == 0) || (L == 3) || (L > 4))
8776 {
8777 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_L_PARM, getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_L_PARM));
8778 return MYKONOS_ERR_DESER_INV_L_PARM;
8779 }
8780
8781 //laneRate_kHz calculation and checks
8782 laneRate_kHz = device->tx->txProfile->iqRate_kHz * 20 * device->tx->deframer->M / L;
8783
8784 if ((laneRate_kHz < 614400) || (laneRate_kHz > 6144000))
8785 {
8786 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANERATE_PARM,
8787 getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANERATE_PARM));
8788 return MYKONOS_ERR_DESER_INV_LANERATE_PARM;
8789 }
8790
8791 if (device->tx->deframer->deserializerLanesEnabled > 15)
8792 {
8793 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANEEN_PARM,
8794 getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANEEN_PARM));
8795 return MYKONOS_ERR_DESER_INV_LANEEN_PARM;
8796 }
8797
8798 if ((device->tx->deframer->deserializerLanesEnabled == 0x7) || (device->tx->deframer->deserializerLanesEnabled == 0xB)
8799 || (device->tx->deframer->deserializerLanesEnabled == 0xD) || (device->tx->deframer->deserializerLanesEnabled == 0xE))
8800 {
8801 /* 3 lanes not valid, only 1,2, or 4 lanes */
8802 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANEEN_PARM,
8803 getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANEEN_PARM));
8804 return MYKONOS_ERR_DESER_INV_LANEEN_PARM;
8805 }
8806
8807 if (device->tx->deframer->EQSetting > 4)
8808 {
8809 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_EQ_PARM, getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_EQ_PARM));
8810 return MYKONOS_ERR_DESER_INV_EQ_PARM;
8811 }
8812
8813 if (device->tx->deframer->invertLanePolarity > 15)
8814 {
8815 /* only lower 4 bits of parameter are valid */
8816 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANEPN_PARM,
8817 getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANEPN_PARM));
8818 return MYKONOS_ERR_DESER_INV_LANEPN_PARM;
8819 }
8820
8821 //hsclkRate_kHz calculations
8822 switch (device->clocks->clkPllVcoDiv)
8823 {
8824 case VCODIV_1:
8825 hsclkRate_kHz = device->clocks->clkPllVcoFreq_kHz;
8826 break;
8827 case VCODIV_1p5:
8828 hsclkRate_kHz = (device->clocks->clkPllVcoFreq_kHz / 15) * 10;
8829 break;
8830 case VCODIV_2:
8831 hsclkRate_kHz = device->clocks->clkPllVcoFreq_kHz >> 1;
8832 break;
8833 case VCODIV_3:
8834 hsclkRate_kHz = (device->clocks->clkPllVcoFreq_kHz / 30) * 10;
8835 break;
8836 default:
8837 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITDES_INV_VCODIV_PARM,
8838 getMykonosErrorMessage(MYKONOS_ERR_INITDES_INV_VCODIV_PARM));
8839 return MYKONOS_ERR_INITDES_INV_VCODIV_PARM;
8840 }
8841
8842 /* The deserializer clock needs to be in the range 3.8GHz to 6.144 GHz in reg x107. The rest of the division is in xDD */
8843 if (hsclkRate_kHz <= 6144000)
8844 {
8845 rxcdr_div = 1;
8846 }
8847 else if ((hsclkRate_kHz > 6144000) && (hsclkRate_kHz <= MAX_HSCLKRATE_KHZ))
8848 {
8849 rxcdr_div = 2;
8850 }
8851 else if ((hsclkRate_kHz > MAX_HSCLKRATE_KHZ) && (hsclkRate_kHz < 24576000))
8852 {
8853 rxcdr_div = 4;
8854 }
8855 else
8856 {
8857 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_HSCLK_PARM,
8858 getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_HSCLK_PARM));
8859 return MYKONOS_ERR_DESER_INV_HSCLK_PARM;
8860 }
8861
8862 switch (rxcdr_div)
8863 {
8864 case 1:
8865 rxcdr_div_bitfield = 0;
8866 break;
8867 case 2:
8868 rxcdr_div_bitfield = 1;
8869 break;
8870
8871 default:
8872 /* Default case is when rxcdr_div == 4 */
8873 rxcdr_div_bitfield = 2;
8874 break;
8875 }
8876
8877 /* performing integer multiple check on HS clock and lane rate clock */
8878 modHsLaneRate = (uint8_t)(hsclkRate_kHz % laneRate_kHz);
8879 if (modHsLaneRate)
8880 {
8881 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT,
8882 getMykonosErrorMessage(MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT));
8883 return MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT;
8884 }
8885
8886 des_div = (uint8_t)(hsclkRate_kHz / laneRate_kHz / rxcdr_div);
8887
8888 switch (des_div)
8889 {
8890 case 1:
8891 des_div_bitfield = 0;
8892 break;
8893 case 2:
8894 des_div_bitfield = 1;
8895 break;
8896 case 4:
8897 des_div_bitfield = 2;
8898 break;
8899 case 8:
8900 des_div_bitfield = 3;
8901 break;
8902 default:
8903 des_div_bitfield = 0;
8904 break;
8905 }
8906
8907 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_3, rxcdr_div_bitfield, 0x0C, 0x02);
8908
8909 invertLanePolarity = (device->tx->deframer->invertLanePolarity & 0xF);
8910
8911 lanePowerDown = (~(device->tx->deframer->deserializerLanesEnabled)) & 0xF;
8912
8913 /* Deserializer: PLL clock enable */
8914 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_HS_DIV_RXCDR_CLK_EN, 0x01);
8915
8916 /* Deserializer: Set Pdet control */
8917 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_PDET_CTL, 0x09);
8918
8919 /* Deserializer: Set Power down control */
8920 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_CTL_0, (0x80U | lanePowerDown | (uint8_t)(des_div_bitfield << 4)));
8921
8922 /* Deserializer: Set Sine Shape */
8923 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SIN_SHAPE_0, 0x00);
8924
8925 /* Deserializer: Set ss gain and vga */
8926 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SIN_SHAPE_1, 0x00);
8927
8928 /* Deserializer: Enable EQ, AC coupled JESD204B lanes */
8929 /* TODO: add ability to set this for AC coupling or DC coupling */
8930 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_EQ_CTL_1, 0x07);
8931
8932 /* Deserializer: Clear Data present at negedge, disable peak adjust */
8933 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_MISC_CTL, 0x04);
8934
8935 /* Deserializer: Set Equalizer for lanes 1 and 0 */
8936 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_EQ_CTL_1_TO_0, ((uint8_t)(device->tx->deframer->EQSetting << 3) | device->tx->deframer->EQSetting));
8937
8938 /* Deserializer: Set Equalizer for lanes 2 and 3 */
8939 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_EQ_CTL_3_TO_2, ((uint8_t)(device->tx->deframer->EQSetting << 3) | device->tx->deframer->EQSetting));
8940
8941 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LANE_DATA_CTL, invertLanePolarity);
8942
8943 /* Reset Deserializers - toggle resetb bit in [0] */
8944 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SPECIAL, 0x00);
8945 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SPECIAL, 0x01);
8946
8947 /* Start ALC cal */
8948 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_CDR_CAL_CTL, 0x02);
8949
8950 /* Deframer: Enable clocks and lane clocks */
8951 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_CLK_EN, 0x03);
8952
8953 return MYKONOS_ERR_OK;
8954 }
8955
8956 /**
8957 * \brief Sets up the JESD204B Framer
8958 *
8959 * <B>Dependencies</B>
8960 * - device->spiSettings
8961 * - device->spiSettings->chipSelectIndex
8962 * - device->rx->framer->M
8963 * - device->rx->realIfData
8964 * - device->rx->framer->bankId
8965 * - device->rx->framer->lane0Id
8966 * - device->rx->framer->serializerLanesEnabled
8967 * - device->rx->framer->obsRxSyncbSelect
8968 * - device->rx->framer->K
8969 * - device->rx->framer->externalSysref
8970 * - device->rx->rxChannels
8971 * - device->rx->framer->newSysrefOnRelink
8972 * - device->rx->framer->enableAutoChanXbar
8973 * - device->rx->framer->lmfcOffset
8974 * - device->rx->framer->scramble
8975 *
8976 * \param device Pointer to the device settings structure
8977 *
8978 * \retval MYKONOS_ERR_OK Function completed successfully
8979 * \retval MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM Invalid framer M, M can only = 1 in real IF mode
8980 * \retval MYKONOS_ERR_FRAMER_INV_M_PARM Invalid framer M (valid 1,2,4)
8981 * \retval MYKONOS_ERR_FRAMER_INV_BANKID_PARM Invalid BankId (valid 0-15)
8982 * \retval MYKONOS_ERR_FRAMER_INV_LANEID_PARM Invalid Lane0Id (valid 0-31)
8983 * \retval MYKONOS_ERR_RXFRAMER_INV_FK_PARAM
8984 * \retval MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM
8985 */
MYKONOS_setupJesd204bFramer(mykonosDevice_t * device)8986 mykonosErr_t MYKONOS_setupJesd204bFramer(mykonosDevice_t *device)
8987 {
8988 uint8_t i = 0;
8989 uint8_t fifoLaneEnable = 0;
8990 uint8_t L = 0;
8991 uint8_t ML = 0;
8992 uint8_t framerConfigF = 0;
8993
8994 uint8_t subaddr[29] = {0}; /* holds address to framer sub register map */
8995 uint8_t subdata[29] = {0}; /* holds data for framer sub register map */
8996
8997 /* Setup submap registers */
8998 uint8_t SUBCLASSV = 1; /* JESD subclass 1 */
8999 uint8_t JESDV = 1; /* Version: JESD204B */
9000 uint8_t DID = 0;
9001 uint8_t BID = 0;
9002 uint8_t LID0 = 0;
9003 uint8_t LID1 = 1;
9004 uint8_t LID2 = 2;
9005 uint8_t LID3 = 3;
9006 uint8_t CS = 0;
9007 uint8_t N = 0x0F;
9008 uint8_t Np = 0x0F;
9009 uint8_t S = 0;
9010 uint8_t CF = 0;
9011 uint8_t K = 31;
9012 uint8_t HD = 0;
9013 uint8_t FramerL = 1;
9014 uint8_t FramerM = 2;
9015 uint8_t FramerF = 1;
9016 uint8_t framerADC_XBar = 0xE4;
9017 uint16_t FK = 0;
9018
9019 uint8_t regE0 = 0;
9020 uint8_t regE2 = 0;
9021 uint8_t framerLaneXbar = 0xE4;
9022 uint16_t CheckSum = 0;
9023
9024 #if (MYKONOS_VERBOSE == 1)
9025 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupJesd204bFramer()\n");
9026 #endif
9027
9028 if (device->rx->framer->M == 1 && !(device->rx->realIfData))
9029 {
9030 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM,
9031 getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM));
9032 return MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM;
9033 }
9034
9035 if (device->rx->framer->M != 1 && device->rx->framer->M != 2 && device->rx->framer->M != 4)
9036 {
9037 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_M_PARM));
9038 return MYKONOS_ERR_FRAMER_INV_M_PARM;
9039 }
9040
9041 if (device->rx->framer->bankId > 15)
9042 {
9043 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_BANKID_PARM,
9044 getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_BANKID_PARM));
9045 return MYKONOS_ERR_FRAMER_INV_BANKID_PARM;
9046 }
9047
9048 /* no need to check deviceId, its range is full uint8_t range */
9049 if (device->rx->framer->lane0Id > 31)
9050 {
9051 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_LANEID_PARM,
9052 getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_LANEID_PARM));
9053 return MYKONOS_ERR_FRAMER_INV_LANEID_PARM;
9054 }
9055
9056 //count number of lanes
9057 L = 0;
9058 ML = 0;
9059
9060 for (i = 0; i < 4; i++)
9061 {
9062 L += ((device->rx->framer->serializerLanesEnabled >> i) & 0x01);
9063 }
9064 ML = (uint8_t)(device->rx->framer->M * 10) + L;
9065
9066 FK = (uint16_t)(device->rx->framer->K * 2 * device->rx->framer->M / L);
9067
9068 if (FK < 20 || FK > 256 || FK % 4 != 0)
9069 {
9070 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFRAMER_INV_FK_PARAM,
9071 getMykonosErrorMessage(MYKONOS_ERR_RXFRAMER_INV_FK_PARAM));
9072 return MYKONOS_ERR_RXFRAMER_INV_FK_PARAM;
9073 }
9074
9075 if (device->rx->framer->externalSysref == 0)
9076 {
9077 /* Framer: Generate SYSREF internally */
9078 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_TEST_CNTR_CTL, 0x20);
9079 }
9080
9081 framerADC_XBar = 0xB1;
9082 if (ML == 24)
9083 {
9084 if (device->rx->rxChannels == RX1)
9085 {
9086 /* adc 0 and 2 used */
9087 framerADC_XBar = ((framerADC_XBar & 0x0C) << 2) | (framerADC_XBar & 0x03);
9088 }
9089 else if (device->rx->rxChannels == RX2)
9090 {
9091 /* swap ADC xbar for Rx1 and Rx2 */
9092 framerADC_XBar = ((framerADC_XBar & 0xF) << 4) | ((framerADC_XBar & 0xF0) >> 4);
9093 /* adc 0 and 2 used */
9094 framerADC_XBar = ((framerADC_XBar & 0x0C) << 2) | (framerADC_XBar & 0x03);
9095 }
9096
9097 /* Framer: Set ADC Crossbar */
9098 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_ADC_XBAR_SEL, framerADC_XBar);
9099 }
9100 else
9101 {
9102 /* Framer: Set ADC Crossbar */
9103 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_ADC_XBAR_SEL, framerADC_XBar);
9104 }
9105
9106 if (device->rx->framer->enableManualLaneXbar == 1)
9107 {
9108 framerLaneXbar = device->rx->framer->serializerLaneCrossbar;
9109 }
9110 else
9111 {
9112 if (ML == 42)
9113 {
9114 /* uses framer outputs 0 and 2 instead of 0 and 1...fix framer lane XBar */
9115 /* only 2 lane cases here */
9116 switch ((device->rx->framer->serializerLanesEnabled & 0x0F))
9117 {
9118 case 3:
9119 framerLaneXbar = 0x08;
9120 break;
9121 case 5:
9122 framerLaneXbar = 0x20;
9123 break;
9124 case 6:
9125 framerLaneXbar = 0x20;
9126 break;
9127 case 9:
9128 framerLaneXbar = 0x80;
9129 break;
9130 case 10:
9131 framerLaneXbar = 0x80;
9132 break;
9133 case 12:
9134 framerLaneXbar = 0x80;
9135 break;
9136 default:
9137 /* default to valid setting for Lane 0 */
9138 framerLaneXbar = 0x08;
9139 break;
9140 }
9141 }
9142 else
9143 {
9144 switch ((device->rx->framer->serializerLanesEnabled & 0x0F))
9145 {
9146 /* all 4 lanes get framer 0 output */
9147 case 1:
9148 framerLaneXbar = 0x00;
9149 break;
9150 case 2:
9151 framerLaneXbar = 0x00;
9152 break;
9153 case 3:
9154 framerLaneXbar = 0x04;
9155 break;
9156 case 4:
9157 framerLaneXbar = 0x00;
9158 break;
9159 case 5:
9160 framerLaneXbar = 0x10;
9161 break;
9162 case 6:
9163 framerLaneXbar = 0x10;
9164 break;
9165 case 8:
9166 framerLaneXbar = 0x00;
9167 break;
9168 case 9:
9169 framerLaneXbar = 0x40;
9170 break;
9171 case 10:
9172 framerLaneXbar = 0x40;
9173 break;
9174 case 12:
9175 framerLaneXbar = 0x40;
9176 break;
9177 case 15:
9178 framerLaneXbar = 0xE4;
9179 break;
9180 default:
9181 /* default to valid setting for all Lanes */
9182 framerLaneXbar = 0xE4;
9183 break;
9184 }
9185 }
9186 }
9187
9188 /* Framer: Set Lane Crossbar */
9189 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LANE_XBAR_SEL, framerLaneXbar);
9190
9191 if (ML == 24)
9192 {
9193 /* Framer: Clear ADC Xbar channel auto switch */
9194 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x00);
9195 }
9196 else
9197 {
9198 /* Framer: Set ADC Xbar channel auto switch */
9199 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x04);
9200 }
9201
9202 /* enabling the SYSREF for relink if newSysrefOnRelink is set */
9203 if (device->rx->framer->newSysrefOnRelink)
9204 {
9205 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x01, 0x40, 6);
9206 }
9207
9208 /* enabling auto channel if the enableAutoChanXbar structure member is set */
9209 if (device->rx->framer->enableAutoChanXbar)
9210 {
9211 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x01, 0x04, 2);
9212 }
9213
9214 /* determining F octets per frame based on 2*M/L */
9215 framerConfigF = (uint8_t)(2 * (device->rx->framer->M / L));
9216
9217 /* Framer: Soft Reset */
9218 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x03);
9219
9220 /* Framer: Clear Soft Reset */
9221 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x00);
9222
9223 /* Framer: Set F (Octets in Frame) */
9224 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_F, framerConfigF);
9225
9226 /* Framer: Enable framer clock and lane clocks */
9227 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 0x03, 0x03, 0);
9228
9229 /* Set Framer lane FIFO enable for each lane enabled */
9230 fifoLaneEnable = (((device->rx->framer->serializerLanesEnabled & 0x0F) << 4) | 0x01);
9231
9232 /* Framer: Enable Lane FIFOs */
9233 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LANE_CTL, fifoLaneEnable);
9234
9235 /* Setup submap registers */
9236 SUBCLASSV = 1; /* JESD subclass 1 */
9237 JESDV = 1; /* Version: JESD204B */
9238 DID = device->rx->framer->deviceId;
9239 BID = device->rx->framer->bankId;
9240 LID0 = device->rx->framer->lane0Id;
9241 LID1 = device->rx->framer->lane0Id + 1;
9242 LID2 = device->rx->framer->lane0Id + 2;
9243 LID3 = device->rx->framer->lane0Id + 3;
9244
9245 CS = 0;
9246 N = 0x0F;
9247 Np = 0x0F;
9248 S = 0;
9249 CF = 0;
9250 HD = 0;
9251 K = device->rx->framer->K - 1;
9252 FramerL = L - 1;
9253 FramerM = device->rx->framer->M - 1;
9254 FramerF = (uint8_t)(2 * device->rx->framer->M / L) - 1;
9255
9256 if (ML == 11)
9257 {
9258 regE0 = 0x01;
9259 regE2 = 0x01;
9260 }
9261 else if (ML == 12)
9262 {
9263 regE0 = 0x01;
9264 regE2 = 0x03;
9265 HD = 0x01;
9266 }
9267 else if (ML == 21)
9268 {
9269 regE0 = 0x03;
9270 regE2 = 0x01;
9271 }
9272 else if (ML == 22)
9273 {
9274 regE0 = 0x03;
9275 regE2 = 0x03;
9276 }
9277 else if (ML == 24)
9278 {
9279 regE0 = 0x05;
9280 regE2 = 0x0F;
9281 HD = 0x01;
9282 }
9283 else if (ML == 41)
9284 {
9285 regE0 = 0x0F;
9286 regE2 = 0x01;
9287 }
9288 else if (ML == 42)
9289 {
9290 regE0 = 0x0F;
9291 regE2 = 0x05;
9292 }
9293 else if (ML == 44)
9294 {
9295 regE0 = 0x0F;
9296 regE2 = 0x0F;
9297 }
9298 else
9299 {
9300 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_M_PARM));
9301 return MYKONOS_ERR_FRAMER_INV_M_PARM;
9302 }
9303
9304 /* setting K offset for framer */
9305 if (device->rx->framer->lmfcOffset < device->rx->framer->K)
9306 {
9307 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LMFC_K_OFFSET, device->rx->framer->lmfcOffset);
9308 }
9309 else
9310 {
9311 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM,
9312 getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM));
9313 return MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM;
9314 }
9315
9316 subaddr[0] = 0x00;
9317 subdata[0] = (DID & 0xFF); /* Device ID */
9318 subaddr[1] = 0x01;
9319 subdata[1] = (BID & 0x0F); /* Bank ID */
9320 subaddr[2] = 0x02;
9321 subdata[2] = (LID0 & 0x1F); /* Lane 0 ID */
9322 subaddr[3] = 0x03;
9323 subdata[3] = (uint8_t)(device->rx->framer->scramble << 7) | (FramerL & 0x1F); /* [7] Scramble, #Lanes[4:0]-1 */
9324 subaddr[4] = 0x04;
9325 subdata[4] = (FramerF & 0xFF); /* F[7:0]-1 */
9326 subaddr[5] = 0x05;
9327 subdata[5] = (K & 0x1F); /* K[4:0]-1 */
9328 subaddr[6] = 0x06;
9329 subdata[6] = (FramerM & 0xFF); /* M[7:0]-1 */
9330 subaddr[7] = 0x07;
9331 subdata[7] = ((CS & 0x3) << 6) | (N & 0x1F); /* [7:6] = CS[1:0], N[4:0]-1 */
9332 subaddr[8] = 0x08;
9333 subdata[8] = ((SUBCLASSV & 7) << 5) | (Np & 0x1F); /* NP[4:0] -1 */
9334 subaddr[9] = 0x09;
9335 subdata[9] = ((JESDV & 7) << 5) | (S & 0x1F); /* S[4:0]-1 */
9336 subaddr[10] = 0x0A;
9337 subdata[10] = ((HD & 1) << 7) | (CF & 0x1F); /* [7] = HD, CF[4:0] */
9338 subaddr[11] = 0x0B;
9339 subdata[11] = 0x00; /* reserved */
9340 subaddr[12] = 0x0C;
9341 subdata[12] = 0x00; /* reserved */
9342
9343 CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID0 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF)
9344 + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7);
9345
9346 /* Checksum Lane 0 */
9347 subaddr[13] = 0x0D;
9348 subdata[13] = CheckSum & 0xFF;
9349
9350 /* in JESD204B ML=42 case, framer ip lanes 0 and 2 are used, write lane 1 id and checksum to ip lane 2 regs */
9351 if (ML == 42)
9352 {
9353 /* Lane 1 ID */
9354 subaddr[14] = 0x1A;
9355 subdata[14] = LID1;
9356
9357 CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID1 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF)
9358 + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7);
9359
9360 /* Checksum Lane 1 */
9361 subaddr[15] = 0x1D;
9362 subdata[15] = CheckSum & 0xFF;
9363 }
9364 else
9365 {
9366 /* Lane 1 ID */
9367 subaddr[14] = 0x12;
9368 subdata[14] = LID1;
9369
9370 CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID1 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF)
9371 + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7);
9372
9373 /* Checksum Lane 1 */
9374 subaddr[15] = 0x15;
9375 subdata[15] = CheckSum & 0xFF;
9376
9377 /* Lane 2 ID */
9378 subaddr[16] = 0x1A;
9379 subdata[16] = LID2;
9380
9381 CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID2 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF)
9382 + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7);
9383
9384 /* Checksum Lane 2 */
9385 subaddr[17] = 0x1D;
9386 subdata[17] = CheckSum & 0xFF;
9387
9388 /* Lane 3 ID */
9389 subaddr[18] = 0x22;
9390 subdata[18] = LID3;
9391
9392 CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID3 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF)
9393 + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7);
9394
9395 subaddr[19] = 0x25;
9396 subdata[19] = CheckSum & 0xFF;
9397 }
9398
9399 subaddr[20] = 0xE0;
9400 subdata[20] = regE0; /* Enable converter n logic */
9401 subaddr[21] = 0xE2;
9402 subdata[21] = regE2; /* Enable Lane n logic */
9403 subaddr[22] = 0xE4;
9404 subdata[22] = 0x00;
9405 subaddr[23] = 0xE6;
9406 subdata[23] = 0x00;
9407 subaddr[24] = 0xF0;
9408 subdata[24] = 0x00; /* #multiframes in ILAS */
9409 subaddr[25] = 0xF2;
9410 subdata[25] = 0x00;
9411 subaddr[26] = 0xF3;
9412 subdata[26] = 0x00;
9413 subaddr[27] = 0xF4;
9414 subdata[27] = 0x00;
9415 subaddr[28] = 0xC0;
9416 subdata[28] = 0x03; /* Framer enable, both sides perform lane sync */
9417
9418 for (i = 0; i <= 28; i++)
9419 {
9420 /* Set framer sub register map address */
9421 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_ADDR, subaddr[i]);
9422
9423 /* Set framer sub register map data word */
9424 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_DATA, subdata[i]);
9425
9426 /* Write enable */
9427 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_WRITE_EN, 0x01);
9428 }
9429
9430 if (device->rx->framer->externalSysref > 0)
9431 {
9432 /* Framer: Enable lane FIFO sync (Enable CGS) */
9433 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x30);
9434 }
9435 else
9436 {
9437 /* Framer: Enable lane FIFO sync (Enable CGS) */
9438 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x10);
9439 }
9440
9441 return MYKONOS_ERR_OK;
9442 }
9443
9444 /**
9445 * \brief Sets up the JESD204B OBSRX Framer
9446 *
9447 * <B>Dependencies</B>
9448 * - device->rxChannels
9449 * - device->spiSettings->chipSelectIndex
9450 * - device->obsRx->framer->bankId
9451 * - device->obsRx->framer->M
9452 * - device->obsRx->framer->serializerLanesEnabled
9453 * - device->obsRx->framer->externalSysref
9454 * - device->spiSettings
9455 * - device->obsRx->framer->deviceId
9456 * - device->obsRx->framer->lane0Id
9457 * - device->obsRx->framer->K
9458 * - device->obsRx->framer->lmfcOffset
9459 * - device->obsRx->framer->scramble
9460 * - device->obsRx->framer->obsRxSyncbSelect
9461 *
9462 * \param device Pointer to the device settings structure
9463 *
9464 * \retval MYKONOS_ERR_OK Function completed successfully
9465 * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM M parameter can only be 1 when real IF data mode is enabled
9466 * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM ObsRx Framer M parameter can only be 1 or 2
9467 * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM Invalid BankId (0-15)
9468 * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM Invalid lane0Id (0-31)
9469 * \retval MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM Invalid F*K value (F * K must be > 20 and divisible by 4)
9470 * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM Invalid K offset, must be less than K
9471 */
MYKONOS_setupJesd204bObsRxFramer(mykonosDevice_t * device)9472 mykonosErr_t MYKONOS_setupJesd204bObsRxFramer(mykonosDevice_t *device)
9473 {
9474 uint8_t i = 0;
9475 uint8_t laneFifoEnable = 0;
9476 uint8_t L = 1;
9477 uint8_t ML = 2;
9478 uint8_t framerConfigF = 0;
9479
9480 uint8_t subaddr[29] = {0}; /* holds address to framer sub register map */
9481 uint8_t subdata[29] = {0}; /* holds data for framer sub register map */
9482
9483 /* Setup submap registers */
9484 uint8_t SUBCLASSV = 1; /* JESD subclass 1 */
9485 uint8_t JESDV = 1; /* Version: JESD204B */
9486 uint8_t DID = 0;
9487 uint8_t BID = 0;
9488 uint8_t LID0 = 0;
9489 uint8_t LID1 = 1;
9490 uint8_t LID2 = 2;
9491 uint8_t LID3 = 3;
9492 uint8_t CS = 0;
9493 uint8_t N = 0x0F;
9494 uint8_t Np = 0x0F;
9495 uint8_t S = 0;
9496 uint8_t CF = 0;
9497 uint8_t K = 31;
9498 uint8_t HD = 0;
9499 uint8_t FramerL = 1;
9500 uint8_t FramerM = 2;
9501 uint8_t FramerF = 1;
9502 uint8_t framerADC_XBar = 0xE4;
9503 uint8_t regE0 = 0;
9504 uint8_t regE2 = 0;
9505 uint8_t framerLaneXbar = 0xE4;
9506 uint16_t CheckSum = 0;
9507 uint16_t FK = 0;
9508
9509 #if (MYKONOS_VERBOSE == 1)
9510 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupJesd204bObsRxFramer()\n");
9511 #endif
9512
9513 if (device->obsRx->framer->M == 1 && !(device->obsRx->realIfData))
9514 {
9515 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM,
9516 getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM));
9517 return MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM;
9518 }
9519
9520 if (device->obsRx->framer->M != 1 && device->obsRx->framer->M != 2)
9521 {
9522 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM,
9523 getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM));
9524 return MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM;
9525 }
9526
9527 if (device->obsRx->framer->bankId > 15)
9528 {
9529 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM,
9530 getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM));
9531 return MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM;
9532 }
9533
9534 /* no need to check deviceId, its range is full uint8_t range */
9535 if (device->obsRx->framer->lane0Id > 31)
9536 {
9537 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM,
9538 getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM));
9539 return MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM;
9540 }
9541
9542 //count number of lanes
9543 L = 0;
9544 ML = 0;
9545
9546 for (i = 0; i < 4; i++)
9547 {
9548 L += ((device->obsRx->framer->serializerLanesEnabled >> i) & 0x01);
9549 }
9550
9551 ML = (uint8_t)(device->obsRx->framer->M * 10 + L);
9552
9553 if (L == 0)
9554 {
9555 /* Disable framer and return successfully */
9556 /* Disable framer clock and lane clocks */
9557 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0, 0x03, 0);
9558
9559 /* Disable lane FIFO enables */
9560 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_CTL, 0, 0xF0, 4);
9561 return MYKONOS_ERR_OK;
9562 }
9563
9564 FK = (uint16_t)(device->obsRx->framer->K * 2 * device->obsRx->framer->M / L);
9565 if (FK < 20 || FK > 256 || FK % 4 != 0)
9566 {
9567 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM,
9568 getMykonosErrorMessage(MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM));
9569 return MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM;
9570 }
9571
9572 if (device->obsRx->framer->externalSysref == 0)
9573 {
9574 /* Framer: Generate SYSREF internally */
9575 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_TEST_CNTR_CTL, 0x20);
9576 }
9577
9578 /* Framer: Set ADC Crossbar */
9579 framerADC_XBar = 0xB1;
9580 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_ADC_XBAR_SEL, framerADC_XBar);
9581
9582 if (device->obsRx->framer->enableManualLaneXbar == 1)
9583 {
9584 framerLaneXbar = device->obsRx->framer->serializerLaneCrossbar;
9585 }
9586 else
9587 {
9588 if (ML == 42)
9589 {
9590 /* uses framer outputs 0 and 2 instead of 0 and 1...fix framer lane XBar */
9591 /* only 2 lane cases here */
9592 switch ((device->obsRx->framer->serializerLanesEnabled & 0x0F))
9593 {
9594 case 3:
9595 framerLaneXbar = 0x08;
9596 break;
9597 case 5:
9598 framerLaneXbar = 0x20;
9599 break;
9600 case 6:
9601 framerLaneXbar = 0x20;
9602 break;
9603 case 9:
9604 framerLaneXbar = 0x80;
9605 break;
9606 case 10:
9607 framerLaneXbar = 0x80;
9608 break;
9609 case 12:
9610 framerLaneXbar = 0x80;
9611 break;
9612 default:
9613 /* default to valid setting for Lane 0 */
9614 framerLaneXbar = 0x08;
9615 break;
9616 }
9617 }
9618 else
9619 {
9620 switch ((device->obsRx->framer->serializerLanesEnabled & 0x0F))
9621 {
9622 /* all 4 lanes get framer 0 output */
9623 case 1:
9624 framerLaneXbar = 0x00;
9625 break;
9626 case 2:
9627 framerLaneXbar = 0x00;
9628 break;
9629 case 3:
9630 framerLaneXbar = 0x04;
9631 break;
9632 case 4:
9633 framerLaneXbar = 0x00;
9634 break;
9635 case 5:
9636 framerLaneXbar = 0x10;
9637 break;
9638 case 6:
9639 framerLaneXbar = 0x10;
9640 break;
9641 case 8:
9642 framerLaneXbar = 0x00;
9643 break;
9644 case 9:
9645 framerLaneXbar = 0x40;
9646 break;
9647 case 10:
9648 framerLaneXbar = 0x40;
9649 break;
9650 case 12:
9651 framerLaneXbar = 0x40;
9652 break;
9653 case 15:
9654 framerLaneXbar = 0xE4;
9655 break;
9656 default:
9657 /* default to valid setting for all Lanes */
9658 framerLaneXbar = 0xE4;
9659 break;
9660 }
9661 }
9662 }
9663
9664 /* Framer: set Lane Crossbar */
9665 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_XBAR_SEL, framerLaneXbar);
9666
9667 /* Framer: determine the framerConfigF value (2*M/L) */
9668 framerConfigF = (uint8_t)(2 * (device->obsRx->framer->M/L));
9669
9670 /* Framer: Soft Reset */
9671 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x03);
9672
9673 /* Framer: Clear Soft Reset */
9674 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x00);
9675
9676 /* Framer: Set F (Octets in Frame) */
9677 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CONFIG_F, framerConfigF);
9678
9679 /* Framer: Enable framer clock and lane clocks */
9680 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0x03, 0x03, 0);
9681
9682 /* Set Framer lane FIFO enable for each lane enabled */
9683 laneFifoEnable = (uint8_t)(((device->obsRx->framer->serializerLanesEnabled & 0x0F) << 4) | 0x01);
9684
9685 /* Framer: Enable Lane FIFOs */
9686 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_CTL, laneFifoEnable);
9687
9688 /* enabling the SYSREF for relink if newSysrefOnRelink is set */
9689 if (device->obsRx->framer->newSysrefOnRelink)
9690 {
9691 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x01, 0x40, 6);
9692 }
9693
9694 /* enabling auto channel if the enableAutoChanXbar structure member is set */
9695 if (device->obsRx->framer->enableAutoChanXbar)
9696 {
9697 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x01, 0x04, 2);
9698 }
9699
9700 /* Setup submap registers */
9701 SUBCLASSV = 1; /* JESD subclass 1 */
9702 JESDV = 1; /* Version: JESD204B */
9703 DID = device->obsRx->framer->deviceId;
9704 BID = device->obsRx->framer->bankId;
9705 LID0 = device->obsRx->framer->lane0Id;
9706 LID1 = device->obsRx->framer->lane0Id + 1;
9707 LID2 = device->obsRx->framer->lane0Id + 2;
9708 LID3 = device->obsRx->framer->lane0Id + 3;
9709
9710 CS = 0;
9711 N = 0x0F;
9712 Np = 0x0F;
9713 S = 0;
9714 CF = 0;
9715 K = device->obsRx->framer->K - 1;
9716 HD = 0;
9717 FramerL = L - 1;
9718 FramerM = device->obsRx->framer->M - 1;
9719 FramerF = (uint8_t)((2*device->obsRx->framer->M/L) - 1);
9720
9721 if (ML == 11)
9722 {
9723 regE0 = 0x1;
9724 regE2 = 0x1;
9725 }
9726 else if (ML == 12)
9727 {
9728 regE0 = 0x1;
9729 regE2 = 0x3;
9730 HD = 1;
9731 }
9732 else if (ML == 21)
9733 {
9734 regE0 = 0x3;
9735 regE2 = 0x1;
9736 }
9737 else if (ML == 22)
9738 {
9739 regE0 = 0x3;
9740 regE2 = 0x3;
9741 }
9742 else
9743 {
9744 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM,
9745 getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM));
9746 return MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM;
9747 }
9748
9749 /* setting K offset for framer */
9750 if (device->obsRx->framer->lmfcOffset < device->rx->framer->K)
9751 {
9752 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LMFC_K_OFFSET, device->obsRx->framer->lmfcOffset);
9753 }
9754 else
9755 {
9756 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM,
9757 getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM));
9758 return MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM;
9759 }
9760
9761 subaddr[0] = 0x00;
9762 subdata[0] = (DID & 0xFF); /* Device ID */
9763 subaddr[1] = 0x01;
9764 subdata[1] = (BID & 0x0F); /* Bank ID */
9765 subaddr[2] = 0x02;
9766 subdata[2] = (LID0 & 0x1F); /* Lane 0 ID */
9767 subaddr[3] = 0x03;
9768 subdata[3] = (uint8_t)(device->obsRx->framer->scramble << 7) | (FramerL & 0x1F); /* [7] Scramble, #Lanes[4:0]-1 */
9769 subaddr[4] = 0x04;
9770 subdata[4] = (FramerF & 0xFF); /* F[7:0]-1 */
9771 subaddr[5] = 0x05;
9772 subdata[5] = (K & 0x1F); /* K[4:0]-1 */
9773 subaddr[6] = 0x06;
9774 subdata[6] = (FramerM & 0xFF); /* M[7:0]-1 */
9775 subaddr[7] = 0x07;
9776 subdata[7] = ((CS & 0x3) << 6) | (N & 0x1F); /* [7:6] = CS[1:0], N[4:0]-1 */
9777 subaddr[8] = 0x08;
9778 subdata[8] = ((SUBCLASSV & 7) << 5) | (Np & 0x1F); /* NP[4:0] -1 */
9779 subaddr[9] = 0x09;
9780 subdata[9] = ((JESDV & 7) << 5) | (S & 0x1F); /* S[4:0]-1 */
9781 subaddr[10] = 0x0a;
9782 subdata[10] = ((HD & 1) << 7) | (CF & 0x1F); /* [7] = HD, CF[4:0] */
9783 subaddr[11] = 0x0b;
9784 subdata[11] = 0x00; /* reserved */
9785 subaddr[12] = 0x0c;
9786 subdata[12] = 0x00; /* reserved */
9787
9788 CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID0 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF)
9789 + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7);
9790
9791 /* Checksum Lane 0 */
9792 subaddr[13] = 0x0d;
9793 subdata[13] = CheckSum & 0xFF;
9794
9795 /* Lane 1 ID */
9796 subaddr[14] = 0x12;
9797 subdata[14] = LID1;
9798
9799 CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID1 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF)
9800 + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7);
9801
9802 /* Checksum Lane 1 */
9803 subaddr[15] = 0x15;
9804 subdata[15] = CheckSum & 0xFF;
9805
9806 /* Lane 2 ID */
9807 subaddr[16] = 0x1a;
9808 subdata[16] = LID2;
9809
9810 CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID2 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF)
9811 + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7);
9812
9813 /* Checksum Lane 2 */
9814 subaddr[17] = 0x1d;
9815 subdata[17] = CheckSum & 0xFF;
9816
9817 /* Lane 3 ID */
9818 subaddr[18] = 0x22;
9819 subdata[18] = LID3;
9820
9821 CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID3 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF)
9822 + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7);
9823
9824 subaddr[19] = 0x25;
9825 subdata[19] = CheckSum & 0xFF;
9826
9827 subaddr[20] = 0xe0;
9828 subdata[20] = regE0; /* Enable converter n logic */
9829 subaddr[21] = 0xe2;
9830 subdata[21] = regE2; /* Enable Lane n logic */
9831 subaddr[22] = 0xe4;
9832 subdata[22] = 0x00;
9833 subaddr[23] = 0xe6;
9834 subdata[23] = 0x00;
9835 subaddr[24] = 0xf0;
9836 subdata[24] = 0x00; /* #multiframes in ILAS */
9837 subaddr[25] = 0xf2;
9838 subdata[25] = 0x00;
9839 subaddr[26] = 0xf3;
9840 subdata[26] = 0x00;
9841 subaddr[27] = 0xf4;
9842 subdata[27] = 0x00;
9843 subaddr[28] = 0xc0;
9844 subdata[28] = 0x03; /* Framer enable, both sides perform lane sync */
9845
9846 for (i = 0; i <= 28; i++)
9847 {
9848 /* Set framer sub register map address */
9849 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_ADDR, subaddr[i]);
9850
9851 /* Set framer sub register map data word */
9852 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_DATA, subdata[i]);
9853
9854 /* Write enable */
9855 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_WRITE_EN, 0x01);
9856 }
9857
9858 if (device->obsRx->framer->externalSysref > 0)
9859 {
9860 /* Framer: Enable lane FIFO sync (Enable CGS) */
9861 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x30);
9862 }
9863 else
9864 {
9865 /* Framer: Enable lane FIFO sync (Enable CGS) */
9866 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x10);
9867 }
9868
9869 return MYKONOS_ERR_OK;
9870 }
9871
9872 /**
9873 * \brief Enables/Disables the JESD204B Rx Framer
9874 *
9875 * This function is normally not necessary. In the event that the link needs to be reset, this
9876 * function allows the Rx framer to be disabled and re-enabled.
9877 *
9878 * <B>Dependencies</B>
9879 * - device->spiSettings
9880 * - device->rx->framer->serializerLanesEnabled
9881 *
9882 * \param device is a pointer to the device settings structure
9883 * \param enable 0 = Disable the selected framer, 1 = enable the selected framer link
9884 *
9885 * \retval MYKONOS_ERR_OK Function completed successfully
9886 * \retval MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM Invalid serializerLanesEnabled parameter in device data structure
9887 */
MYKONOS_enableRxFramerLink(mykonosDevice_t * device,uint8_t enable)9888 mykonosErr_t MYKONOS_enableRxFramerLink(mykonosDevice_t *device, uint8_t enable)
9889 {
9890 uint8_t enableLink = 0;
9891
9892 #if (MYKONOS_VERBOSE == 1)
9893 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableFramerLink()\n");
9894 #endif
9895
9896 enableLink = (enable > 0) ? 1 : 0;
9897
9898 if (enableLink)
9899 {
9900 /* Power Up serializer lanes */
9901 if (device->rx->framer->serializerLanesEnabled > 15)
9902 {
9903 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM,
9904 getMykonosErrorMessage(MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM));
9905 return MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM;
9906 }
9907
9908 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, ((~device->rx->framer->serializerLanesEnabled) & 0x0F),
9909 device->rx->framer->serializerLanesEnabled, 0);
9910
9911 /* Enable Clocks to Framer */
9912 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 3, 0x03, 0);
9913
9914 /* Release reset to framer and lane FIFOs */
9915 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x00);
9916 }
9917 else
9918 {
9919 /* Disable Link */
9920 /* Hold Rx framer in reset */
9921 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x03);
9922
9923 /* Disable Clocks to Framer */
9924 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 0, 0x03, 0);
9925
9926 /* Power down serializer lanes */
9927 if (device->rx->framer->serializerLanesEnabled > 15)
9928 {
9929 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM,
9930 getMykonosErrorMessage(MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM));
9931 return MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM;
9932 }
9933
9934 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, device->rx->framer->serializerLanesEnabled, device->rx->framer->serializerLanesEnabled, 0);
9935 }
9936
9937 return MYKONOS_ERR_OK;
9938 }
9939
9940 /**
9941 * \brief Enables/Disables the JESD204B ObsRx Framer
9942 *
9943 * This function is normally not necessary. In the event that the link needs to be reset, this
9944 * function allows the ObsRx framer to be disabled and re-enabled.
9945 *
9946 * <B>Dependencies</B>
9947 * - device->spiSettings
9948 * - device->obsRx->framer->serializerLanesEnabled
9949 *
9950 * \param device is a pointer to the device settings structure
9951 * \param enable 0 = Disable the selected framer, 1 = enable the selected framer link
9952 *
9953 * \retval MYKONOS_ERR_OK Function completed successfully
9954 * \retval MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM Invalid serializerLanesEnabled parameter in device data structure (Valid 0-15)
9955 */
MYKONOS_enableObsRxFramerLink(mykonosDevice_t * device,uint8_t enable)9956 mykonosErr_t MYKONOS_enableObsRxFramerLink(mykonosDevice_t *device, uint8_t enable)
9957 {
9958 uint8_t enableLink = 0;
9959
9960 #if (MYKONOS_VERBOSE == 1)
9961 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableObsRxFramerLink()\n");
9962 #endif
9963
9964 enableLink = (enable > 0) ? 1 : 0;
9965
9966 if (enableLink)
9967 {
9968 /* Power Up serializer lanes */
9969 if (device->rx->framer->serializerLanesEnabled > 15)
9970 {
9971 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM,
9972 getMykonosErrorMessage(MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM));
9973 return MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM;
9974 }
9975
9976 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, ((~device->obsRx->framer->serializerLanesEnabled) & 0x0F),
9977 device->obsRx->framer->serializerLanesEnabled, 0);
9978
9979 /* Enable Clocks to Framer */
9980 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 3, 0x03, 0);
9981
9982 /* Release reset to framer and lane FIFOs */
9983 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x00);
9984 }
9985 else
9986 {
9987 /* Disable Link */
9988 /* Hold Rx framer in reset */
9989 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x03);
9990
9991 /* Disable Clocks to Framer */
9992 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0, 0x03, 0);
9993
9994 /* Power down serializer lanes */
9995 if (device->obsRx->framer->serializerLanesEnabled > 15)
9996 {
9997 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM,
9998 getMykonosErrorMessage(MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM));
9999 return MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM;
10000 }
10001
10002 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, device->obsRx->framer->serializerLanesEnabled,
10003 device->obsRx->framer->serializerLanesEnabled, 0);
10004 }
10005
10006 return MYKONOS_ERR_OK;
10007 }
10008
10009 /**
10010 * \brief Sets up the JESD204B Deframer
10011 *
10012 * <B>Dependencies</B>
10013 * - device->spiSettings->chipSelectIndex
10014 * - device->tx->deframer->M
10015 * - device->tx->deframer->bankId
10016 * - device->tx->deframer->lane0Id
10017 * - device->tx->deframer->K
10018 * - device->tx->deframer->deserializerLanesEnabled
10019 * - device->tx->deframer->externalSysref
10020 * - device->tx->deframer->newSysrefOnRelink
10021 * - device->tx->deframer->enableAutoChanXbar
10022 * - device->tx->deframer->lmfcOffset
10023 * - device->tx->deframer->scramble
10024 *
10025 * \param device Pointer to device settings structure
10026 *
10027 * \retval MYKONOS_ERR_OK Function completed successfully
10028 * \retval MYKONOS_ERR_DEFRAMER_INV_M_PARM Invalid M parameter in deframer structure
10029 * \retval MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM Invalid BankId parameter in deframer structure (Valid 0-15)
10030 * \retval MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM Invalid Lane0Id parameter in deframer structure (Valid 0-31)
10031 * \retval MYKONOS_ERR_DEFRAMER_INV_K_PARAM Invalid K parameter in deframer structure (valid 1-32 with other constraints)
10032 * \retval MYKONOS_ERR_DEFRAMER_INV_FK_PARAM Invalid F*K parameter (Valid F*K > 20, F*K must be divisible by 4), K must be <= 32
10033 * \retval MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM Invalid K offset parameter in deframer structure (must be less than K)
10034 */
MYKONOS_setupJesd204bDeframer(mykonosDevice_t * device)10035 mykonosErr_t MYKONOS_setupJesd204bDeframer(mykonosDevice_t *device)
10036 {
10037 uint8_t i = 0;
10038 uint8_t temp = 0;
10039 uint8_t reg080 = 0;
10040 uint8_t laneXbar = 0;
10041 uint8_t L = 0;
10042 uint8_t ML = 0;
10043
10044 /* Setup submap registers */
10045 uint8_t SUBCLASSV = 1;
10046 uint8_t JESDV = 1;
10047 uint8_t DID = 0;
10048 uint8_t BID = 0;
10049 uint8_t LID0 = 0;
10050 uint8_t CS = 2; /* 2 control bits */
10051 uint8_t N = 0x0D; /* 14 bits */
10052 uint8_t Np = 0x0F; /* 16 bits */
10053 uint8_t S = 0;
10054 uint8_t CF = 0;
10055 uint8_t K = 0x1F;
10056 uint16_t FK = 0;
10057 uint8_t HD = 0; /* only one case has HD == 1 */
10058 uint8_t CTRLREG0 = 0;
10059 uint8_t DeframerL = 1;
10060 uint8_t DeframerM = 2;
10061 uint8_t DeframerF = 0;
10062 uint8_t CTRLREG1 = 0;
10063 uint8_t CTRLREG2 = 0;
10064 uint8_t DeframerLaneEnable = 0x00;
10065 uint16_t CheckSum = 0;
10066 uint8_t subaddr[25] = {0};
10067 uint8_t subdata[25] = {0};
10068
10069 uint8_t deframerInput = 0;
10070 uint8_t lane = 0;
10071
10072 #if (MYKONOS_VERBOSE == 1)
10073 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupJesd204bDeframer()\n");
10074 #endif
10075
10076 if (device->tx->deframer->M != 0 && device->tx->deframer->M != 2 && device->tx->deframer->M != 4)
10077 {
10078 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_M_PARM));
10079 return MYKONOS_ERR_DEFRAMER_INV_M_PARM;
10080 }
10081
10082 if (device->tx->deframer->bankId > 15)
10083 {
10084 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM,
10085 getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM));
10086 return MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM;
10087 }
10088
10089 if (device->tx->deframer->lane0Id > 31)
10090 {
10091 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM,
10092 getMykonosErrorMessage(MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM));
10093 return MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM;
10094 }
10095
10096 //count number of lanes
10097 L = 0;
10098 ML = 0;
10099
10100 for (i = 0; i < 4; i++)
10101 {
10102 L += ((device->tx->deframer->deserializerLanesEnabled >> i) & 0x01);
10103 }
10104
10105 ML = (uint8_t)(device->tx->deframer->M * 10 + L);
10106
10107 if (device->tx->deframer->K > 32)
10108 {
10109 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_K_PARAM,
10110 getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_K_PARAM));
10111 return MYKONOS_ERR_DEFRAMER_INV_K_PARAM;
10112 }
10113
10114 FK = (uint16_t)(device->tx->deframer->K * 2 * device->tx->deframer->M / L);
10115
10116 if (FK < 20 || FK > 256 || FK % 4 != 0)
10117 {
10118 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_FK_PARAM,
10119 getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_FK_PARAM));
10120 return MYKONOS_ERR_DEFRAMER_INV_FK_PARAM;
10121 }
10122
10123 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYNC_REQ_RETIME, (device->tx->deframer->K - 1), 0x1F, 0x00);
10124
10125 if (!device->tx->deframer->externalSysref)
10126 {
10127 /* Deframer: Generate SYSREF internally */
10128 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_TEST, 0x02);
10129 }
10130
10131 /* enabling the SYSREF for relink if newSysrefOnRelink is set */
10132 if (device->tx->deframer->newSysrefOnRelink)
10133 {
10134 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x01, 0x40, 6);
10135 }
10136
10137 /* enabling auto channel if the enableAutoChanXbar structure member is set */
10138 if (device->tx->deframer->enableAutoChanXbar)
10139 {
10140 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_STRT_DAC_XBAR_REV, 0x01, 0x04, 2);
10141 }
10142
10143 /* Fix bad default bit to allow deterministic latency on deframer (Clear bit 4)*/
10144 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_STRT_DAC_XBAR_REV, 0x00, 0x10, 4);
10145
10146 /* Deframer: Set DAC Crossbar */
10147 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DAC_XBAR_SEL, 0xB1);
10148
10149 if (device->tx->deframer->enableManualLaneXbar == 1)
10150 {
10151 laneXbar = device->tx->deframer->deserializerLaneCrossbar;
10152 }
10153 else
10154 {
10155 /* Lane crossbar - Allow user to reorder lanes in deframer->deserializerLaneCrossbar, but this code still */
10156 /* maps used lanes to deframer inputs */
10157 deframerInput = 0;
10158 for (lane = 0; lane < 4; lane++)
10159 {
10160 if ((device->tx->deframer->deserializerLanesEnabled >> lane) & 1)
10161 {
10162 laneXbar |= (uint8_t)(((device->tx->deframer->deserializerLaneCrossbar >> (lane << 1)) & 3) << (deframerInput << 1));
10163 deframerInput += 1;
10164 }
10165 }
10166
10167 if (ML == 42)
10168 {
10169 /* M4L2 uses internal deframer ports 0 and 2 */
10170 /* swap bits 3:2 and 5:4, keep 1:0 and 7:6 in place */
10171 laneXbar = (laneXbar & 0xC3U) | ((laneXbar & 0x30) >> 2) | ((laneXbar & 0x0C) << 2);
10172 }
10173 }
10174
10175 /* Deframer: Set Lane Crossbar */
10176 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LANE_XBAR_SEL, laneXbar);
10177
10178 //Find value for Framer F depending on M and L
10179 switch (ML)
10180 {
10181 case 21:
10182 reg080 = 0x04;
10183 break;
10184 case 22:
10185 reg080 = 0x22;
10186 break;
10187 case 24:
10188 reg080 = 0x41;
10189 break;
10190 case 41:
10191 reg080 = 0x18;
10192 break;
10193 case 42:
10194 reg080 = 0x34;
10195 break;
10196 case 44:
10197 reg080 = 0x52;
10198 break;
10199 default:
10200 reg080 = 0x04;
10201 break;
10202 }
10203
10204 /* Deframer: Set F (Octets in Frame) */
10205 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_CONFIG_F, reg080);
10206
10207 /* Deframer: Enable clocks and lane clocks */
10208 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_CLK_EN, 0x03);
10209
10210 /* Set deframer lane FIFO enable for each lane enabled */
10211 temp = (device->tx->deframer->deserializerLanesEnabled & 0x0F);
10212
10213 /* Deframer: Enable Lane FIFOs */
10214 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LANE_FIFO_CTL, temp);
10215
10216 /* Setup submap registers */
10217 SUBCLASSV = 1; /* JESD subclass 1 */
10218 JESDV = 1; /* Version: JESD204B */
10219 DID = device->tx->deframer->deviceId;
10220 BID = device->tx->deframer->bankId;
10221 LID0 = device->tx->deframer->lane0Id;
10222 CS = 2; /* 2 control bits */
10223 N = 0x0D; /* 14 bits */
10224 Np = 0x0F;
10225 S = 0;
10226 CF = 0;
10227 K = device->tx->deframer->K - 1;
10228 HD = 0; /* only one case has HD = 1 */
10229 CTRLREG0 = 1;
10230 DeframerL = L - 1;
10231 DeframerM = device->tx->deframer->M - 1;
10232 DeframerF = (uint8_t)((2*device->tx->deframer->M/L) - 1);
10233 CheckSum = 0;
10234
10235 if (ML == 21)
10236 {
10237 CTRLREG1 = 4;
10238 CTRLREG2 = 0x14;
10239 DeframerLaneEnable = 1;
10240 }
10241 else if (ML == 22)
10242 {
10243 CTRLREG1 = 2;
10244 CTRLREG2 = 4;
10245 DeframerLaneEnable = 3;
10246 }
10247 else if (ML == 24)
10248 {
10249 HD = 1;
10250 CTRLREG1 = 1;
10251 CTRLREG2 = 0;
10252 DeframerLaneEnable = 0x0F;
10253 }
10254 else if (ML == 41)
10255 {
10256 CTRLREG1 = 8;
10257 CTRLREG2 = 0;
10258 DeframerLaneEnable = 1;
10259 }
10260 else if (ML == 42)
10261 {
10262 CTRLREG1 = 4;
10263 CTRLREG2 = 0;
10264 DeframerLaneEnable = 5;
10265 }
10266 else if (ML == 44)
10267 {
10268 CTRLREG1 = 2;
10269 CTRLREG2 = 0;
10270 DeframerLaneEnable = 0x0F;
10271 }
10272 else
10273 {
10274 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_M_PARM));
10275 return MYKONOS_ERR_DEFRAMER_INV_M_PARM;
10276 }
10277
10278 /* LMFC offset limit check */
10279 if (device->tx->deframer->lmfcOffset < device->tx->deframer->K)
10280 {
10281 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LMFC_K_OFFSET, device->tx->deframer->lmfcOffset);
10282 }
10283 else
10284 {
10285 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM,
10286 getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM));
10287 return MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM;
10288 }
10289
10290 subaddr[0] = 0x50;
10291 subdata[0] = DID & 0xFFU; /* Device ID */
10292 subaddr[1] = 0x51;
10293 subdata[1] = BID & 0x0F; /* Bank ID */
10294 subaddr[2] = 0x52;
10295 subdata[2] = LID0 & 0x1F; /* Lane 0 ID */
10296 subaddr[3] = 0x53;
10297 subdata[3] = (uint8_t)(device->tx->deframer->scramble << 7) | (DeframerL & 0x1F); /* [7] = Scramble Enable, #Lanes[4:0] */
10298 subaddr[4] = 0x54;
10299 subdata[4] = DeframerF & 0xFFU; /* F[7:0] */
10300 subaddr[5] = 0x55;
10301 subdata[5] = K & 0x1F; /* K[4:0] */
10302 subaddr[6] = 0x56;
10303 subdata[6] = DeframerM & 0xFFU; /* M[7:0] */
10304 subaddr[7] = 0x57;
10305 subdata[7] = ((CS & 0x3) << 6) | (N & 0x1F); /* [7:6] = CS[1:0], N[4:0] */
10306 subaddr[8] = 0x58;
10307 subdata[8] = ((SUBCLASSV & 7) << 5) | (Np & 0x1F); /* Np[4:0] */
10308 subaddr[9] = 0x59;
10309 subdata[9] = ((JESDV & 7) << 5) | (S & 0x1F); /* S[4:0] */
10310 subaddr[10] = 0x5A;
10311 subdata[10] = ((HD & 1) << 7) | (CF & 0x1F); /* [7]=HD, CF[4:0] */
10312 subaddr[11] = 0x5B;
10313 subdata[11] = 0x00; /* reserved */
10314 subaddr[12] = 0x5C;
10315 subdata[12] = 0x00; /* reserved */
10316 CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID0 & 0x1F) + (device->tx->deframer->scramble) + (DeframerL & 0x1F) + (DeframerF & 0xFF) + (K & 0x1F) + (DeframerM & 0xFF)
10317 + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7);
10318 subaddr[13] = 0x5D;
10319 subdata[13] = CheckSum & 0xFFU; /* Checksum Lane 0 */
10320 subaddr[14] = 0x6D;
10321 subdata[14] = 0xA0U; /* Bad Disparity setup */
10322 subaddr[15] = 0x6E;
10323 subdata[15] = 0xA0U; /* Not in Table setup */
10324 subaddr[16] = 0x6F;
10325 subdata[16] = 0xA0U; /* UnExpected K character setup */
10326 subaddr[17] = 0x75;
10327 subdata[17] = CTRLREG0; /* CTRLREG 0 */
10328 subaddr[18] = 0x76;
10329 subdata[18] = CTRLREG1; /* CTRLREG 1 (Bytes per frame) */
10330 subaddr[19] = 0x77;
10331 subdata[19] = CTRLREG2; /* CTRLREG 2 */
10332 subaddr[20] = 0x78;
10333 subdata[20] = 0x01; /* # 4*K multiframes during ILAS */
10334 subaddr[21] = 0x7A;
10335 subdata[21] = 0xE0U; /* Setup JESD interrupt sources */
10336 subaddr[22] = 0x7B;
10337 subdata[22] = 0x08U; /* Sync assertion setup */
10338 subaddr[23] = 0x7C;
10339 subdata[23] = 0xFFU; /* Error count threshold */
10340 subaddr[24] = 0x7D;
10341 subdata[24] = DeframerLaneEnable & 0xFFU; /* Lane enable */
10342
10343 for (i = 0; i <= 24; i++)
10344 {
10345 /* Set deframer sub-register map address */
10346 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_ADDR, subaddr[i]);
10347
10348 /* Set deframer sub-register map data word */
10349 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DATA, subdata[i]);
10350
10351 /* Set write enable to latch data into deframer sub register map */
10352 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_WR_EN, 0x01);
10353 }
10354
10355 /* Deframer: Enable lane FIFO sync */
10356 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x01, 0x10, 4);
10357
10358 return MYKONOS_ERR_OK;
10359 }
10360
10361 /**
10362 * \brief Sets up the chip for multichip sync, and cleans up after MCS.
10363 *
10364 * When working with multiple transceivers or even only one transceiver that requires deterministic
10365 * latency between the Tx and observation and or main Rx JESD204B data path, Multichip sync is
10366 * necessary. This function should be run after all transceivers are initialized.
10367 *
10368 * After the SYSREF pulses have been sent, call the MYKONOS_enableMultichipSync() function again with the
10369 * enableMcs parameter set to 0. When enableMcs = 0, the MCS status will be returned in the mcsStatus
10370 * parameter.
10371 *
10372 * Typical sequence:
10373 * 1) Initialize all Mykonos devices in system using MYKONOS_initialize()
10374 * 2) Run MYKONOS_enableMultichipSync with enableMcs = 1
10375 * 3) Send at least 3 SYSREF pulses
10376 * 4) Run MYKONOS_enableMultichipSync with enableMcs = 0
10377 * 5) Load ARM, run ARM cals and continue to active Transmit/Receive
10378 *
10379 * mcsStatus | bit Description
10380 * -----------|--------------------------------------------------------
10381 * [0] | MCS JESD SYSREF Status (1 = sync occurred)
10382 * [1] | MCS Digital Clocks Sync Status (1 = sync occurred)
10383 * [2] | MCS CLKPLL SDM Sync Status (1 = sync occurred)
10384 * [3] | MCS Device Clock divider Sync Status (1 = sync occurred)
10385 *
10386 * <B>Dependencies</B>
10387 * - device->spiSettings
10388 *
10389 * \param device is a pointer to the device settings structure
10390 * \param enableMcs =1 will enable the MCS state machine, =0 will allow reading back MCS status
10391 * \param mcsStatus optional parameter, if pointer is not null the function Which will be populated with the mcsStatus word described in the table above.
10392 *
10393 * \retval MYKONOS_ERR_OK Function completed successfully
10394 */
MYKONOS_enableMultichipSync(mykonosDevice_t * device,uint8_t enableMcs,uint8_t * mcsStatus)10395 mykonosErr_t MYKONOS_enableMultichipSync(mykonosDevice_t *device, uint8_t enableMcs, uint8_t *mcsStatus)
10396 {
10397 uint8_t clkPllSdmBypass = 0;
10398 uint8_t mcsEnable = 0x9B; /* [7] Keeps RF LO divider enabled, Enable MCS[4] and reset Device Clock divider[3], Digital clocks[1], and JESD204 SYSREF[0] */
10399
10400 #if (MYKONOS_VERBOSE == 1)
10401 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableMultichipSync()\n");
10402 #endif
10403
10404 if (enableMcs)
10405 {
10406 /* If CLKPLL SDM not bypassed, reset CLKPLL SDM as well. */
10407 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1, &clkPllSdmBypass, 0x40, 6);
10408
10409 if (clkPllSdmBypass == 0)
10410 {
10411 mcsEnable |= 0x04; /* enable MCS for CLKPLL SDM */
10412 }
10413
10414 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_MCS_CONTROL, mcsEnable);
10415 }
10416
10417 /* if mcsStatus is a valid pointer, return the MCS status */
10418 if (mcsStatus != NULL)
10419 {
10420 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_MCS_STATUS, mcsStatus);
10421 }
10422
10423 return MYKONOS_ERR_OK;
10424 }
10425
10426 /**
10427 * \brief Enables or disables SYSREF to the transceiver's RX framer
10428 *
10429 * <B>Dependencies</B>
10430 * - device->spiSettings
10431 *
10432 * \param device is a pointer to the device settings structure
10433 * \param enable = '1' enables SYSREF to RX framer, '0' disables SYSREF to framer
10434 *
10435 * \retval MYKONOS_ERR_OK Function completed successfully
10436 */
MYKONOS_enableSysrefToRxFramer(mykonosDevice_t * device,uint8_t enable)10437 mykonosErr_t MYKONOS_enableSysrefToRxFramer(mykonosDevice_t *device, uint8_t enable)
10438 {
10439
10440 #if (MYKONOS_VERBOSE == 1)
10441 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableSysrefToRxFramer()\n");
10442 #endif
10443
10444 if (enable)
10445 {
10446 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x01, 0x01, 0);
10447 }
10448 else
10449 {
10450 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x00, 0x01, 0);
10451 }
10452
10453 return MYKONOS_ERR_OK;
10454 }
10455
10456 /**
10457 * \brief Enables or disables SYSREF to the transceiver's Observation RX framer
10458 *
10459 * <B>Dependencies</B>
10460 * - device->spiSettings
10461 *
10462 * \param device is a pointer to the device settings structure
10463 * \param enable = '1' enables SYSREF to OBSRX framer, '0' disables SYSREF to framer
10464 *
10465 * \retval MYKONOS_ERR_OK Function completed successfully
10466 */
MYKONOS_enableSysrefToObsRxFramer(mykonosDevice_t * device,uint8_t enable)10467 mykonosErr_t MYKONOS_enableSysrefToObsRxFramer(mykonosDevice_t *device, uint8_t enable)
10468 {
10469
10470 #if (MYKONOS_VERBOSE == 1)
10471 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableSysrefToObsRxFramer()\n");
10472 #endif
10473
10474 if (enable)
10475 {
10476 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x01, 0x01, 0);
10477 }
10478 else
10479 {
10480 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x00, 0x01, 0);
10481 }
10482
10483 return MYKONOS_ERR_OK;
10484 }
10485
10486 /**
10487 * \brief Enables or disables SYSREF to the transceiver's deframer
10488 *
10489 * <B>Dependencies</B>
10490 * - device->spiSettings
10491 *
10492 * \param device is a pointer to the device settings structure
10493 * \param enable = '1' enables SYSREF to deframer, '0' disables SYSREF to deframer
10494 *
10495 * \retval MYKONOS_ERR_OK Function completed successfully
10496 */
MYKONOS_enableSysrefToDeframer(mykonosDevice_t * device,uint8_t enable)10497 mykonosErr_t MYKONOS_enableSysrefToDeframer(mykonosDevice_t *device, uint8_t enable)
10498 {
10499
10500 #if (MYKONOS_VERBOSE == 1)
10501 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableSysrefToDeframer()\n");
10502 #endif
10503
10504 if (enable)
10505 {
10506 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x01, 0x01, 0);
10507 }
10508 else
10509 {
10510 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x00, 0x01, 0);
10511 }
10512
10513 return MYKONOS_ERR_OK;
10514 }
10515
10516 /**
10517 * \brief Reads the transceiver's RX framer status
10518 *
10519 * <B>Dependencies</B>
10520 * - device->spiSettings
10521 *
10522 * framerStatus | Description
10523 * -------------|-----------------------------------------------------------------------------
10524 * [7] | SYSREF phase error ? a new SYSREF had different timing than the first that set the LMFC timing.
10525 * [6] | Framer lane FIFO read/write pointer delta has changed. Can help debug issues with deterministic latency.
10526 * [5] | Framer has received the SYSREF and has retimed its LMFC
10527 * [4:2] | Framer ILAS state: 0=CGS, 1= 1st Multframe, 2= 2nd Multiframe, 3= 3rd Multiframe, 4= 4th multiframe, 5= Last multiframe, 6=invalid, 7= ILAS complete
10528 * [1:0] | Framer Tx state: 0=CGS, 1= ILAS, 2 = ADC Data
10529 *
10530 * \param device is a pointer to the device settings structure
10531 * \param framerStatus is the RX framer status byte read
10532 *
10533 * \retval MYKONOS_ERR_OK Function completed successfully
10534 * \retval MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM Function parameter framerStatus has NULL pointer
10535 */
MYKONOS_readRxFramerStatus(mykonosDevice_t * device,uint8_t * framerStatus)10536 mykonosErr_t MYKONOS_readRxFramerStatus(mykonosDevice_t *device, uint8_t *framerStatus)
10537 {
10538
10539 #if (MYKONOS_VERBOSE == 1)
10540 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readRxFramerStatus()\n");
10541 #endif
10542
10543 if (framerStatus == NULL)
10544 {
10545 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM,
10546 getMykonosErrorMessage(MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM));
10547 return MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM;
10548 }
10549
10550 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_STATUS_STRB, 0x01);
10551 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_STATUS_STRB, 0x00);
10552 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FRAMER_STATUS, framerStatus);
10553
10554 return MYKONOS_ERR_OK;
10555 }
10556
10557 /**
10558 * \brief Reads the transceiver's Observation RX framer status
10559 *
10560 * <B>Dependencies</B>
10561 * * - device->spiSettings
10562 *
10563 * obsFramerStatus | Description
10564 * ----------------|-----------------------------------------------------------------------------
10565 * [7] | SYSREF phase error ? a new SYSREF had different timing than the first that set the LMFC timing.
10566 * [6] | Framer lane FIFO read/write pointer delta has changed. Can help debug issues with deterministic latency.
10567 * [5] | Framer has received the SYSREF and has retimed its LMFC
10568 * [4:2] | Framer ILAS state: 0=CGS, 1= 1st Multframe, 2= 2nd Multiframe, 3= 3rd Multiframe, 4= 4th multiframe, 5= Last multiframe, 6=invalid, 7= ILAS complete
10569 * [1:0] | Framer Tx state: 0=CGS, 1= ILAS, 2 = ADC Data
10570 *
10571 * \param device is a pointer to the device settings structure
10572 * \param obsFramerStatus is the OBSRX framer status byte read
10573 *
10574 * \retval MYKONOS_ERR_OK Function completed successfully
10575 * \retval MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM Function parameter obsFramerStatus has NULL pointer
10576 */
MYKONOS_readOrxFramerStatus(mykonosDevice_t * device,uint8_t * obsFramerStatus)10577 mykonosErr_t MYKONOS_readOrxFramerStatus(mykonosDevice_t *device, uint8_t *obsFramerStatus)
10578 {
10579
10580 #if (MYKONOS_VERBOSE == 1)
10581 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readOrxFramerStatus()\n");
10582 #endif
10583
10584 if (obsFramerStatus == NULL)
10585 {
10586 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM,
10587 getMykonosErrorMessage(MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM));
10588 return MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM;
10589 }
10590
10591 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_STATUS_STRB, 0x01);
10592 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_STATUS_STRB, 0x00);
10593 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_STATUS, obsFramerStatus);
10594
10595 return MYKONOS_ERR_OK;
10596 }
10597
10598 /**
10599 * \brief Reads the transceiver's deframer status
10600 *
10601 * <B>Dependencies</B>
10602 * - device->spiSettings
10603 *
10604 * deframerStatus | Bit Name | Description
10605 * ----------------|--------------------------|---------------------------------------------
10606 * [7] | Unused | Unused
10607 * [6] | Deframer IRQ | This bit indicates that the IRQ interrupt was asserted.
10608 * [5] | Deframer SYSREF Received | When this bit is set, it indicates that the SYSREF pulse was received by the deframer IP
10609 * [4] | Deframer Receiver Error | This bit is set when PRBS has received an error.
10610 * [3] | Valid Checksum | This bit is set when the received ILAS checksum is valid.
10611 * [2] | EOF Event | This bit captures the internal status of the framer End of Frame event. Value =1 if framing error during ILAS
10612 * [1] | EOMF Event | This bit captures the internal status of the framer End of Multi-Frame event. Value =1 if framing error during ILAS
10613 * [0] | FS Lost | This bit captures the internal status of the framer Frame Symbol event. Value =1 if framing error during ILAS or user data (invalid replacement characters)
10614 *
10615 *
10616 * \param device is a pointer to the device settings structure
10617 * \param deframerStatus is the deframer status byte read
10618 *
10619 * \retval MYKONOS_ERR_OK Function completed successfully
10620 * \retval MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM Function parameter deframerStatus has NULL pointer
10621 */
MYKONOS_readDeframerStatus(mykonosDevice_t * device,uint8_t * deframerStatus)10622 mykonosErr_t MYKONOS_readDeframerStatus(mykonosDevice_t *device, uint8_t *deframerStatus)
10623 {
10624
10625 #if (MYKONOS_VERBOSE == 1)
10626 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readDeframerStatus()\n");
10627 #endif
10628
10629 if (deframerStatus == NULL)
10630 {
10631 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM,
10632 getMykonosErrorMessage(MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM));
10633 return MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM;
10634 }
10635
10636 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x01);
10637 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x00);
10638 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT, deframerStatus);
10639
10640 return MYKONOS_ERR_OK;
10641 }
10642
10643 /**
10644 * \brief Reads the Mykonos JESD204b Deframer determinstic FIFO depth
10645 *
10646 * To verify that the deterministic latency FIFO is not close to a underflow or
10647 * overflow condition, it is recommended to check the FIFO depth. If the FIFO
10648 * is close to an overflow or underflow condition, it is possible that from
10649 * power up to powerup, deterministic latency may not be met. If a underflow
10650 * or overflow occurred, the data would still be correct, but would possibly
10651 * slip by 1 multiframe (losing deterministic latency). To correct for an
10652 * overflow/underflow, the BBIC would need to add delay from SYSREF until
10653 * the first symbol in a multiframe
10654 *
10655 * <B>Dependencies</B>
10656 * - device->spiSettings
10657 *
10658 * \param device is a pointer to the device settings structure
10659 * \param fifoDepth Return value that describes the depth of the Mykonos
10660 * deterministic latency deframer FIFO.
10661 * \param readEnLmfcCount Returns the LMFC count value when the deterministic FIFO read enable was asserted.
10662 * Counts at the Mykonos internal deframer PCLK frequency.
10663 *
10664 * \retval MYKONOS_ERR_OK Function completed successfully
10665 * \retval MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM Error: function parameter fifoDepth is a NULL pointer
10666 * \retval MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM Error: function parameter readEnLmfcCount is a NULL pointer
10667 *
10668 */
MYKONOS_getDeframerFifoDepth(mykonosDevice_t * device,uint8_t * fifoDepth,uint8_t * readEnLmfcCount)10669 mykonosErr_t MYKONOS_getDeframerFifoDepth(mykonosDevice_t *device, uint8_t *fifoDepth, uint8_t *readEnLmfcCount)
10670 {
10671 uint8_t fifoReadPtr = 0;
10672 uint8_t fifoWritePtr = 0;
10673
10674 #if (MYKONOS_VERBOSE == 1)
10675 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDeframerFifoDepth()\n");
10676 #endif
10677
10678 if (fifoDepth == NULL)
10679 {
10680 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM,
10681 getMykonosErrorMessage(MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM));
10682 return MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM;
10683 }
10684
10685 if (readEnLmfcCount == NULL)
10686 {
10687 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM,
10688 getMykonosErrorMessage(MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM));
10689 return MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM;
10690 }
10691
10692 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x01);
10693 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x00);
10694
10695 /* read/write pointers are 7 bits, (0 - 127) */
10696 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_RD_ADDR, &fifoReadPtr, 0x7F, 0);
10697 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_ADDR, &fifoWritePtr, 0x7F, 0);
10698
10699 /* Adding 128 and modulus 128 handle the wrap cases where the read pointer
10700 * is less than write pointer
10701 */
10702 *fifoDepth = (((fifoWritePtr + 128) - fifoReadPtr) % 128);
10703
10704 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_PHASE, readEnLmfcCount);
10705
10706 return MYKONOS_ERR_OK;
10707 }
10708
10709 /**
10710 * \brief Selects the PRBS type and enables or disables RX Framer PRBS20 generation
10711 *
10712 * <B>Dependencies</B>
10713 * - device->spiSettings
10714 *
10715 * \param device is a pointer to the device settings structure
10716 * \param polyOrder selects the PRBS type based on a two-bit value range from 0-3
10717 * \param enable '1' = enables PRBS RX framer PRBS generator, '0' = disables PRBS generator
10718 *
10719 * \retval MYKONOS_ERR_OK Function completed successfully
10720 * \retval MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM Invalid polyOrder parameter, use ENUM
10721 *
10722 */
MYKONOS_enableRxFramerPrbs(mykonosDevice_t * device,mykonosPrbsOrder_t polyOrder,uint8_t enable)10723 mykonosErr_t MYKONOS_enableRxFramerPrbs(mykonosDevice_t *device, mykonosPrbsOrder_t polyOrder, uint8_t enable)
10724 {
10725 uint8_t wrmask = 0;
10726 uint8_t enableBit = 0;
10727
10728 #if (MYKONOS_VERBOSE == 1)
10729 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableRxFramerPrbs()\n");
10730 #endif
10731
10732 enableBit = (enable > 0) ? 1 : 0;
10733
10734 if ((polyOrder == MYK_PRBS7) || (polyOrder == MYK_PRBS15) || (polyOrder == MYK_PRBS31))
10735 {
10736 wrmask = ((uint8_t)polyOrder << 1) | enableBit;
10737 }
10738 else
10739 {
10740 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM,
10741 getMykonosErrorMessage(MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM));
10742 return MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM;
10743 }
10744
10745 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, wrmask);
10746
10747 return MYKONOS_ERR_OK;
10748 }
10749
10750 /**
10751 * \brief Selects the PRBS type and enables or disables OBSRX Framer PRBS20 generation
10752 *
10753 * <B>Dependencies</B>
10754 * - device->spiSettings
10755 *
10756 * \param device is a pointer to the device settings structure
10757 * \param polyOrder selects the PRBS type based on a two-bit value range from 0-3
10758 * \param enable '1' = enables PRBS OBSRX framer PRBS generator, '0' = disables PRBS generator
10759 *
10760 * \retval MYKONOS_ERR_OK Function completed successfully
10761 * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM polyOrder parameter is not a valid value - use ENUM
10762 */
MYKONOS_enableObsRxFramerPrbs(mykonosDevice_t * device,mykonosPrbsOrder_t polyOrder,uint8_t enable)10763 mykonosErr_t MYKONOS_enableObsRxFramerPrbs(mykonosDevice_t *device, mykonosPrbsOrder_t polyOrder, uint8_t enable)
10764 {
10765 uint8_t wrmask = 0;
10766 uint8_t enableBit = 0;
10767
10768 #if (MYKONOS_VERBOSE == 1)
10769 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableObsRxFramerPrbs()\n");
10770 #endif
10771
10772 enableBit = (enable > 0) ? 1 : 0;
10773
10774 if ((polyOrder == MYK_PRBS7) || (polyOrder == MYK_PRBS15) || (polyOrder == MYK_PRBS31))
10775 {
10776 wrmask = ((uint8_t)polyOrder << 1) | enableBit;
10777 }
10778 else
10779 {
10780 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM,
10781 getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM));
10782 return MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM;
10783 }
10784
10785 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, wrmask);
10786
10787 return MYKONOS_ERR_OK;
10788 }
10789
10790 /**
10791 * \brief Injects a PRBS error into the RX data path
10792 *
10793 * <B>Dependencies</B>
10794 * - device->spiSettings
10795 *
10796 * \param device is a pointer to the device settings structure
10797 *
10798 * \retval MYKONOS_ERR_OK Function completed successfully
10799 */
MYKONOS_rxInjectPrbsError(mykonosDevice_t * device)10800 mykonosErr_t MYKONOS_rxInjectPrbsError(mykonosDevice_t *device)
10801 {
10802 uint8_t prbsControl = 0x00;
10803
10804 #if (MYKONOS_VERBOSE == 1)
10805 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_rxInjectPrbsError()\n");
10806 #endif
10807
10808 /* reading current PRBS20 control register contents */
10809 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, &prbsControl);
10810
10811 /* setting bit 4 in framer PRBS20 control register and then clearing it for error injection */
10812 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, prbsControl |= 0x10);
10813 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, prbsControl &= ~0x10);
10814
10815 return MYKONOS_ERR_OK;
10816 }
10817
10818 /**
10819 * \brief Initiates a PRBS error injection into the Observation RX data path
10820 *
10821 * <B>Dependencies</B>
10822 * - device->spiSettings
10823 *
10824 * \param device is a pointer to the device settings structure
10825 *
10826 * \retval MYKONOS_ERR_OK Function completed successfully
10827 */
MYKONOS_obsRxInjectPrbsError(mykonosDevice_t * device)10828 mykonosErr_t MYKONOS_obsRxInjectPrbsError(mykonosDevice_t *device)
10829 {
10830 uint8_t prbsControl = 0x00;
10831
10832 #if (MYKONOS_VERBOSE == 1)
10833 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_obsRxInjectPrbsError()\n");
10834 #endif
10835
10836 /* reading current PRBS20 control register contents */
10837 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, &prbsControl);
10838
10839 /* setting bit 4 in framer PRBS20 control register and then clearing it for error injection */
10840 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, prbsControl |= 0x10);
10841 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, prbsControl &= ~0x10);
10842
10843 return MYKONOS_ERR_OK;
10844 }
10845
10846 /**
10847 * \brief Configures and enables or disables the transceiver's deframer PRBS checker
10848 *
10849 * <B>Dependencies</B>
10850 * - device->spiSettings
10851 *
10852 * \param device is a pointer to the device settings structure
10853 * \param lanes selects the lane for PRBS checking based on a 4-bit mask, where each weighted bit
10854 * corresponds with a different lane selection as such: '1' = lane 0, '2' = lane 1, '4' = lane 2, '8' = lane 3
10855 * \param polyOrder selects the PRBS type based on enum values (MYK_PRBS7, MYK_PRBS15, MYK_PRBS31)
10856 * \param enable '1' = enables checking, '0' = disables checking
10857 *
10858 * \retval MYKONOS_ERR_OK Function completed successfully
10859 * \retval MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM Invalid polyOrder parameter - use ENUM
10860 * \retval MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM Invalid enable (valid 0-1) or lanes (valid 0-15) parameter
10861 */
MYKONOS_enableDeframerPrbsChecker(mykonosDevice_t * device,uint8_t lanes,mykonosPrbsOrder_t polyOrder,uint8_t enable)10862 mykonosErr_t MYKONOS_enableDeframerPrbsChecker(mykonosDevice_t *device, uint8_t lanes, mykonosPrbsOrder_t polyOrder, uint8_t enable)
10863 {
10864 uint8_t wrmask = 0x00;
10865
10866 #if (MYKONOS_VERBOSE == 1)
10867 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableDeframerPrbsChecker()\n");
10868 #endif
10869
10870 if ((enable <= 0x01) && (lanes <= 0x0F))
10871 {
10872 if ((polyOrder == MYK_PRBS7) || (polyOrder == MYK_PRBS15) || (polyOrder == MYK_PRBS31))
10873 {
10874 wrmask = ((lanes << 4) | ((uint8_t)polyOrder << 1) | enable);
10875 }
10876 else
10877 {
10878 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM,
10879 getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM));
10880 return MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM;
10881 }
10882 }
10883 else
10884 {
10885 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM,
10886 getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM));
10887 return MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM;
10888 }
10889
10890 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, wrmask);
10891
10892 return MYKONOS_ERR_OK;
10893 }
10894
10895 /**
10896 * \brief Reads the deframer PRBS counters
10897 *
10898 * <B>Dependencies</B>
10899 * - device->spiSettings
10900 *
10901 * \param device is a pointer to the device settings structure
10902 * \param counterSelect selects the PRBS error counter to be read based on values between 0-3
10903 * If counterSelect exceeds this value an error is thrown.
10904 *
10905 * \param prbsErrorCount is return value after reading the PRBS error count
10906 *
10907 * \retval MYKONOS_ERR_OK Function completed successfully
10908 * \retval MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM Function parameter prbsErrorCount has NULL pointer
10909 * \retval MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM if counterSelect is out of bounds
10910 */
MYKONOS_readDeframerPrbsCounters(mykonosDevice_t * device,uint8_t counterSelect,uint32_t * prbsErrorCount)10911 mykonosErr_t MYKONOS_readDeframerPrbsCounters(mykonosDevice_t *device, uint8_t counterSelect, uint32_t *prbsErrorCount)
10912 {
10913 uint8_t wrmask = 0x00;
10914 uint8_t errorCnt[3] = {0};
10915 const uint8_t COUNTER_SATURATE = 0x40;
10916
10917 #if (MYKONOS_VERBOSE == 1)
10918 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readDeframerPrbsCounters()\n");
10919 #endif
10920
10921 if (prbsErrorCount == NULL)
10922 {
10923 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM,
10924 getMykonosErrorMessage(MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM));
10925 return MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM;
10926 }
10927
10928 if (counterSelect & ~0x03)
10929 {
10930 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM,
10931 getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM));
10932 return MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM;
10933 }
10934 else
10935 {
10936 wrmask = (uint8_t)(COUNTER_SATURATE | (counterSelect << 4));
10937 *prbsErrorCount = 0x00000000;
10938 }
10939
10940 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_STRB_CHKSUM_TYPE, wrmask);
10941 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_STRB_CHKSUM_TYPE, wrmask |= 0x01);
10942 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_STRB_CHKSUM_TYPE, wrmask &= ~0x01);
10943
10944 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_7_TO_0, &errorCnt[0]);
10945 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_15_TO_8, &errorCnt[1]);
10946 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_23_TO_16, &errorCnt[2]);
10947
10948 *prbsErrorCount = (uint32_t)(errorCnt[2] << 16) | (uint32_t)(errorCnt[1] << 8) | (uint32_t)(errorCnt[0]);
10949
10950 return MYKONOS_ERR_OK;
10951 }
10952
10953 /**
10954 * \brief Clears the deframer/deserializer PRBS counters
10955 *
10956 * <B>Dependencies</B>
10957 * - device->spiSettings
10958 *
10959 * \param device is a pointer to the device settings structure
10960 *
10961 * \retval MYKONOS_ERR_OK Function completed successfully
10962 */
MYKONOS_clearDeframerPrbsCounters(mykonosDevice_t * device)10963 mykonosErr_t MYKONOS_clearDeframerPrbsCounters(mykonosDevice_t *device)
10964 {
10965 uint8_t spiReg = 0;
10966
10967 #if (MYKONOS_VERBOSE == 1)
10968 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_clearDeframerPrbsCounters()\n");
10969 #endif
10970
10971 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, &spiReg);
10972 spiReg &= ~0x08; //make sure PRBS clear bit is 0
10973
10974 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, (spiReg | 0xF8)); //clear counters for all lanes
10975 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, spiReg); //set reg back to previous value
10976
10977 return MYKONOS_ERR_OK;
10978 }
10979
10980 /**
10981 * \brief Reads the lane 0 JESD204B deframer configuration and compares it against the ILAS received values
10982 *
10983 * <B>Dependencies</B>
10984 * - device->spiSettings->chipSelectIndex
10985 *
10986 * \param device is a pointer to the device settings structure
10987 * \param mismatch [15-0] is a bit-encoded word which for mismatch[15] = '0' = no mismatch, '1' = mismatch for one or more parameters
10988 * mismatch bits [14-0] are aligned with the mykonosJesd204bLane0Config_t structure members starting at '0' = DID. The aligned bit is set to
10989 * '1' if the configuration parameter does not agree with its corresponding received ILAS value, otherwise '0' if they agree.
10990 *
10991 * The bit assignments for the 16-bit word are:
10992 * mismatch | bit description
10993 * -----------|--------------------------------------------------------
10994 * [0] | JESD204B DID: device ID
10995 * [1] | JESD204B BID: bank ID
10996 * [2] | JESD204B LID0: lane ID
10997 * [3] | JESD204B L: lanes per data converter
10998 * [4] | JESD204B SCR: scramble setting
10999 * [5] | JESD204B F: octets per frame
11000 * [6] | JESD204B K: frames per multiframe
11001 * [7] | JESD204B M: number of data converters
11002 * [8] | JESD204B N: data converter sample resolution
11003 * [9] | JESD204B CS: number of control bits transferred per sample per frame
11004 * [10] | JESD204B NP: JESD204B word size based on the highest data converter resolution
11005 * [11] | JESD204B S: number of samples per converter per frame
11006 * [12] | JESD204B CF: '0' = control bits appended to each sample, '1' = control bits appended to end of frame
11007 * [13] | JESD204B HD: high density bit, where '0' = samples are contained with single lane, '1' = samples are divided over more than one lane
11008 * [14] | JESD204B FCHK0: configuration checksum OK bit. where '1' = fail, '0' = pass
11009 * [15] | MISMATCH DETECTED BIT: bits 0-14 are ored together to set this bit
11010 *
11011 * \retval MYKONOS_ERR_OK Function completed successfully
11012 * \retval MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM Function parameter mismatch has NULL pointer
11013 */
MYKONOS_jesd204bIlasCheck(mykonosDevice_t * device,uint16_t * mismatch)11014 mykonosErr_t MYKONOS_jesd204bIlasCheck(mykonosDevice_t *device, uint16_t *mismatch)
11015 {
11016 uint8_t i = 0;
11017 uint8_t ilasdata[15] = {0};
11018 uint8_t cfgdata[15] = {0};
11019 mykonosJesd204bLane0Config_t lane0ILAS;
11020 mykonosJesd204bLane0Config_t lane0Cfg;
11021
11022 #if (MYKONOS_VERBOSE == 1)
11023 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_jesd204bIlasCheck()\n");
11024 #endif
11025
11026 if (mismatch == NULL)
11027 {
11028 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM,
11029 getMykonosErrorMessage(MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM));
11030 return MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM;
11031 }
11032
11033 *mismatch = 0;
11034
11035 /* setting deframer read received ILAS data */
11036 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_WR_EN, 0x00);
11037
11038 /* reading deframer received ILAS register contents into array */
11039 for (i = 0; i < 15; i++)
11040 {
11041 /* setting the deframer sub-address for received ilas data */
11042 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_ADDR, MYKONOS_SUBADDR_DEFRAMER_LANE0_ILAS_RECVD + i);
11043
11044 /* reading the received ILAS data into byte array */
11045 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DATA, &ilasdata[i]);
11046 }
11047
11048 /* reading deframer config register contents into array */
11049 for (i = 0; i < 15; i++)
11050 {
11051 /* setting the deframer sub-address for received ilas data */
11052 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_ADDR, MYKONOS_SUBADDR_DEFRAMER_LANE0_ILAS_CFG + i);
11053
11054 /* reading the received ILAS data into byte array */
11055 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DATA, &cfgdata[i]);
11056 }
11057
11058 /* loading the structures with the read values for easier reading when doing compares */
11059 lane0ILAS.DID = ilasdata[0];
11060 lane0ILAS.BID = ilasdata[1] & 0x0F;
11061 lane0ILAS.LID0 = ilasdata[2] & 0x1F;
11062 lane0ILAS.L = ilasdata[3] & 0x1F;
11063 lane0ILAS.SCR = ilasdata[3] >> 7;
11064 lane0ILAS.F = ilasdata[4];
11065 lane0ILAS.K = ilasdata[5] & 0x1F;
11066 lane0ILAS.M = ilasdata[6];
11067 lane0ILAS.N = ilasdata[7] & 0x1F;
11068 lane0ILAS.CS = ilasdata[7] >> 6;
11069 lane0ILAS.NP = ilasdata[8] & 0x1F;
11070 lane0ILAS.S = ilasdata[9] & 0x1F;
11071 lane0ILAS.CF = ilasdata[10] & 0x1F;
11072 lane0ILAS.HD = ilasdata[10] >> 7;
11073 lane0ILAS.FCHK0 = ilasdata[13];
11074
11075 lane0Cfg.DID = cfgdata[0];
11076 lane0Cfg.BID = cfgdata[1] & 0x0F;
11077 lane0Cfg.LID0 = cfgdata[2] & 0x0F;
11078 lane0Cfg.L = cfgdata[3] & 0x1F;
11079 lane0Cfg.SCR = cfgdata[3] >> 7;
11080 lane0Cfg.F = cfgdata[4];
11081 lane0Cfg.K = cfgdata[5] & 0x1F;
11082 lane0Cfg.M = cfgdata[6];
11083 lane0Cfg.N = cfgdata[7] & 0x1F;
11084 lane0Cfg.CS = cfgdata[7] >> 6;
11085 lane0Cfg.NP = cfgdata[8] & 0x1F;
11086 lane0Cfg.S = cfgdata[9] & 0x1F;
11087 lane0Cfg.CF = cfgdata[10] & 0x1F;
11088 lane0Cfg.HD = cfgdata[10] >> 7;
11089 lane0Cfg.FCHK0 = cfgdata[13];
11090
11091 /* performing ILAS mismatch check */
11092 if (lane0ILAS.DID != lane0Cfg.DID)
11093 {
11094 *mismatch |= 0x0001;
11095 }
11096
11097 if (lane0ILAS.BID != lane0Cfg.BID)
11098 {
11099 *mismatch |= 0x0002;
11100 }
11101
11102 if (lane0ILAS.LID0 != lane0Cfg.LID0)
11103 {
11104 *mismatch |= 0x0004;
11105 }
11106
11107 if (lane0ILAS.L != lane0Cfg.L)
11108 {
11109 *mismatch |= 0x0008;
11110 }
11111
11112 if (lane0ILAS.SCR != lane0Cfg.SCR)
11113 {
11114 *mismatch |= 0x0010;
11115 }
11116
11117 if (lane0ILAS.F != lane0Cfg.F)
11118 {
11119 *mismatch |= 0x0020;
11120 }
11121
11122 if (lane0ILAS.K != lane0Cfg.K)
11123 {
11124 *mismatch |= 0x0040;
11125 }
11126
11127 if (lane0ILAS.M != lane0Cfg.M)
11128 {
11129 *mismatch |= 0x0080;
11130 }
11131
11132 if (lane0ILAS.N != lane0Cfg.N)
11133 {
11134 *mismatch |= 0x0100;
11135 }
11136
11137 if (lane0ILAS.CS != lane0Cfg.CS)
11138 {
11139 *mismatch |= 0x0200;
11140 }
11141
11142 if (lane0ILAS.NP != lane0Cfg.NP)
11143 {
11144 *mismatch |= 0x0400;
11145 }
11146
11147 if (lane0ILAS.S != lane0Cfg.S)
11148 {
11149 *mismatch |= 0x0800;
11150 }
11151
11152 if (lane0ILAS.CF != lane0Cfg.CF)
11153 {
11154 *mismatch |= 0x1000;
11155 }
11156
11157 if (lane0ILAS.HD != lane0Cfg.HD)
11158 {
11159 *mismatch |= 0x2000;
11160 }
11161
11162 if (lane0ILAS.FCHK0 != lane0Cfg.FCHK0)
11163 {
11164 *mismatch |= 0x4000;
11165 }
11166
11167 if (*mismatch)
11168 {
11169 *mismatch |= 0x8000;
11170 CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_ERR_JESD204B_ILAS_MISMATCH,
11171 getMykonosErrorMessage(MYKONOS_ERR_JESD204B_ILAS_MISMATCH));
11172 }
11173
11174 return MYKONOS_ERR_OK;
11175 }
11176
11177 /**
11178 * \brief Select data to inject into the Rx framer input (ADC data or Loopback data from deframer output)
11179 *
11180 * This function allows inputting deframed data (IQ samples) from the Tx data path into the Rx framer.
11181 * For this to work correctly, the IQ data rate of the Tx data path must match the Rx IQ data rate.
11182 * Framer/Deframer JESD204 config parameters can vary as long as the Rx and Tx IQ rates match.
11183 *
11184 * <B>Dependencies</B>
11185 * - device->spiSettings->chipSelectIndex
11186 *
11187 * \param device A pointer to the device settings structure
11188 * \param dataSource 0 = ADC data at Rx Framer input, 1 = Deframed Tx JESD204 IQ samples input into Rx framer
11189 *
11190 * \retval MYKONOS_ERR_OK Function completed successfully
11191 */
MYKONOS_setRxFramerDataSource(mykonosDevice_t * device,uint8_t dataSource)11192 mykonosErr_t MYKONOS_setRxFramerDataSource(mykonosDevice_t *device, uint8_t dataSource)
11193 {
11194 uint8_t enableLoopBack = 0;
11195
11196 #if (MYKONOS_VERBOSE == 1)
11197 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxFramerDataSource()\n");
11198 #endif
11199
11200 enableLoopBack = (dataSource > 0) ? 1 : 0;
11201
11202 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, enableLoopBack, 0x10, 4);
11203
11204 return MYKONOS_ERR_OK;
11205 }
11206
11207 /**
11208 * \brief Select data to inject into the ObsRx framer input (ADC data or Loopback data from deframer output)
11209 *
11210 * This function allows inputting deframed data (IQ samples) from the Tx data path into the Obs Rx framer.
11211 * For this to work correctly, the IQ data rate of the Tx data path must match the ORx IQ data rate.
11212 * Framer/Deframer JESD204 config parameters can vary as long as the Obs Rx and Tx IQ rates match.
11213 *
11214 * <B>Dependencies</B>
11215 * - device->spiSettings->chipSelectIndex
11216 *
11217 * \param device A pointer to the device settings structure
11218 * \param dataSource 0 = ADC data at ObsRx Framer input, 1 = Deframed Tx JESD204 IQ samples input into Obs Rx framer
11219 *
11220 * \retval MYKONOS_ERR_OK Function completed successfully
11221 */
MYKONOS_setObsRxFramerDataSource(mykonosDevice_t * device,uint8_t dataSource)11222 mykonosErr_t MYKONOS_setObsRxFramerDataSource(mykonosDevice_t *device, uint8_t dataSource)
11223 {
11224 uint8_t enableLoopBack = 0;
11225
11226 #if (MYKONOS_VERBOSE == 1)
11227 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxFramerDataSource()\n");
11228 #endif
11229
11230 enableLoopBack = (dataSource > 0) ? 1 : 0;
11231
11232 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CONFIG_LOOPBACK_XBAR_REV, enableLoopBack, 0x10, 4);
11233
11234 return MYKONOS_ERR_OK;
11235 }
11236
11237 /**
11238 * \brief Runs the Mykonos initialization calibrations
11239 *
11240 * <B>Dependencies</B>
11241 * - device->spiSettings->chipSelectIndex
11242 *
11243 * ENUM mykonosInitCalibrations_t can be used to OR together to generate the calMask parameter.
11244 *
11245 * calMask Bit | Calibration
11246 * ------------|----------------------
11247 * 0 | Tx BB Filter
11248 * 1 | ADC Tuner
11249 * 2 | TIA 3dB Corner
11250 * 3 | DC Offset
11251 * 4 | Tx Attenuation Delay
11252 * 5 | Rx Gain Delay
11253 * 6 | Flash Cal
11254 * 7 | Path Delay
11255 * 8 | Tx LO Leakage Internal
11256 * 9 | Tx LO Leakage External
11257 * 10 | Tx QEC Init
11258 * 11 | LoopBack Rx LO Delay
11259 * 12 | LoopBack Rx Rx QEC Init
11260 * 13 | Rx LO Delay
11261 * 14 | Rx QEC Init
11262 * 15 | DPD Init
11263 * 16 | Tx CLGC (Closed Loop Gain Control)
11264 * 17 | Tx VSWR Init
11265 * [31-18] | Ignored - Future space for new calibrations
11266 *
11267 * \param device A pointer to the device settings structure
11268 * \param calMask A bitmask that informs the Mykonos ARM processor which calibrations to run
11269 *
11270 * \retval MYKONOS_ERR_OK Function completed successfully
11271 */
MYKONOS_runInitCals(mykonosDevice_t * device,uint32_t calMask)11272 mykonosErr_t MYKONOS_runInitCals(mykonosDevice_t *device, uint32_t calMask)
11273 {
11274 mykonosErr_t retVal = MYKONOS_ERR_OK;
11275 const uint8_t RUNINITCALS_OPCODE = 0x02;
11276 uint8_t payload[4] = {0};
11277
11278 #if (MYKONOS_VERBOSE == 1)
11279 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_runInitCals()\n");
11280 #endif
11281
11282 payload[0] = (uint8_t)(calMask & 0xFF);
11283 payload[1] = (uint8_t)((calMask >> 8) & 0xFF);
11284 payload[2] = (uint8_t)((calMask >> 16) & 0xFF);
11285 payload[3] = (uint8_t)((calMask >> 24) & 0xFF);
11286
11287 retVal = MYKONOS_sendArmCommand(device, RUNINITCALS_OPCODE, &payload[0], sizeof(payload));
11288 if (retVal != MYKONOS_ERR_OK)
11289 {
11290 return retVal;
11291 }
11292
11293 return MYKONOS_ERR_OK;
11294 }
11295
11296 /**
11297 * \brief Blocking waits for the Mykonos initialization calibrations to complete
11298 *
11299 * The *errorFlag and *errorCode parameters are optional. If the pointers are
11300 * set to null, no values will be returned. If the function returns an error
11301 * that the init calibration failed, use the MYKONOS_getInitCalStatus() function
11302 * to get more detailed information about why the init cal failed.
11303 *
11304 * <B>Dependencies</B>
11305 * - device->spiSettings->chipSelectIndex
11306 *
11307 * \param device A pointer to the device settings structure
11308 * \param timeoutMs A timeout value in Ms to wait for the calibrations to complete
11309 * \param errorFlag A 3bit error flag that helps identify what went wrong in the ARM. 0=No Error
11310 * \param errorCode The value represents the init calibration object ID that caused a failure.
11311 *
11312 * \retval MYKONOS_ERR_OK Function completed successfully
11313 * \retval MYKONOS_ERR_WAIT_INITCALS_ARMERROR ARM returned error unrelated to init cals
11314 */
MYKONOS_waitInitCals(mykonosDevice_t * device,uint32_t timeoutMs,uint8_t * errorFlag,uint8_t * errorCode)11315 mykonosErr_t MYKONOS_waitInitCals(mykonosDevice_t *device, uint32_t timeoutMs, uint8_t *errorFlag, uint8_t *errorCode)
11316 {
11317 mykonosErr_t retVal = MYKONOS_ERR_OK;
11318 mykonosErr_t retValCalStatus = MYKONOS_ERR_OK;
11319 uint8_t cmdStatusByte = 0;
11320 uint8_t _errorFlag = 0; /* Local version of parameter */
11321 mykonosInitCalStatus_t initCalStatus = {0};
11322
11323 const uint8_t INITCALS_CAL_ERROR = 0x07;
11324
11325 #if (MYKONOS_VERBOSE == 1)
11326 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_waitInitCals()\n");
11327 #endif
11328
11329 /* Clear before making any calls that can throw errors */
11330 if (errorFlag != NULL)
11331 {
11332 *errorFlag = 0;
11333 }
11334
11335 /* Clear before making any calls that can throw errors */
11336 if (errorCode != NULL)
11337 {
11338 *errorCode = 0;
11339 }
11340
11341 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_RUNINIT_OPCODE, timeoutMs, &cmdStatusByte);
11342 _errorFlag = cmdStatusByte >> 1; /* remove pending bit in [0], error flag is in bits [3:1] */
11343
11344 if (errorFlag != NULL)
11345 {
11346 *errorFlag = _errorFlag;
11347 }
11348
11349 if (retVal != MYKONOS_ERR_OK)
11350 {
11351 if (_errorFlag == INITCALS_CAL_ERROR)
11352 {
11353 /* return Error code if a calibration had an error */
11354 retValCalStatus = MYKONOS_getInitCalStatus(device, &initCalStatus);
11355 if (retValCalStatus == MYKONOS_ERR_OK)
11356 {
11357 if (errorCode != NULL)
11358 {
11359 *errorCode = initCalStatus.initErrCal;
11360 }
11361 }
11362
11363 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_CALFAILED,
11364 getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_CALFAILED));
11365 return MYKONOS_ERR_WAIT_INITCALS_CALFAILED;
11366 }
11367 else if (cmdStatusByte > 0)
11368 {
11369 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_ARMERROR,
11370 getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_ARMERROR));
11371 return MYKONOS_ERR_WAIT_INITCALS_ARMERROR;
11372 }
11373 }
11374
11375 /* Same logic if MYKONOS_waitArmCmdStatus() did not return an error, but cmdStatusByte shows an ARM error */
11376 if (_errorFlag == INITCALS_CAL_ERROR)
11377 {
11378 /* return Error code if a calibration had an error */
11379 retValCalStatus = MYKONOS_getInitCalStatus(device, &initCalStatus);
11380 if (retValCalStatus == MYKONOS_ERR_OK)
11381 {
11382 if (errorCode != NULL)
11383 {
11384 *errorCode = initCalStatus.initErrCal;
11385 }
11386 }
11387
11388 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_CALFAILED,
11389 getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_CALFAILED));
11390 return MYKONOS_ERR_WAIT_INITCALS_CALFAILED;
11391 }
11392 else if (cmdStatusByte > 0)
11393 {
11394 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_ARMERROR,
11395 getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_ARMERROR));
11396 return MYKONOS_ERR_WAIT_INITCALS_ARMERROR;
11397 }
11398
11399 return MYKONOS_ERR_OK;
11400 }
11401
11402 /**
11403 * \brief Aborts from an on going ARM init calibration operation.
11404 *
11405 * The ARM init calibrations can take several seconds. If for any reason the Baseband processor
11406 * needs to stop the running ARM calibration sequence, call this function. The *calsCompleted
11407 * parameter is an option parameter that will return which cals completed before the abort
11408 * command was received. If *calsCompleted is a null pointer, no value will be returned.
11409 *
11410 * <B>Dependencies</B>
11411 * - device->spiSettings->chipSelectIndex
11412 *
11413 * \param device A pointer to the device settings structure
11414 * \param calsCompleted A bitmask is returned which describes which cals completed during the previous
11415 * MYKONOS_runInitCals() call.
11416 *
11417 * \retval MYKONOS_ERR_OK Function completed successfully
11418 * \retval MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM Function parameter calsCompleted has NULL pointer
11419 */
MYKONOS_abortInitCals(mykonosDevice_t * device,uint32_t * calsCompleted)11420 mykonosErr_t MYKONOS_abortInitCals(mykonosDevice_t *device, uint32_t *calsCompleted)
11421 {
11422 mykonosErr_t retVal = MYKONOS_ERR_OK;
11423 uint32_t timeoutMs = 1000; //1 second timeout
11424 uint8_t cmdStatusByte = 0;
11425 uint8_t payload = 0x43; /* object ID to get INIT_CAL_DONE status */
11426 uint8_t calCompleteBitField[4] = {0, 0, 0, 0};
11427
11428 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_ABORT_OPCODE, 0, 0);
11429 if (retVal != MYKONOS_ERR_OK)
11430 {
11431 return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */
11432 }
11433
11434 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_ABORT_OPCODE, timeoutMs, &cmdStatusByte);
11435 if (retVal != MYKONOS_ERR_OK)
11436 {
11437 return retVal; /* Will return if timeout occurred */
11438 }
11439
11440 /* Read back Calibration Completion status */
11441 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &payload, sizeof(payload));
11442 if (retVal != MYKONOS_ERR_OK)
11443 {
11444 return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */
11445 }
11446
11447 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
11448 if (retVal != MYKONOS_ERR_OK)
11449 {
11450 return retVal; /* Will return if timeout occurred */
11451 }
11452
11453 retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + 4), &calCompleteBitField[0], 4, 1);
11454 if (retVal != MYKONOS_ERR_OK)
11455 {
11456 return retVal;
11457 }
11458
11459 if (calsCompleted != NULL)
11460 {
11461 *calsCompleted = ((uint32_t)(calCompleteBitField[3]) << 24) | ((uint32_t)(calCompleteBitField[2]) << 16) | ((uint32_t)(calCompleteBitField[1]) << 8)
11462 | ((uint32_t)(calCompleteBitField[0]));
11463 }
11464 else
11465 {
11466 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM,
11467 getMykonosErrorMessage(MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM));
11468 return MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM;
11469 }
11470
11471 return MYKONOS_ERR_OK;
11472 }
11473
11474 /**
11475 * \brief Gets the device initialization calibration status
11476 *
11477 * This function requests the init cal status information from the Mykonos ARM
11478 * processor. The ARM returns information including a bitmask that describes
11479 * which calibrations have completed during the last cal of runInitCals, as
11480 * well as the init cals that have run successfully since loading the ARM. If
11481 * an ARM error does occur during one of the init calibrations, the initErrCal
11482 * member returns the object ID of the failing calibration. The initErrCode
11483 * returns the specific ARM error code that caused that calibration to fail.
11484 * The calsMinimum structure member describes the minimum set of init calibrations
11485 * required to complete by the ARM before it will allow the device to move to
11486 * the radioOn state.
11487 *
11488 * <B>Dependencies</B>
11489 * - device->spiSettings
11490 * - device->spiSettings->chipSelectIndex
11491 *
11492 * \param device A pointer to the device settings structure
11493 * \param initCalStatus Pointer to a structure that returns cal status information such as cals completed since last run, and init error codes
11494 *
11495 * \retval MYKONOS_ERR_OK Function completed successfully
11496 * \retval MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM if initCalStatus parameter is a NULL pointer
11497 * \retval MYKONOS_ERR_GETINITCALSTATUS_ARMERROR if ARM returned an error while requesting the init cal status information
11498 */
MYKONOS_getInitCalStatus(mykonosDevice_t * device,mykonosInitCalStatus_t * initCalStatus)11499 mykonosErr_t MYKONOS_getInitCalStatus(mykonosDevice_t *device, mykonosInitCalStatus_t *initCalStatus)
11500 {
11501 mykonosErr_t retVal = MYKONOS_ERR_OK;
11502 uint8_t cmdStatusByte = 0;
11503 uint8_t calStatusArray[14] = {0};
11504 uint8_t payload[1] = {MYKONOS_ARM_OBJECTID_INIT_CAL_DONE};
11505
11506 uint32_t timeoutMs = 1000;
11507
11508 /* Verify function parameter pointer is not NULL */
11509 if (initCalStatus == NULL)
11510 {
11511 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM,
11512 getMykonosErrorMessage(MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM));
11513 return MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM;
11514 }
11515
11516 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &payload[0], sizeof(payload));
11517 if (retVal != MYKONOS_ERR_OK)
11518 {
11519 return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */
11520 }
11521
11522 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
11523 if (retVal != MYKONOS_ERR_OK)
11524 {
11525 if (cmdStatusByte > 0)
11526 {
11527 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETINITCALSTATUS_ARMERROR,
11528 getMykonosErrorMessage(MYKONOS_ERR_GETINITCALSTATUS_ARMERROR));
11529 return MYKONOS_ERR_GETINITCALSTATUS_ARMERROR;
11530 }
11531
11532 return retVal; /* Will return if timeout occurred */
11533 }
11534
11535 if (cmdStatusByte > 0)
11536 {
11537 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETINITCALSTATUS_ARMERROR,
11538 getMykonosErrorMessage(MYKONOS_ERR_GETINITCALSTATUS_ARMERROR));
11539 return MYKONOS_ERR_GETINITCALSTATUS_ARMERROR;
11540 }
11541
11542 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &calStatusArray[0], sizeof(calStatusArray), 1);
11543 if (retVal != MYKONOS_ERR_OK)
11544 {
11545 return retVal;
11546 }
11547
11548 initCalStatus->calsDoneLifetime = ((uint32_t)(calStatusArray[3]) << 24) | ((uint32_t)(calStatusArray[2]) << 16) | ((uint32_t)(calStatusArray[1]) << 8)
11549 | ((uint32_t)(calStatusArray[0]));
11550 initCalStatus->calsDoneLastRun = ((uint32_t)(calStatusArray[7]) << 24) | ((uint32_t)(calStatusArray[6]) << 16) | ((uint32_t)(calStatusArray[5]) << 8)
11551 | ((uint32_t)(calStatusArray[4]));
11552 initCalStatus->calsMinimum = ((uint32_t)(calStatusArray[11]) << 24) | ((uint32_t)(calStatusArray[10]) << 16) | ((uint32_t)(calStatusArray[9]) << 8)
11553 | ((uint32_t)(calStatusArray[8]));
11554 initCalStatus->initErrCal = calStatusArray[12];
11555 initCalStatus->initErrCode = calStatusArray[13];
11556
11557 return MYKONOS_ERR_OK;
11558 }
11559
11560 /**
11561 * \brief Instructs the ARM processor to move the radio state to the Radio ON state
11562 *
11563 * When the ARM to the Radio On state, the enabled Rx and Tx signal chains will power up,
11564 * and the ARM tracking calibrations will begin. To exit this state back to a low power,
11565 * offline state, call the MYKONOS_radioOff() function.
11566 *
11567 * <B>Dependencies</B>
11568 * - device->spiSettings->chipSelectIndex
11569 *
11570 * \param device Pointer to the device settings structure
11571 *
11572 * \retval MYKONOS_ERR_OK Function completed successfully
11573 * \retval MYKONOS_ERR_ARM_RADIOON_FAILED ARM returned error running this command
11574 */
MYKONOS_radioOn(mykonosDevice_t * device)11575 mykonosErr_t MYKONOS_radioOn(mykonosDevice_t *device)
11576 {
11577 mykonosErr_t retVal = MYKONOS_ERR_OK;
11578 uint32_t timeoutMs = 1000; //1 second timeout
11579 uint8_t cmdStatusByte = 0;
11580
11581 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_RADIOON_OPCODE, 0, 0);
11582 if (retVal != MYKONOS_ERR_OK)
11583 {
11584 return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */
11585 }
11586
11587 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_RADIOON_OPCODE, timeoutMs, &cmdStatusByte);
11588 if (retVal != MYKONOS_ERR_OK)
11589 {
11590 if (cmdStatusByte > 0)
11591 {
11592 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOON_FAILED,
11593 getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOON_FAILED));
11594 return MYKONOS_ERR_ARM_RADIOON_FAILED;
11595 }
11596
11597 return retVal; /* Will return if timeout occurred */
11598 }
11599
11600 /* If ARM command error flag is 2, the command was not accepted, RUN_INIT must complete first */
11601 if (cmdStatusByte > 0)
11602 {
11603 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOON_FAILED, getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOON_FAILED));
11604 return MYKONOS_ERR_ARM_RADIOON_FAILED;
11605 }
11606
11607 return MYKONOS_ERR_OK;
11608 }
11609
11610 /**
11611 * \brief Instructs the ARM processor to move the radio state to the off state
11612 *
11613 * When the ARM moves from the Radio On state to Radio Off (Idle) the ARM tracking calibrations
11614 * are stopped and the TxEnable/RxEnable, etc GPIO control pins will be ignored. This will also
11615 * keep the receive and transmit chains powered down until the MYKONOS_radioOn() function
11616 * is called again.
11617 *
11618 * <B>Dependencies</B>
11619 * - device->spiSettings->chipSelectIndex
11620 *
11621 * \param device Pointer to the device settings structure
11622 *
11623 * \retval MYKONOS_ERR_OK Function completed successfully
11624 * \retval MYKONOS_ERR_ARM_RADIOOFF_FAILED ARM returned error running this command
11625 */
MYKONOS_radioOff(mykonosDevice_t * device)11626 mykonosErr_t MYKONOS_radioOff(mykonosDevice_t *device)
11627 {
11628 mykonosErr_t retVal = MYKONOS_ERR_OK;
11629 const uint8_t ABORTCAL_OPCODE = 0x00;
11630 uint32_t timeoutMs = 1000; //1 second timeout
11631 uint8_t cmdStatusByte = 0;
11632
11633 retVal = MYKONOS_sendArmCommand(device, ABORTCAL_OPCODE, 0, 0);
11634 if (retVal != MYKONOS_ERR_OK)
11635 {
11636 return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */
11637 }
11638
11639 retVal = MYKONOS_waitArmCmdStatus(device, ABORTCAL_OPCODE, timeoutMs, &cmdStatusByte);
11640 if (retVal != MYKONOS_ERR_OK)
11641 {
11642 if (cmdStatusByte > 0)
11643 {
11644 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOOFF_FAILED,
11645 getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOOFF_FAILED));
11646 return MYKONOS_ERR_ARM_RADIOOFF_FAILED;
11647 }
11648
11649 return retVal; /* Will return if timeout occurred */
11650 }
11651
11652 if (cmdStatusByte > 0)
11653 {
11654 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOOFF_FAILED, getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOOFF_FAILED));
11655 return MYKONOS_ERR_ARM_RADIOOFF_FAILED;
11656 }
11657
11658 return MYKONOS_ERR_OK;
11659 }
11660
11661 /**
11662 * \brief Reads the current ARM radio state
11663 *
11664 * Currently, *radioStatus only returns data in the lower 8 bits, but
11665 * is defined as a 32bit status to allow for more information to be returned
11666 * in the future.
11667 *
11668 * radioStatus | Bitfield
11669 * -------------|------------------
11670 * [1:0] | State[1:0], 0=POWERUP, 1=READY, 2=INIT, 3=RADIO ON
11671 * [3:2] | unused
11672 * [4] | TDD_nFDD , 1= TDD, 0=FDD
11673 * [7:5] | unused
11674 *
11675 * <B>Dependencies</B>
11676 * - device->spiSettings->chipSelectIndex
11677 *
11678 * \param device Pointer to the device settings structure
11679 * \param radioStatus The current ARM radio state is returned in this parameter
11680 *
11681 * \retval MYKONOS_ERR_OK Function completed successfully
11682 * \retval MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM Function parameter radioStatus has a NULL pointer
11683 */
MYKONOS_getRadioState(mykonosDevice_t * device,uint32_t * radioStatus)11684 mykonosErr_t MYKONOS_getRadioState(mykonosDevice_t *device, uint32_t *radioStatus)
11685 {
11686 uint8_t status = 0;
11687
11688 /* if radioStatus is not null */
11689 if (radioStatus != NULL)
11690 {
11691 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_0, &status);
11692 *radioStatus = (uint32_t)status;
11693 }
11694 else
11695 {
11696 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM,
11697 getMykonosErrorMessage(MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM));
11698 return MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM;
11699 }
11700
11701 return MYKONOS_ERR_OK;
11702 }
11703
11704 /**
11705 * \brief Sets which ARM tracking cals are enabled during the radioOn state.
11706 *
11707 * This command must be called during radioOff state. If called during radioOn,
11708 * an error will be returned. The enum mykonosTrackingCalibrations_t can be used to
11709 * OR together to form the enableMask parameter.
11710 *
11711 * enableMask | Bit description
11712 * ------------|------------
11713 * [0] | TRACK_RX1_QEC
11714 * [1] | TRACK_RX2_QEC
11715 * [2] | TRACK_ORX1_QEC
11716 * [3] | TRACK_ORX2_QEC
11717 * [4] | TRACK_TX1_LOL
11718 * [5] | TRACK_TX2_LOL
11719 * [6] | TRACK_TX1_QEC
11720 * [7] | TRACK_TX2_QEC
11721 * [8] | TRACK_TX1_DPD
11722 * [9] | TRACK_TX2_DPD
11723 * [10] | TRACK_TX1_CLGC
11724 * [11] | TRACK_TX2_CLGC
11725 * [12] | TRACK_TX1_VSWR
11726 * [13] | TRACK_TX2_VSWR
11727 * [16] | TRACK_ORX1_QEC_SNLO
11728 * [17] | TRACK_ORX2_QEC_SNLO
11729 * [18] | TRACK_SRX_QEC
11730 *
11731 *
11732 * <B>Dependencies</B>
11733 * - device->spiSettings->chipSelectIndex
11734 *
11735 * \param device Pointer to the device settings structure
11736 * \param enableMask A bitmask that selects which cals to run during radioOn state.
11737 *
11738 * \retval MYKONOS_ERR_OK Function completed successfully
11739 * \retval MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR Error: Tracking cals can only be enabled in the radioOff state.
11740 * \retval MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR ARM returned error when executing this command
11741 */
MYKONOS_enableTrackingCals(mykonosDevice_t * device,uint32_t enableMask)11742 mykonosErr_t MYKONOS_enableTrackingCals(mykonosDevice_t *device, uint32_t enableMask)
11743 {
11744 mykonosErr_t retVal = MYKONOS_ERR_OK;
11745 uint8_t armData[4] = {0, 0, 0, 0};
11746 uint8_t extData[4] = {MYKONOS_ARM_OBJECTID_CALSCHEDULER, 0x00, 0x00, 0x04}; //Target ARM Object ID, Offset LSB, Offset MSB, Length
11747 uint32_t timeoutMs = 0;
11748 uint8_t cmdStatusByte = 0;
11749 uint32_t radioStatus = 0;
11750 uint8_t allowTx1AttenUpdates = 0;
11751 uint8_t allowTx2AttenUpdates = 0;
11752
11753 #if (MYKONOS_VERBOSE == 1)
11754 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableTrackingCals()\n");
11755 #endif
11756
11757 /* read radio state to make sure ARM is in radioOff /IDLE */
11758 retVal = MYKONOS_getRadioState(device, &radioStatus);
11759 if (retVal != MYKONOS_ERR_OK)
11760 {
11761 return retVal;
11762 }
11763
11764 /* throw error if not in radioOff/IDLE state */
11765 if ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE)
11766 {
11767 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR,
11768 getMykonosErrorMessage(MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR));
11769 return MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR;
11770 }
11771
11772 /* In the ARM, DPD tracking and CLGC tracking share the same cal. Must
11773 * set extra enable bits in ARM Memory to tell which cal to run. */
11774 retVal = enableDpdTracking(device, ((enableMask & (uint32_t)TRACK_TX1_DPD) ? 1 : 0), ((enableMask & (uint32_t)TRACK_TX2_DPD) ? 1 : 0));
11775 if (retVal != MYKONOS_ERR_OK)
11776 {
11777 return retVal;
11778 }
11779
11780 if (((device->profilesValid & TX_PROFILE_VALID) > 0) && (device->tx->clgcConfig != NULL))
11781 {
11782 allowTx1AttenUpdates = device->tx->clgcConfig->allowTx1AttenUpdates;
11783 allowTx2AttenUpdates = device->tx->clgcConfig->allowTx2AttenUpdates;
11784 }
11785 else
11786 {
11787 allowTx1AttenUpdates = 0;
11788 allowTx2AttenUpdates = 0;
11789 }
11790
11791 retVal = enableClgcTracking(device, ((allowTx1AttenUpdates > 0) ? 1 : 0), ((allowTx2AttenUpdates > 0) ? 1 : 0));
11792 if (retVal != MYKONOS_ERR_OK)
11793 {
11794 return retVal;
11795 }
11796
11797 armData[0] = (uint8_t)(enableMask & 0xFF);
11798 armData[1] = (uint8_t)((enableMask >> 8) & 0xFF);
11799 armData[2] = (uint8_t)((enableMask >> 16) & 0xFF);
11800 armData[3] = (uint8_t)((enableMask >> 24) & 0xFF);
11801 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData));
11802 if (retVal != MYKONOS_ERR_OK)
11803 {
11804 return retVal;
11805 }
11806
11807 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_WRITECFG_OPCODE, &extData[0], sizeof(extData));
11808 if (retVal != MYKONOS_ERR_OK)
11809 {
11810 return retVal;
11811 }
11812
11813 timeoutMs = 1000;
11814 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_WRITECFG_OPCODE, timeoutMs, &cmdStatusByte);
11815 if (retVal != MYKONOS_ERR_OK)
11816 {
11817 if (cmdStatusByte > 0)
11818 {
11819 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR,
11820 getMykonosErrorMessage(MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR));
11821 return MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR;
11822 }
11823
11824 return retVal;
11825 }
11826
11827 if (cmdStatusByte > 0)
11828 {
11829 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR,
11830 getMykonosErrorMessage(MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR));
11831 return MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR;
11832 }
11833
11834 return MYKONOS_ERR_OK;
11835 }
11836
11837 /**
11838 * \brief Reschedules a tracking calibration to run. Can be used to
11839 * override the tracking calibration timer and force a tracking calibration to run.
11840 * Can be used to reschedule a tracking calibration after a tracking calibration
11841 * error has been detected. Only one tracking calibration object can be scheduled
11842 * per channel per function call.
11843 *
11844 * \pre Command can be called in either Radio On or Radio Off state. ARM must be
11845 * initialized.
11846 *
11847 * <B>Dependencies</B>
11848 * - device->spiSettings->chipSelectIndex
11849 *
11850 * \param device Pointer to the device settings structure
11851 * \param trackingCal Selects the tracking calibration to schedule.
11852 *
11853 * \retval MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV Not valid calibration passed
11854 * \retval MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG ARM error
11855 * \retval MYKONOS_ERR_OK Function completed successfully
11856 */
MYKONOS_rescheduleTrackingCal(mykonosDevice_t * device,mykonosTrackingCalibrations_t trackingCal)11857 mykonosErr_t MYKONOS_rescheduleTrackingCal(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal)
11858 {
11859 mykonosErr_t retVal = MYKONOS_ERR_OK;
11860 uint8_t extData[3] = {0};
11861 uint8_t cmdStatusByte = 0;
11862 uint32_t timeoutMs = 1000;
11863
11864 #if (MYKONOS_VERBOSE == 1)
11865 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_rescheduleTrackingCal()\n");
11866 #endif
11867
11868 switch (trackingCal)
11869 {
11870 case TRACK_RX1_QEC:
11871 extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING;
11872 extData[2] = 0;
11873 break;
11874
11875 case TRACK_RX2_QEC:
11876 extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING;
11877 extData[2] = 1;
11878 break;
11879
11880 case TRACK_ORX1_QEC:
11881 extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING;
11882 extData[2] = 0;
11883 break;
11884
11885 case TRACK_ORX2_QEC:
11886 extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING;
11887 extData[2] = 1;
11888 break;
11889
11890 case TRACK_TX1_LOL:
11891 extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING;
11892 extData[2] = 0;
11893 break;
11894
11895 case TRACK_TX2_LOL:
11896 extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING;
11897 extData[2] = 1;
11898 break;
11899
11900 case TRACK_TX1_QEC:
11901 extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING;
11902 extData[2] = 0;
11903 break;
11904
11905 case TRACK_TX2_QEC:
11906 extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING;
11907 extData[2] = 1;
11908 break;
11909
11910 case TRACK_TX1_DPD:
11911 extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG;
11912 extData[2] = 0;
11913 break;
11914
11915 case TRACK_TX2_DPD:
11916 extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG;
11917 extData[2] = 1;
11918 break;
11919
11920 case TRACK_TX1_CLGC:
11921 extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG;
11922 extData[2] = 0;
11923 break;
11924
11925 case TRACK_TX2_CLGC:
11926 extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG;
11927 extData[2] = 1;
11928 break;
11929
11930 case TRACK_TX1_VSWR:
11931 extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG;
11932 extData[2] = 0;
11933 break;
11934
11935 case TRACK_TX2_VSWR:
11936 extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG;
11937 extData[2] = 1;
11938 break;
11939
11940 default:
11941 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV,
11942 getMykonosErrorMessage(MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV));
11943 return MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV;
11944 }
11945
11946 extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_PENDING;
11947
11948 /* sending ARM command */
11949 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData));
11950 if (retVal != MYKONOS_ERR_OK)
11951 {
11952 return retVal;
11953 }
11954
11955 /* check for completion */
11956 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte);
11957 if (retVal != MYKONOS_ERR_OK)
11958 {
11959 if (cmdStatusByte > 0)
11960 {
11961 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG,
11962 getMykonosErrorMessage(MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG));
11963 return MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG;
11964 }
11965
11966 return retVal;
11967 }
11968
11969 if (cmdStatusByte > 0)
11970 {
11971 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG,
11972 getMykonosErrorMessage(MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG));
11973 return MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG;
11974 }
11975
11976 return retVal;
11977 }
11978
11979 /**
11980 * \brief Suspend or resume tracking calibrations in RADIO_ON.
11981 *
11982 * This function is used to suspend or resume active tracking calibrations based on the passed mask trackingCals.
11983 *
11984 * \pre Command can be called in Radio On.
11985 *
11986 * trackCals[bit] | Bit description
11987 * ----------------|------------
11988 * [0] | TRACK_RX1_QEC
11989 * [1] | TRACK_RX2_QEC
11990 * [2] | TRACK_ORX1_QEC
11991 * [3] | TRACK_ORX2_QEC
11992 * [4] | TRACK_TX1_LOL
11993 * [5] | TRACK_TX2_LOL
11994 * [6] | TRACK_TX1_QEC
11995 * [7] | TRACK_TX2_QEC
11996 * [8] | TRACK_TX1_DPD
11997 * [9] | TRACK_TX2_DPD
11998 * [10] | TRACK_TX1_CLGC
11999 * [11] | TRACK_TX2_CLGC
12000 * [12] | TRACK_TX1_VSWR
12001 * [13] | TRACK_TX2_VSWR
12002 *
12003 * <B>Dependencies</B>
12004 * - device->spiSettings->chipSelectIndex
12005 *
12006 * \param device Pointer to the device settings structure
12007 * \param trackCals Selects the tracking calibrations to suspend or resume during the radio ON state.
12008 * mykonosTrackingCalibrations_t enumerated types are or'd together to form the tracking calibration
12009 * mask word. If the bit is high the calibration will resume, if the bit is low the calibration will be suspended.
12010 *
12011 * \retval MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV Not valid calibration mask passed for trackCals
12012 * \retval MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG ARM error
12013 * \retval MYKONOS_ERR_OK Function completed successfully
12014 */
MYKONOS_setAllTrackCalState(mykonosDevice_t * device,uint32_t trackCals)12015 mykonosErr_t MYKONOS_setAllTrackCalState(mykonosDevice_t *device, uint32_t trackCals)
12016 {
12017 mykonosErr_t retVal = MYKONOS_ERR_OK;
12018 uint8_t cfgData[4] = {0};
12019 uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME, 0x0F, 0};
12020 uint8_t cmdStatusByte = 0;
12021 uint32_t enTrackCal = 0x00;
12022 uint32_t timeoutMs = 1000;
12023
12024 const uint32_t TRACKING_MASK = 0x3FFF;
12025
12026 #if (MYKONOS_VERBOSE == 1)
12027 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setAllTrackCalState()\n");
12028 #endif
12029
12030 /* reading enabled tracking calibrations */
12031 retVal = MYKONOS_getEnabledTrackingCals(device, &enTrackCal);
12032
12033 /* trackingCalMask check */
12034 if (((trackCals | enTrackCal) > enTrackCal) || (trackCals > TRACKING_MASK))
12035 {
12036 /* invalid cal mask error return, tracking cal not enable so we can not resume it */
12037 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV,
12038 getMykonosErrorMessage(MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV));
12039 return MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV;
12040 }
12041
12042 /* convert tracking mask to array of uint8_t type */
12043 cfgData[0] = (uint8_t)(trackCals & 0xFF);
12044 cfgData[1] = (uint8_t)((trackCals >> 8) & 0xFF);
12045 cfgData[2] = (uint8_t)((trackCals >> 16) & 0x0FF);
12046 cfgData[3] = (uint8_t)((trackCals >> 24) & 0xFF);
12047
12048 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &cfgData[0], sizeof(cfgData));
12049 if (retVal != MYKONOS_ERR_OK)
12050 {
12051 return retVal;
12052 }
12053
12054 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData));
12055 if (retVal != MYKONOS_ERR_OK)
12056 {
12057 return retVal;
12058 }
12059
12060 /* check for completion */
12061 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte);
12062 if (retVal != MYKONOS_ERR_OK)
12063 {
12064 if (cmdStatusByte > 0)
12065 {
12066 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG,
12067 getMykonosErrorMessage(MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG));
12068 return MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG;
12069 }
12070
12071 return retVal;
12072 }
12073
12074 if (cmdStatusByte > 0)
12075 {
12076 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG,
12077 getMykonosErrorMessage(MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG));
12078 return MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG;
12079 }
12080
12081 return retVal;
12082 }
12083
12084 /**
12085 * \brief Get the Suspended or Resumed state for tracking calibrations
12086 *
12087 * This function is used to get the suspend or resume state of all active tracking calibrations and the state is stored in trackCals.
12088 *
12089 * \pre Command can be called in Radio On.
12090 *
12091 * <B>Dependencies</B>
12092 * - device->spiSettings->chipSelectIndex
12093 *
12094 * \param device Pointer to the device settings structure
12095 * \param trackCals pointer to store the tracking calibration state.
12096 * If the bit is set then the tracking calibration is resumed and if not set then the tracking cal is suspended, the bit field follows:
12097 *
12098 * trackCals[bit] | Bit description
12099 * ---------------|------------
12100 * [0] | TRACK_RX1_QEC
12101 * [1] | TRACK_RX2_QEC
12102 * [2] | TRACK_ORX1_QEC
12103 * [3] | TRACK_ORX2_QEC
12104 * [4] | TRACK_TX1_LOL
12105 * [5] | TRACK_TX2_LOL
12106 * [6] | TRACK_TX1_QEC
12107 * [7] | TRACK_TX2_QEC
12108 * [8] | TRACK_TX1_DPD
12109 * [9] | TRACK_TX2_DPD
12110 * [10] | TRACK_TX1_CLGC
12111 * [11] | TRACK_TX2_CLGC
12112 * [12] | TRACK_TX1_VSWR
12113 * [13] | TRACK_TX2_VSWR
12114 *
12115 * \retval MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM Null parameter passed for trackCals
12116 * \retval MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG ARM error flag set.
12117 * \retval MYKONOS_ERR_GETSTATEALL_TRACK_ARMERROR ARM command error.
12118 * \retval MYKONOS_ERR_OK Function completed successfully
12119 */
MYKONOS_getAllTrackCalState(mykonosDevice_t * device,uint32_t * trackCals)12120 mykonosErr_t MYKONOS_getAllTrackCalState(mykonosDevice_t *device, uint32_t *trackCals)
12121 {
12122 mykonosErr_t retVal = MYKONOS_ERR_OK;
12123 uint8_t extData = MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME;
12124 uint8_t armData[4] = {0};
12125 uint8_t cmdStatusByte = 0;
12126 uint32_t timeoutMs = 1000;
12127
12128 #if (MYKONOS_VERBOSE == 1)
12129 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getAllTrackCalState()\n");
12130 #endif
12131
12132 /* Check for passed parameter */
12133 if (trackCals == NULL)
12134 {
12135 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM,
12136 getMykonosErrorMessage(MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM));
12137 return MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM;
12138 }
12139
12140 /* sending ARM command */
12141 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData, sizeof(extData));
12142 if (retVal != MYKONOS_ERR_OK)
12143 {
12144 return retVal;
12145 }
12146
12147 /* check for completion */
12148 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
12149 if (retVal != MYKONOS_ERR_OK)
12150 {
12151 if (cmdStatusByte > 0)
12152 {
12153 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG,
12154 getMykonosErrorMessage(MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG));
12155 return MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG;
12156 }
12157
12158 return retVal;
12159 }
12160
12161 if (cmdStatusByte > 0)
12162 {
12163 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG,
12164 getMykonosErrorMessage(MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG));
12165 return MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG;
12166 }
12167
12168 /* read 32-bit tracking state from ARM memory */
12169 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1);
12170 if (retVal != MYKONOS_ERR_OK)
12171 {
12172 return retVal;
12173 }
12174
12175 *trackCals = (uint32_t)armData[0] | ((uint32_t)armData[1] << 8) | ((uint32_t)armData[2] << 16) | ((uint32_t)armData[3] << 24);
12176
12177 return retVal;
12178 }
12179
12180 /**
12181 * \brief Suspend or resume individual tracking calibration
12182 *
12183 * \pre The tracking calibration must have been enabled with MYKONOS_enableTrackingCals(), this command can be called in Radio On.
12184 *
12185 * <B>Dependencies</B>
12186 * - device->spiSettings->chipSelectIndex
12187 *
12188 * \param device Pointer to the device settings structure
12189 * \param trackingCal Selects the tracking calibration to resume or suspend.
12190 * \param trackCalState if set then the selected tracking calibration will be resumed and if not set then the tracking cal will be suspended
12191 *
12192 * \retval MYKONOS_ERR_SETSTATE_TRACK_CAL_INV Not valid calibration passed
12193 * \retval MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG ARM error
12194 * \retval MYKONOS_ERR_OK Function completed successfully
12195 */
MYKONOS_setTrackingCalState(mykonosDevice_t * device,mykonosTrackingCalibrations_t trackingCal,uint8_t trackCalState)12196 mykonosErr_t MYKONOS_setTrackingCalState(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal, uint8_t trackCalState)
12197 {
12198 mykonosErr_t retVal = MYKONOS_ERR_OK;
12199 uint8_t extData[2] = {0};
12200 uint8_t cmdStatusByte = 0;
12201 uint8_t suspendTrack = 0x0F;
12202 uint32_t timeoutMs = 1000;
12203 uint32_t enTrackCal = 0x00;
12204
12205 const uint8_t CHANNEL_1 = 0x00;
12206 const uint8_t CHANNEL_2 = 0x10;
12207
12208 #if (MYKONOS_VERBOSE == 1)
12209 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setTrackingCalState()\n");
12210 #endif
12211
12212 if (trackCalState > 0)
12213 {
12214 suspendTrack = 0x2F;
12215 }
12216
12217 /* reading enabled tracking calibrations */
12218 retVal = MYKONOS_getEnabledTrackingCals(device, &enTrackCal);
12219 if (retVal != MYKONOS_ERR_OK)
12220 {
12221 return retVal;
12222 }
12223
12224 /* trackingCalMask check */
12225 if (((uint8_t)trackingCal & enTrackCal) != (uint8_t)trackingCal)
12226 {
12227 /* invalid cal mask error return, tracking cal not enable so we can not resume or suspend it */
12228 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATE_TRACK_CAL_INV,
12229 getMykonosErrorMessage(MYKONOS_ERR_SETSTATE_TRACK_CAL_INV));
12230 return MYKONOS_ERR_SETSTATE_TRACK_CAL_INV;
12231 }
12232
12233 switch (trackingCal)
12234 {
12235 case TRACK_RX1_QEC:
12236 extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING & suspendTrack;
12237 extData[1] |= CHANNEL_1;
12238 break;
12239
12240 case TRACK_RX2_QEC:
12241 extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING & suspendTrack;
12242 extData[1] |= CHANNEL_2;
12243 break;
12244
12245 case TRACK_ORX1_QEC:
12246 extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING & suspendTrack;
12247 extData[1] |= CHANNEL_1;
12248 break;
12249
12250 case TRACK_ORX2_QEC:
12251 extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING & suspendTrack;
12252 extData[1] |= CHANNEL_2;
12253 break;
12254
12255 case TRACK_TX1_LOL:
12256 extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING & suspendTrack;
12257 extData[1] |= CHANNEL_1;
12258 break;
12259
12260 case TRACK_TX2_LOL:
12261 extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING & suspendTrack;
12262 extData[1] |= CHANNEL_2;
12263 break;
12264
12265 case TRACK_TX1_QEC:
12266 extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING & suspendTrack;
12267 extData[1] |= CHANNEL_1;
12268 break;
12269
12270 case TRACK_TX2_QEC:
12271 extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING & suspendTrack;
12272 extData[1] |= CHANNEL_2;
12273 break;
12274
12275 case TRACK_TX1_DPD:
12276 extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG & suspendTrack;
12277 extData[1] |= CHANNEL_1;
12278 break;
12279
12280 case TRACK_TX2_DPD:
12281 extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG & suspendTrack;
12282 extData[1] |= CHANNEL_2;
12283 break;
12284
12285 case TRACK_TX1_CLGC:
12286 extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG & suspendTrack;
12287 extData[1] |= CHANNEL_1;
12288 break;
12289
12290 case TRACK_TX2_CLGC:
12291 extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG & suspendTrack;
12292 extData[1] |= CHANNEL_2;
12293 break;
12294
12295 case TRACK_TX1_VSWR:
12296 extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG & suspendTrack;
12297 extData[1] |= CHANNEL_1;
12298 break;
12299
12300 case TRACK_TX2_VSWR:
12301 extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG & suspendTrack;
12302 extData[1] |= CHANNEL_2;
12303 break;
12304
12305 default:
12306 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATE_TRACK_CAL_INV,
12307 getMykonosErrorMessage(MYKONOS_ERR_SETSTATE_TRACK_CAL_INV));
12308 return MYKONOS_ERR_SETSTATE_TRACK_CAL_INV;
12309 }
12310
12311 extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME;
12312
12313 /* sending ARM command */
12314 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData));
12315 if (retVal != MYKONOS_ERR_OK)
12316 {
12317 return retVal;
12318 }
12319
12320 /* check for completion */
12321 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte);
12322 if (retVal != MYKONOS_ERR_OK)
12323 {
12324 if (cmdStatusByte > 0)
12325 {
12326 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG,
12327 getMykonosErrorMessage(MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG));
12328 return MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG;
12329 }
12330 }
12331
12332 return retVal;
12333 }
12334
12335 /**
12336 * \brief Get the Suspended or Resumed state for individual tracking calibration
12337 *
12338 * \pre Command can be called in Radio On.
12339 *
12340 * <B>Dependencies</B>
12341 * - device->spiSettings->chipSelectIndex
12342 *
12343 * \param device Pointer to the device settings structure
12344 * \param trackingCal Selects the tracking calibration to get the resumed or suspended state.
12345 * \param trackCalState pointer to store the tracking calibration state,
12346 * if set then the selected tracking calibration is resumed and if not set then the tracking cal is suspended
12347 *
12348 * \retval MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM Null parameter passed to trackCalState
12349 * \retval MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG ARM command error flag set.
12350 * \retval MYKONOS_ERR_GETSTATE_TRACK_ARMERROR ARM command error.
12351 * \retval MYKONOS_ERR_OK Function completed successfully
12352 */
MYKONOS_getTrackingCalState(mykonosDevice_t * device,mykonosTrackingCalibrations_t trackingCal,uint8_t * trackCalState)12353 mykonosErr_t MYKONOS_getTrackingCalState(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal, uint8_t *trackCalState)
12354 {
12355 mykonosErr_t retVal = MYKONOS_ERR_OK;
12356 uint8_t extData = MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME;
12357 uint8_t armData[4] = {0};
12358 uint8_t cmdStatusByte = 0;
12359 uint32_t timeoutMs = 1000;
12360 uint32_t trackMask = 0x00;
12361
12362 #if (MYKONOS_VERBOSE == 1)
12363 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTrackingCalState()\n");
12364 #endif
12365
12366 /* Check for passed parameter */
12367 if (trackCalState == NULL)
12368 {
12369 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM,
12370 getMykonosErrorMessage(MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM));
12371 return MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM;
12372 }
12373
12374 /* sending ARM command */
12375 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData, sizeof(extData));
12376 if (retVal != MYKONOS_ERR_OK)
12377 {
12378 return retVal;
12379 }
12380
12381 /* check for completion */
12382 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
12383 if (retVal != MYKONOS_ERR_OK)
12384 {
12385 if (cmdStatusByte > 0)
12386 {
12387 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG,
12388 getMykonosErrorMessage(MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG));
12389 return MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG;
12390 }
12391
12392 return retVal;
12393 }
12394
12395 if (cmdStatusByte > 0)
12396 {
12397 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG,
12398 getMykonosErrorMessage(MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG));
12399 return MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG;
12400 }
12401
12402 /* read 32-bit tracking state from ARM memory */
12403 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1);
12404 if (retVal != MYKONOS_ERR_OK)
12405 {
12406 return retVal;
12407 }
12408
12409 trackMask = (uint32_t)armData[0] | ((uint32_t)armData[1] << 8) | ((uint32_t)armData[2] << 16) | ((uint32_t)armData[3] << 24);
12410
12411 if (trackMask & (uint32_t)trackingCal)
12412 {
12413 *trackCalState = 1;
12414 }
12415 else
12416 {
12417 *trackCalState = 0;
12418 }
12419
12420 return retVal;
12421 }
12422
12423 /**
12424 * \brief Reads back which ARM tracking cals are enabled
12425 *
12426 * enableMask | Bit description
12427 * ------------|----------------------
12428 * [0] | TRACK_RX1_QEC
12429 * [1] | TRACK_RX2_QEC
12430 * [2] | TRACK_ORX1_QEC
12431 * [3] | TRACK_ORX2_QEC
12432 * [4] | TRACK_TX1_LOL
12433 * [5] | TRACK_TX2_LOL
12434 * [6] | TRACK_TX1_QEC
12435 * [7] | TRACK_TX2_QEC
12436 * [8] | TRACK_TX1_DPD
12437 * [9] | TRACK_TX2_DPD
12438 * [10] | TRACK_TX1_CLGC
12439 * [11] | TRACK_TX2_CLGC
12440 * [12] | TRACK_TX1_VSWR
12441 * [13] | TRACK_TX2_VSWR
12442 * [16] | TRACK_ORX1_QEC_SNLO
12443 * [17] | TRACK_ORX1_QEC_SNLO
12444 * [18] | TRACK_SRX_QEC
12445 *
12446 * <B>Dependencies</B>
12447 * - device->spiSettings->chipSelectIndex
12448 *
12449 * \param device Pointer to the device settings structure
12450 * \param enableMask Returned bitmask that shows which tracking cals are enabled
12451 * to run during radioOn state. See mykonosTrackingCalibrations_t enum of tracking cals.
12452 *
12453 * \retval MYKONOS_ERR_OK Function completed successfully
12454 */
MYKONOS_getEnabledTrackingCals(mykonosDevice_t * device,uint32_t * enableMask)12455 mykonosErr_t MYKONOS_getEnabledTrackingCals(mykonosDevice_t *device, uint32_t *enableMask)
12456 {
12457 mykonosErr_t retVal = MYKONOS_ERR_OK;
12458 uint8_t armData[4] = {0};
12459
12460 #if (MYKONOS_VERBOSE == 1)
12461 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getEnabledTrackingCals()\n");
12462 #endif
12463
12464 /* Ask ARM to read tracking cal enable bits and place in mailbox buffer memory */
12465 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CALSCHEDULER, 0, &armData[0], 4);
12466 if (retVal != MYKONOS_ERR_OK)
12467 {
12468 return retVal;
12469 }
12470
12471 *enableMask = ((uint32_t)(armData[0]) | ((uint32_t)(armData[1]) << 8) | ((uint32_t)(armData[2]) << 16) | ((uint32_t)(armData[3]) << 24));
12472
12473 return MYKONOS_ERR_OK;
12474 }
12475
12476 /**
12477 * \brief Returns the tracking calibration pending and error status.
12478 *
12479 * When in radioOn state, the enabled tracking calibrations will set the pending
12480 * flag when the particular calibration is ready to be run, but has not completed
12481 * yet. For Tx tracking cals to complete, the BBIC must set the ObsRx path to
12482 * the INTERNAL CALS mode. If a tracking calibration had an error, the corresponding
12483 * error flag will be asserted.
12484 *
12485 * pendingCalMask | bit Description
12486 * ----------------|--------------------------------------------------------
12487 * [0] | Rx1 QEC tracking pending
12488 * [1] | Rx1 QEC tracking error
12489 * [2] | Rx2 QEC tracking pending
12490 * [3] | Rx2 QEC tracking error
12491 * [4] | ORx1 QEC tracking pending
12492 * [5] | ORx1 QEC tracking error
12493 * [6] | ORx2 QEC tracking pending
12494 * [7] | ORx2 QEC tracking error
12495 * [8] | Tx1 LOL tracking pending
12496 * [9] | Tx1 LOL tracking error
12497 * [10] | Tx2 LOL tracking pending
12498 * [11] | Tx2 LOL tracking error
12499 * [12] | Tx1 QEC tracking pending
12500 * [13] | Tx1 QEC tracking error
12501 * [14] | Tx2 QEC tracking pending
12502 * [15] | Tx2 QEC tracking error
12503 * [16] | Tx1 DPD tracking pending
12504 * [17] | Tx1 DPD tracking error
12505 * [18] | Tx2 DPD tracking pending
12506 * [19] | Tx2 DPD tracking error
12507 * [20] | Tx1 CLGC tracking pending
12508 * [21] | Tx1 CLGC tracking error
12509 * [22] | Tx2 CLGC tracking pending
12510 * [23] | Tx2 CLGC tracking error
12511 * [24] | Tx1 VSWR tracking pending
12512 * [25] | Tx1 VSWR tracking error
12513 * [26] | Tx2 VSWR tracking pending
12514 * [27] | Tx2 VSWR tracking error
12515 *
12516 * <B>Dependencies</B>
12517 * - device->spiSettings->chipSelectIndex
12518 *
12519 * \param device Pointer to the device settings structure
12520 * \param pendingCalMask Bit mask that describes which tracking cals are pending
12521 * or had errors
12522 *
12523 * \retval MYKONOS_ERR_OK Function completed successfully
12524 * \retval MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM Function parameter pendingCalMask is a NULL pointer
12525 */
MYKONOS_getPendingTrackingCals(mykonosDevice_t * device,uint32_t * pendingCalMask)12526 mykonosErr_t MYKONOS_getPendingTrackingCals(mykonosDevice_t *device, uint32_t *pendingCalMask)
12527 {
12528 uint8_t readData[4] = {0};
12529
12530 #if (MYKONOS_VERBOSE == 1)
12531 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getPendingTrackingCals()\n");
12532 #endif
12533
12534 if (pendingCalMask == NULL)
12535 {
12536 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM,
12537 getMykonosErrorMessage(MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM));
12538 return MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM;
12539 }
12540
12541 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_3, &readData[0]);
12542 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_4, &readData[1]);
12543 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_5, &readData[2]);
12544 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_6, &readData[3]);
12545 *pendingCalMask = ((uint32_t)readData[3] << 24) | ((uint32_t)readData[2] << 16) | ((uint32_t)readData[1] << 8) | ((uint32_t)readData[0]);
12546
12547 return MYKONOS_ERR_OK;
12548 }
12549
12550 /**
12551 * \brief Returns the status of the TxLOL external tracking calibration
12552 *
12553 * The Tx LOL external tracking calibration is run during the radioOn state.
12554 * The function can be called to read back the status of the TxLOL external
12555 * calibration including metrics like error codes, percentage of data
12556 * collected for current cal, the performance of the cal and the number of
12557 * times the cal has run and updated the hardware.
12558 *
12559 * \pre Before the function is called, the device must be initialized, the ARM
12560 * loaded, and init cals run. These functions can be called in radioOff or
12561 * radioOn state.
12562 *
12563 * \param device Pointer to the device settings structure
12564 * \param txChannel The channel (Tx1/Tx2) whose status is to be read back
12565 * \param txLolStatus Status of the TxLOL external calibration, as a structure
12566 * of type mykonosTxLolStatus_t is returned to this pointer address
12567 *
12568 * \retval MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM Function parameter mykonosTxLolStatus_t is a NULL pointer
12569 * \retval MYKONOS_ERR_GETTXLOLSTATUS_INV_CH Channel selection not valid
12570 * \retval MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG ARM command error
12571 * \retval MYKONOS_ERR_OK Function completed successfully
12572 */
MYKONOS_getTxLolStatus(mykonosDevice_t * device,mykonosTxChannels_t txChannel,mykonosTxLolStatus_t * txLolStatus)12573 mykonosErr_t MYKONOS_getTxLolStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosTxLolStatus_t *txLolStatus)
12574 {
12575 uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_TXLOL_TRACKING, 0};
12576 uint8_t cmdStatusByte = 0;
12577 uint32_t offset = 0;
12578 uint32_t timeoutMs = 0;
12579 uint8_t armReadBack[20] = {0};
12580 mykonosErr_t retVal = MYKONOS_ERR_OK;
12581
12582 #if (MYKONOS_VERBOSE == 1)
12583 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTxLolStatus()\n");
12584 #endif
12585
12586 if (txLolStatus == NULL)
12587 {
12588 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM,
12589 getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM));
12590 return MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM;
12591 }
12592
12593 switch (txChannel)
12594 {
12595 case TX1:
12596 extData[2] = 0;
12597 break;
12598 case TX2:
12599 extData[2] = 1;
12600 break;
12601 default:
12602 {
12603 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_INV_CH,
12604 getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_INV_CH));
12605 return MYKONOS_ERR_GETTXLOLSTATUS_INV_CH;
12606 }
12607 }
12608
12609 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
12610 if (retVal != MYKONOS_ERR_OK)
12611 {
12612 return retVal;
12613 }
12614
12615 timeoutMs = 1000;
12616 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
12617 if (retVal != MYKONOS_ERR_OK)
12618 {
12619 if (cmdStatusByte > 0)
12620 {
12621 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG,
12622 getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG));
12623 return MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG;
12624 }
12625
12626 return retVal;
12627 }
12628
12629 if (cmdStatusByte > 0)
12630 {
12631 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG,
12632 getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG));
12633 return MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG;
12634 }
12635
12636 /* read status from ARM memory */
12637 offset = 0;
12638 retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1);
12639 if (retVal != MYKONOS_ERR_OK)
12640 {
12641 return retVal;
12642 }
12643
12644 /* Assign to data structure */
12645 txLolStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]);
12646 txLolStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8)
12647 | ((uint32_t)armReadBack[4]);
12648 txLolStatus->performanceMetric = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8)
12649 | ((uint32_t)armReadBack[8]);
12650 txLolStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8) | ((uint32_t)armReadBack[12]);
12651 txLolStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8)
12652 | ((uint32_t)armReadBack[16]);
12653
12654 return MYKONOS_ERR_OK;
12655 }
12656
12657 /**
12658 * \brief Returns the status of the TxQEC tracking calibration
12659 *
12660 * The Tx QEC tracking calibration is run during the radioOn state.
12661 * The function can be called to read back the status of the TxQEC
12662 * calibration including metrics like error codes, percentage of data
12663 * collected for current cal, the performance of the cal and the number of
12664 * times the cal has run and updated the hardware.
12665 *
12666 * \pre Before the function is called, the device must be initialized, the ARM
12667 * loaded, and init cals run. These functions can be called in radioOff or
12668 * radioOn state.
12669 *
12670 * \param device Pointer to the device settings structure
12671 * \param txChannel The channel (Tx1/Tx2) whose status is to be read back
12672 * \param txQecStatus Status of the TxQEC external calibration, as a structure
12673 * of type mykonosTxQecStatus_t is returned to this pointer address
12674 *
12675 * \retval MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM Function parameter txQecStatus is a NULL pointer
12676 * \retval MYKONOS_ERR_GETTXQECSTATUS_INV_CH Channel selection not valid
12677 * \retval MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG ARM command error
12678 * \retval MYKONOS_ERR_OK Function completed successfully
12679 */
MYKONOS_getTxQecStatus(mykonosDevice_t * device,mykonosTxChannels_t txChannel,mykonosTxQecStatus_t * txQecStatus)12680 mykonosErr_t MYKONOS_getTxQecStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosTxQecStatus_t *txQecStatus)
12681 {
12682 uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_TXQEC_TRACKING, 0};
12683 uint8_t cmdStatusByte = 0;
12684 uint32_t offset = 0;
12685 uint32_t timeoutMs = 0;
12686 uint8_t armReadBack[20] = {0};
12687 mykonosErr_t retVal = MYKONOS_ERR_OK;
12688
12689 #if (MYKONOS_VERBOSE == 1)
12690 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTxQecStatus()\n");
12691 #endif
12692
12693 if (txQecStatus == NULL)
12694 {
12695 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM,
12696 getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM));
12697 return MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM;
12698 }
12699
12700 switch (txChannel)
12701 {
12702 case TX1:
12703 extData[2] = 0;
12704 break;
12705 case TX2:
12706 extData[2] = 1;
12707 break;
12708 default:
12709 {
12710 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_INV_CH,
12711 getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_INV_CH));
12712 return MYKONOS_ERR_GETTXQECSTATUS_INV_CH;
12713 }
12714 }
12715
12716 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
12717 if (retVal != MYKONOS_ERR_OK)
12718 {
12719 return retVal;
12720 }
12721
12722 timeoutMs = 1000;
12723 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
12724 if (retVal != MYKONOS_ERR_OK)
12725 {
12726 if (cmdStatusByte > 0)
12727 {
12728 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG,
12729 getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG));
12730 return MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG;
12731 }
12732
12733 return retVal;
12734 }
12735
12736 if (cmdStatusByte > 0)
12737 {
12738 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG,
12739 getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG));
12740 return MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG;
12741 }
12742
12743 /* read status from ARM memory */
12744 offset = 0;
12745 retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1);
12746 if (retVal != MYKONOS_ERR_OK)
12747 {
12748 return retVal;
12749 }
12750
12751 /* Assign to data structure */
12752 txQecStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]);
12753 txQecStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8)
12754 | ((uint32_t)armReadBack[4]);
12755 txQecStatus->performanceMetric = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8)
12756 | ((uint32_t)armReadBack[8]);
12757 txQecStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8) | ((uint32_t)armReadBack[12]);
12758 txQecStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8)
12759 | ((uint32_t)armReadBack[16]);
12760
12761 return MYKONOS_ERR_OK;
12762 }
12763
12764 /**
12765 * \brief Returns the status of the RxQEC tracking calibration
12766 *
12767 * The Rx QEC tracking calibration is run during the radioOn state.
12768 * The function can be called to read back the status of the RxQEC external
12769 * calibration including metrics like error codes, percentage of data
12770 * collected for current cal, the performance of the cal and the number of
12771 * times the cal has run and updated the hardware.
12772 *
12773 * \pre Before the function is called, the device must be initialized, the ARM
12774 * loaded, and init cals run. These functions can be called in radioOff or
12775 * radioOn state.
12776 *
12777 * \param device Pointer to the device settings structure
12778 * \param rxChannel The channel (Rx1/Rx2) whose status is to be read back
12779 * \param rxQecStatus Status of the RxQEC calibration, as a structure
12780 * of type mykonosRxQecStatus_t is returned to this pointer address
12781 *
12782 * \retval MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM Function parameter rxQecStatus is a NULL pointer
12783 * \retval MYKONOS_ERR_GETRXQECSTATUS_INV_CH Channel selection not valid
12784 * \retval MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG ARM command error
12785 * \retval MYKONOS_ERR_OK Function completed successfully
12786 */
MYKONOS_getRxQecStatus(mykonosDevice_t * device,mykonosRxChannels_t rxChannel,mykonosRxQecStatus_t * rxQecStatus)12787 mykonosErr_t MYKONOS_getRxQecStatus(mykonosDevice_t *device, mykonosRxChannels_t rxChannel, mykonosRxQecStatus_t *rxQecStatus)
12788 {
12789 uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_RXQEC_TRACKING, 0};
12790 uint8_t cmdStatusByte = 0;
12791 uint32_t offset = 0;
12792 uint32_t timeoutMs = 0;
12793 uint8_t armReadBack[20] = {0};
12794 mykonosErr_t retVal = MYKONOS_ERR_OK;
12795
12796 #if (MYKONOS_VERBOSE == 1)
12797 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRxQecStatus()\n");
12798 #endif
12799
12800 if (rxQecStatus == NULL)
12801 {
12802 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM,
12803 getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM));
12804 return MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM;
12805 }
12806
12807 switch (rxChannel)
12808 {
12809 case RX1:
12810 extData[2] = 0;
12811 break;
12812 case RX2:
12813 extData[2] = 1;
12814 break;
12815 default:
12816 {
12817 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_INV_CH,
12818 getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_INV_CH));
12819 return MYKONOS_ERR_GETRXQECSTATUS_INV_CH;
12820 }
12821 }
12822
12823 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
12824 if (retVal != MYKONOS_ERR_OK)
12825 {
12826 return retVal;
12827 }
12828
12829 timeoutMs = 1000;
12830 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
12831 if (retVal != MYKONOS_ERR_OK)
12832 {
12833 if (cmdStatusByte > 0)
12834 {
12835 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG,
12836 getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG));
12837 return MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG;
12838 }
12839
12840 return retVal;
12841 }
12842
12843 if (cmdStatusByte > 0)
12844 {
12845 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG,
12846 getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG));
12847 return MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG;
12848 }
12849
12850 /* read status from ARM memory */
12851 offset = 0;
12852 retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1);
12853 if (retVal != MYKONOS_ERR_OK)
12854 {
12855 return retVal;
12856 }
12857
12858 /* Assign to data structure */
12859 rxQecStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]);
12860 rxQecStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8)
12861 | ((uint32_t)armReadBack[4]);
12862 rxQecStatus->selfcheckIrrDb = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8)
12863 | ((uint32_t)armReadBack[8]);
12864 rxQecStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8) | ((uint32_t)armReadBack[12]);
12865 rxQecStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8)
12866 | ((uint32_t)armReadBack[16]);
12867
12868 return MYKONOS_ERR_OK;
12869 }
12870
12871 /**
12872 * \brief Returns the status of the ORxQEC tracking calibration
12873 *
12874 * The ORx QEC tracking calibration is run during the radioOn state.
12875 * The function can be called to read back the status of the ORxQEC external
12876 * calibration including metrics like error codes, percentage of data
12877 * collected for current cal, the performance of the cal and the number of
12878 * times the cal has run and updated the hardware.
12879 *
12880 * \pre Before the function is called, the device must be initialized, the ARM
12881 * loaded, and init cals run. These functions can be called in radioOff or
12882 * radioOn state.
12883 *
12884 * \param device Pointer to the device settings structure
12885 * \param orxChannel The channel whose status is to be read back
12886 * \param orxQecStatus Status of the ORxQEC external calibration, as a structure
12887 * of type mykonosOrxQecStatus_t is returned to this pointer address
12888 *
12889 * \retval MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM Function parameter orxQecStatus is a NULL pointer
12890 * \retval MYKONOS_ERR_GETORXQECSTATUS_INV_CH Channel selection not valid
12891 * \retval MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG ARM command error
12892 * \retval MYKONOS_ERR_OK Function completed successfully
12893 */
MYKONOS_getOrxQecStatus(mykonosDevice_t * device,mykonosObsRxChannels_t orxChannel,mykonosOrxQecStatus_t * orxQecStatus)12894 mykonosErr_t MYKONOS_getOrxQecStatus(mykonosDevice_t *device, mykonosObsRxChannels_t orxChannel, mykonosOrxQecStatus_t *orxQecStatus)
12895 {
12896 uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING, 0};
12897 uint8_t cmdStatusByte = 0;
12898 uint32_t offset = 0;
12899 uint32_t timeoutMs = 0;
12900 uint8_t armReadBack[20] = {0};
12901 mykonosErr_t retVal = MYKONOS_ERR_OK;
12902
12903 #if (MYKONOS_VERBOSE == 1)
12904 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getOrxQecStatus()\n");
12905 #endif
12906
12907 if (orxQecStatus == NULL)
12908 {
12909 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM,
12910 getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM));
12911 return MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM;
12912 }
12913
12914 switch (orxChannel)
12915 {
12916 case OBS_RX1_TXLO:
12917 case OBS_RX1_SNIFFERLO:
12918 extData[2] = 0;
12919 break;
12920 case OBS_RX2_TXLO:
12921 case OBS_RX2_SNIFFERLO:
12922 extData[2] = 1;
12923 break;
12924 default:
12925 {
12926 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_INV_CH,
12927 getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_INV_CH));
12928 return MYKONOS_ERR_GETORXQECSTATUS_INV_CH;
12929 }
12930 }
12931
12932 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
12933 if (retVal != MYKONOS_ERR_OK)
12934 {
12935 return retVal;
12936 }
12937
12938 timeoutMs = 1000;
12939 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
12940 if (retVal != MYKONOS_ERR_OK)
12941 {
12942 if (cmdStatusByte > 0)
12943 {
12944 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG,
12945 getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG));
12946 return MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG;
12947 }
12948
12949 return retVal;
12950 }
12951
12952 if (cmdStatusByte > 0)
12953 {
12954 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG,
12955 getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG));
12956 return MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG;
12957 }
12958
12959 /* read status from ARM memory */
12960 offset = 0;
12961 retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1);
12962 if (retVal != MYKONOS_ERR_OK)
12963 {
12964 return retVal;
12965 }
12966
12967 /* Assign to data structure */
12968 orxQecStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]);
12969 orxQecStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8)
12970 | ((uint32_t)armReadBack[4]);
12971 orxQecStatus->selfcheckIrrDb = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8)
12972 | ((uint32_t)armReadBack[8]);
12973 orxQecStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8)
12974 | ((uint32_t)armReadBack[12]);
12975 orxQecStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8)
12976 | ((uint32_t)armReadBack[16]);
12977
12978 return MYKONOS_ERR_OK;
12979 }
12980
12981 /**
12982 * \brief Selects the Sniffer RF input to use for the observation receiver when in ObsRx pin mode and ORX_MODE = SNIFFER(4)
12983 *
12984 * This function is only valid when using the ObsRx Pin mode. In pin mode, 3 GPIO pins select an Observation Rx source.
12985 * See mykonosObsRxChannels_t enum values less than 7. When the ORX_MODE GPIO pins are set to 4 for Sniffer, Sniffer inputs
12986 * A, B, and C can be chosen by calling this function. This function can be called any time after the ARM is loaded and running.
12987 * It can be called in radioOn or radioOff state.
12988 *
12989 * <B>Dependencies</B>
12990 * - device->spiSettings->chipSelectIndex
12991 *
12992 * \param device Pointer to the device settings structure
12993 * \param snifferChannel Desired channel to set. This channel will be enabled when ORX_MODE = SNIFFER.
12994 *
12995 * \retval MYKONOS_ERR_OK Function completed successfully
12996 * \retval MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR ARM returned an error
12997 */
MYKONOS_setSnifferChannel(mykonosDevice_t * device,mykonosSnifferChannel_t snifferChannel)12998 mykonosErr_t MYKONOS_setSnifferChannel(mykonosDevice_t *device, mykonosSnifferChannel_t snifferChannel)
12999 {
13000 uint8_t armData[2] = {0};
13001 uint32_t timeoutMs = 0;
13002 uint8_t cmdStatusByte = 0;
13003 mykonosErr_t retVal = MYKONOS_ERR_OK;
13004
13005 armData[0] = 0x6A; /* SET SRX_SOURCE ARM object ID */
13006 armData[1] = (uint8_t)snifferChannel;
13007
13008 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &armData[0], sizeof(armData));
13009 if (retVal != MYKONOS_ERR_OK)
13010 {
13011 return retVal;
13012 }
13013
13014 timeoutMs = 1000;
13015 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte);
13016 if (retVal != MYKONOS_ERR_OK)
13017 {
13018 if (cmdStatusByte > 0)
13019 {
13020 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR,
13021 getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR));
13022 retVal = (mykonosErr_t)MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR;
13023 }
13024
13025 return retVal;
13026 }
13027
13028 if (cmdStatusByte > 0)
13029 {
13030 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR,
13031 getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR));
13032 return (mykonosErr_t)MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR;
13033 }
13034
13035 return MYKONOS_ERR_OK;
13036 }
13037
13038 /**
13039 * \brief Resets the ARM processor and performs initialization
13040 *
13041 * Sets ARM Run = 0, Disables parity checks, sets ARM and SPI reg clock selects,
13042 * resets ARM, and enables ARM SPI register access
13043 *
13044 * <B>Dependencies</B>
13045 * - device->spiSettings->chipSelectIndex
13046 * - device->rx->rxProfile->iqRate_kHz
13047 * - device->deviceClock_kHz
13048 * - device->rx->rxProfile->rfBandwidth_Hz
13049 * - device->tx->txProfile->rfBandwidth_Hz
13050 * - device->rx->rxProfile->rxFirDecimation
13051 * - device->rx->rxProfile->rhb1Decimation
13052 * - device->spiSettings
13053 *
13054 * \param device Pointer to the device settings structure
13055 *
13056 * \retval MYKONOS_ERR_OK Function completed successfully
13057 * \retval MYKONOS_ERR_INITARM_INV_VCODIV
13058 * \retval MYKONOS_ERR_INITARM_INV_REGCLK Could not calculate a valid ARM Register clock divider
13059 * \retval MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM Could not calculate a valid ARM clock divider
13060 */
MYKONOS_initArm(mykonosDevice_t * device)13061 mykonosErr_t MYKONOS_initArm(mykonosDevice_t *device)
13062 {
13063 uint8_t regClkSel = 0;
13064 uint8_t armClkSel = 0;
13065 uint32_t hsClkRateDiv4or5_Khz = 0;
13066 uint32_t hb1Clk = 0;
13067 uint32_t vcoDivTimes10 = 1;
13068 uint8_t adcDiv = 0;
13069 mykonosErr_t retVal = MYKONOS_ERR_OK;
13070
13071 #if (MYKONOS_VERBOSE == 1)
13072 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_initArm()\n");
13073 #endif
13074
13075 /* Finish init - this is part of init that must run after Multi Chip Sync */
13076 retVal = MYKONOS_initSubRegisterTables(device);
13077 if (retVal != MYKONOS_ERR_OK)
13078 {
13079 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal));
13080 return retVal;
13081 }
13082
13083 switch (device->clocks->clkPllVcoDiv)
13084 {
13085 case VCODIV_1:
13086 vcoDivTimes10 = 10;
13087 break;
13088 case VCODIV_1p5:
13089 vcoDivTimes10 = 15;
13090 break;
13091 case VCODIV_2:
13092 vcoDivTimes10 = 20;
13093 break;
13094 case VCODIV_3:
13095 vcoDivTimes10 = 30;
13096 break;
13097 default:
13098 {
13099 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITARM_INV_VCODIV,
13100 getMykonosErrorMessage(MYKONOS_ERR_INITARM_INV_VCODIV));
13101 return MYKONOS_ERR_INITARM_INV_VCODIV;
13102 }
13103 }
13104
13105 hsClkRateDiv4or5_Khz = device->clocks->clkPllVcoFreq_kHz * 10 / vcoDivTimes10 / 20;
13106
13107 /* If ADC divider is set, divide hsClkRateDiv4or5_kHz by 2 (ADC divider) */
13108 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_1, &adcDiv, 0x01, 0);
13109 hb1Clk = (adcDiv == 1) ? (hsClkRateDiv4or5_Khz >> 1) : (hsClkRateDiv4or5_Khz);
13110
13111 /* the ARM clock should not exceed 250 Mhz */
13112 if (hb1Clk <= 250000)
13113 {
13114 armClkSel = 0x00;
13115 }
13116 else if (hb1Clk > 250000 && hb1Clk <= 500000)
13117 {
13118 armClkSel = 0x02;
13119 }
13120 else if (hb1Clk > 500000 && hb1Clk <= 1000000)
13121 {
13122 armClkSel = 0x04;
13123 }
13124 else
13125 {
13126 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM,
13127 getMykonosErrorMessage(MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM));
13128 return MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM;
13129 }
13130
13131 /* the SPI read reg clock must be equal or less than 100MHz and the SPI write reg clock must be less equal or less than 200 Mhz*/
13132 if (hb1Clk <= 100000)
13133 {
13134 regClkSel = 0x00;
13135 }
13136 else if (hb1Clk > 100000 && hb1Clk <= 200000)
13137 {
13138 regClkSel = 0x04;
13139 }
13140 else if (hb1Clk > 200000 && hb1Clk <= 400000)
13141 {
13142 regClkSel = 0x09;
13143 }
13144 else if (hb1Clk > 400000 && hb1Clk <= 800000)
13145 {
13146 regClkSel = 0x0E;
13147 }
13148 else
13149 {
13150 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITARM_INV_REGCLK, getMykonosErrorMessage(MYKONOS_ERR_INITARM_INV_REGCLK));
13151 return MYKONOS_ERR_INITARM_INV_REGCLK;
13152 }
13153
13154 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8C); /* arm_debug_enable[7]=1, mem_hresp_mask[3]=1, auto_incr[2]=1, arm_m3_run[0]=0 */
13155 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CLK_CTL, armClkSel |= 0x41); /* setting the ARM clock rate, resetting the PC, and enabling the ARM clock */
13156 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CLK_CTL, armClkSel &= ~0x40); /* maintaining the ARM clock rate, disabling the PC reset, and maintaining ARM clock enable */
13157 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BRIDGE_CLK_CTL, regClkSel); /* setting the SPI read and write clock rates */
13158 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AHB_SPI_BRIDGE, 0x13); /* blockout_window_size[4:1] = 9, ahb_spi_bridge_enable[0] = 1 */
13159
13160 retVal = MYKONOS_writeArmProfile(device);
13161 if (retVal != MYKONOS_ERR_OK)
13162 {
13163 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal));
13164 return retVal;
13165 }
13166
13167 retVal = MYKONOS_loadAdcProfiles(device);
13168 if (retVal != MYKONOS_ERR_OK)
13169 {
13170 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal));
13171 return retVal;
13172 }
13173
13174 return MYKONOS_ERR_OK;
13175 }
13176
13177 /**
13178 * \brief Loads binary byte array into ARM program memory
13179 *
13180 * This function assumes the ARM auto increment bit is set in 0x0D00[2]. Valid memory
13181 * addresses are: Program Memory (0x01000000 - 0x01017FFF)
13182 *
13183 * <B>Dependencies</B>
13184 * - device->spiSettings->chipSelectIndex
13185 * - device->spiSettings
13186 *
13187 * \param device is structure pointer to the Mykonos data structure containing settings
13188 * \param binary is a byte array containing ARM program memory data bytes (directly from .bin file)
13189 * \param count is the number of bytes in the byte array
13190 *
13191 * \retval MYKONOS_ERR_OK Function completed successfully
13192 * \retval MYKONOS_ERR_LOADBIN_NULL_PARAM Function parameter binary has a NULL pointer
13193 * \retval MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT Count parameter must be 98304 bytes
13194 */
MYKONOS_loadArmFromBinary(mykonosDevice_t * device,uint8_t * binary,uint32_t count)13195 mykonosErr_t MYKONOS_loadArmFromBinary(mykonosDevice_t *device, uint8_t *binary, uint32_t count)
13196 {
13197 mykonosErr_t retVal = MYKONOS_ERR_OK;
13198 uint8_t stackPtr[4] = {0};
13199 uint8_t bootAddr[4] = {0};
13200
13201 #if (MYKONOS_VERBOSE == 1)
13202 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_loadArmFromBinary()\n");
13203 #endif
13204
13205 if (binary == NULL)
13206 {
13207 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADBIN_NULL_PARAM, getMykonosErrorMessage(MYKONOS_ERR_LOADBIN_NULL_PARAM));
13208 return MYKONOS_ERR_LOADBIN_NULL_PARAM;
13209 }
13210
13211 if (count != 98304)
13212 {
13213 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT,
13214 getMykonosErrorMessage(MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT));
13215 return MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT;
13216 }
13217 else
13218 {
13219 /* extraction of stack pointer and boot address from top of array */
13220 stackPtr[0] = binary[0];
13221 stackPtr[1] = binary[1];
13222 stackPtr[2] = binary[2];
13223 stackPtr[3] = binary[3];
13224
13225 bootAddr[0] = binary[4];
13226 bootAddr[1] = binary[5];
13227 bootAddr[2] = binary[6];
13228 bootAddr[3] = binary[7];
13229
13230 /* writing binary data to ARM memory */
13231 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR, &binary[0], count);
13232 }
13233
13234 if (retVal != MYKONOS_ERR_OK)
13235 {
13236 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal));
13237 return retVal;
13238 }
13239 else
13240 {
13241 /* writing the stack pointer address */
13242 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_0, stackPtr[0]); /* stack pointer [7:0] */
13243 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_1, stackPtr[1]); /* stack pointer [15:8] */
13244 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_2, stackPtr[2]); /* stack pointer [23:16] */
13245 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_3, stackPtr[3]); /* stack pointer [31:24] */
13246
13247 /* writing the boot address */
13248 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_0, bootAddr[0]); /* boot address [7:0] */
13249 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_1, bootAddr[1]); /* boot address [15:8] */
13250 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_2, bootAddr[2]); /* boot address [23:16] */
13251 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_3, bootAddr[3]); /* boot address [31:24] */
13252
13253 /* setting the ARM run bit */
13254 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8D); /* arm_debug_enable[7]=1, mem_hresp_mask[3]=1, auto_incr[2]=1, arm_m3_run[0]=1 */
13255 }
13256
13257 /* verifying ARM checksum */
13258 if ((retVal = MYKONOS_verifyArmChecksum(device)) != MYKONOS_ERR_OK)
13259 {
13260 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal));
13261 return retVal;
13262 }
13263
13264 /* verifying ARM state is in MYKONOS_ARM_READY state, otherwise return error */
13265 if ((retVal = MYKONOS_checkArmState(device, MYK_ARM_READY)) != MYKONOS_ERR_OK)
13266 {
13267 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal));
13268 return retVal;
13269 }
13270
13271 /* Setup ARM GPIO pins and program ARMs radio control structure */
13272 if ((retVal = (mykonosErr_t)MYKONOS_setArmGpioPins(device)) != MYKONOS_ERR_OK)
13273 {
13274 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal));
13275 return retVal;
13276 }
13277
13278 if ((retVal = MYKONOS_setRadioControlPinMode(device)) != MYKONOS_ERR_OK)
13279 {
13280 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal));
13281 return retVal;
13282 }
13283
13284 /* Set the default ObsRx Path source for when the device moves to RadioOn */
13285 if ((retVal = MYKONOS_setDefaultObsRxPath(device, device->obsRx->defaultObsRxChannel)) != MYKONOS_ERR_OK)
13286 {
13287 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal));
13288 return retVal;
13289 }
13290
13291 return MYKONOS_ERR_OK;
13292 }
13293
13294 /**
13295 * \brief Loads binary byte array into ARM program memory. This API function allows user to load the ARM concurrently.
13296 * This is specially to reduce the system initialization time.
13297 *
13298 * \pre MYKONOS_initArm() function must be called before calling this API.
13299 *
13300 * \post after calling this function the user must verify:
13301 * Arm Checksum using MYKONOS_verifyArmChecksum(mykonosDevice_t *device)
13302 * verify ARM state is in MYKONOS_ARM_READY state using MYKONOS_checkArmState(device, MYK_ARM_READY);
13303 *
13304 * <B>Dependencies</B>
13305 * - device->spiSettings->chipSelectIndex
13306 * - device->spiSettings
13307 *
13308 * \param device is structure pointer to the Mykonos data structure containing settings
13309 * \param binary is a byte array containing ARM program memory data bytes (directly from .bin file)
13310 * \param count is the number of bytes in the byte array
13311 *
13312 * \retval MYKONOS_ERR_OK Function completed successfully
13313 * \retval MYKONOS_ERR_LOADARMCON_NULL_PARAM Function parameter binary has a NULL pointer
13314 * \retval MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT Count parameter must be 98304 bytes
13315 * \retval MYKONOS_ERR_ARM_INV_ADDR_PARM Invalid memory address
13316 */
MYKONOS_loadArmConcurrent(mykonosDevice_t * device,uint8_t * binary,uint32_t count)13317 mykonosErr_t MYKONOS_loadArmConcurrent(mykonosDevice_t *device, uint8_t *binary, uint32_t count)
13318 {
13319 uint8_t stackPtr[4] = {0};
13320 uint8_t bootAddr[4] = {0};
13321 uint32_t i;
13322 uint32_t address = MYKONOS_ADDR_ARM_START_PROG_ADDR;
13323
13324 #if MYK_ENABLE_SPIWRITEARRAY == 1
13325 uint32_t addrIndex = 0;
13326 uint32_t dataIndex = 0;
13327 uint32_t spiBufferSize = MYK_SPIWRITEARRAY_BUFFERSIZE;
13328 uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0};
13329 #endif
13330
13331 #if (MYKONOS_VERBOSE == 1)
13332 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_loadArmConcurrent()\n");
13333 #endif
13334
13335 if (binary == NULL)
13336 {
13337 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADARMCON_NULL_PARAM, getMykonosErrorMessage(MYKONOS_ERR_LOADARMCON_NULL_PARAM));
13338 return MYKONOS_ERR_LOADARMCON_NULL_PARAM;
13339 }
13340
13341 if (count != 98304)
13342 {
13343 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT,
13344 getMykonosErrorMessage(MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT));
13345 return MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT;
13346 }
13347 else
13348 {
13349 /* extraction of stack pointer and boot address from top of array */
13350 stackPtr[0] = binary[0];
13351 stackPtr[1] = binary[1];
13352 stackPtr[2] = binary[2];
13353 stackPtr[3] = binary[3];
13354
13355 bootAddr[0] = binary[4];
13356 bootAddr[1] = binary[5];
13357 bootAddr[2] = binary[6];
13358 bootAddr[3] = binary[7];
13359
13360 /* set auto increment address bit */
13361 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8C);
13362
13363 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)((address) >> 2));
13364 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, (uint8_t)(address >> 10));
13365
13366 /* start write at correct byte offset */
13367 /* write data is located at SPI address 0xD04=data[7:0], 0xD05=data[15:8], 0xD06=data[23:16], 0xD07=data[31:24] */
13368 /* with address auto increment set, after x407 is written, the address will automatically increment */
13369
13370 #if (MYK_ENABLE_SPIWRITEARRAY == 0)
13371
13372 for (i = 0; i < byteCount; i++)
13373 {
13374 CMB_SPIWriteByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), data[i]);
13375 }
13376
13377 #elif (MYK_ENABLE_SPIWRITEARRAY == 1)
13378
13379 addrIndex = 0;
13380 dataIndex = 0;
13381 for (i = 0; i < count; i++)
13382 {
13383 addrArray[addrIndex++] = (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4));
13384
13385 if (addrIndex == spiBufferSize)
13386 {
13387 CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &binary[dataIndex], addrIndex);
13388 dataIndex = dataIndex + addrIndex;
13389 addrIndex = 0;
13390 }
13391 }
13392
13393 if (addrIndex > 0)
13394 {
13395 CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &binary[dataIndex], addrIndex);
13396 }
13397
13398 #endif
13399
13400 /* writing the stack pointer address */
13401 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_0, stackPtr[0]); /* stack pointer [7:0] */
13402 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_1, stackPtr[1]); /* stack pointer [15:8] */
13403 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_2, stackPtr[2]); /* stack pointer [23:16] */
13404 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_3, stackPtr[3]); /* stack pointer [31:24] */
13405
13406 /* writing the boot address */
13407 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_0, bootAddr[0]); /* boot address [7:0] */
13408 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_1, bootAddr[1]); /* boot address [15:8] */
13409 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_2, bootAddr[2]); /* boot address [23:16] */
13410 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_3, bootAddr[3]); /* boot address [31:24] */
13411
13412 /* setting the ARM run bit */
13413 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8D);
13414
13415 }
13416
13417 return MYKONOS_ERR_OK;
13418 }
13419
13420 /**
13421 * \brief Verifies the ARM checksum value
13422 *
13423 * The checksum which is written into the .hex file is verified with the calculated checksum
13424 * in the Mykonos ARM after the hex file has been loaded
13425 *
13426 * <B>Dependencies</B>
13427 * - device->spiSettings->chipSelectIndex
13428 *
13429 * \param device is structure pointer to the Mykonos data structure containing settings
13430 *
13431 * \retval MYKONOS_ERR_OK Function completed successfully
13432 */
MYKONOS_verifyArmChecksum(mykonosDevice_t * device)13433 mykonosErr_t MYKONOS_verifyArmChecksum(mykonosDevice_t *device)
13434 {
13435 uint32_t buildTimeChecksum = 0x00000000;
13436 uint32_t calculatedChecksum = 0x00000000;
13437 uint8_t buildData[4] = {0};
13438 uint8_t calcData[4] = {0};
13439 mykonosErr_t retVal = MYKONOS_ERR_OK;
13440
13441 const uint8_t CHECKSUM_BYTES = 0x4;
13442
13443 #if (MYKONOS_VERBOSE == 1)
13444 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_verifyArmChecksum()\n");
13445 #endif
13446
13447 /* disabling auto increment and reading four (4) bytes at ARM checksum memory location */
13448 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_BUILD_CHKSUM_ADDR, buildData, CHECKSUM_BYTES, 0);
13449 if (retVal != MYKONOS_ERR_OK)
13450 {
13451 return retVal;
13452 }
13453 /* determining build time checksum */
13454 buildTimeChecksum = (((uint32_t)buildData[3] << 24) | ((uint32_t)buildData[2] << 16) | ((uint32_t)buildData[1] << 8) | (uint32_t)buildData[0]);
13455
13456 /* using 200 msec timeout for exit out of while loop [maximum checksum calculation time = 5 ms] */
13457 CMB_setTimeout_ms(device->spiSettings, 200);
13458
13459 /* determining calculated checksum */
13460 do
13461 {
13462 if ((retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_CALC_CHKSUM_ADDR, calcData, CHECKSUM_BYTES, 0)) != MYKONOS_ERR_OK)
13463 {
13464 return retVal;
13465 }
13466 calculatedChecksum = (((uint32_t)calcData[3] << 24) | ((uint32_t)calcData[2] << 16) | ((uint32_t)calcData[1] << 8) | (uint32_t)calcData[0]);
13467 } while ((!calculatedChecksum) && (!CMB_hasTimeoutExpired(device->spiSettings)));
13468
13469 /* performing consistency check */
13470 if (buildTimeChecksum == calculatedChecksum)
13471 {
13472 return MYKONOS_ERR_OK;
13473 }
13474 else
13475 {
13476 return MYKONOS_ERR_ARM_INVALID_BUILDCHKSUM;
13477 }
13478 }
13479
13480 /**
13481 * \brief Verifies the ARM status once it is start running
13482 *
13483 * Wait for ARM to go into radio state, if takes longer there is and ARM error
13484 * get error in Application layer calling MYKONOS_getRadioState()
13485 *
13486 * <B>Dependencies</B>
13487 * - device->spiSettings->chipSelectIndex
13488 *
13489 * \param device is structure pointer to the Mykonos data structure containing settings
13490 * \param armStateCheck if the ARM is not in this state it will return an error,
13491 *
13492 * \retval MYKONOS_ERR_ARMSTATE_EXCEPTION ARM system problem has been detected.
13493 * \retval MYKONOS_ERR_ARMSTATE_CAL_ERROR ARM has detected an error in the tracking calibrations.
13494 * \retval MYKONOS_ERR_ARMSTATE_EXCEPTION ARM has detected an illegal profile.
13495 * \retval MYKONOS_ERR_WAITARMCSTATE_TIMEOUT Timeout occurred in check ARM state.
13496 * \retval MYKONOS_ERR_OK Function completed successfully
13497 */
MYKONOS_checkArmState(mykonosDevice_t * device,mykonosArmState_t armStateCheck)13498 mykonosErr_t MYKONOS_checkArmState(mykonosDevice_t *device, mykonosArmState_t armStateCheck)
13499 {
13500 mykonosErr_t retVal = MYKONOS_ERR_OK;
13501 uint32_t armStatus = 0x00;
13502 uint32_t armStatusMapped = 0x00;
13503 uint32_t timeoutMs = 500; /* 500ms timeOut */
13504 uint8_t endCheck = 0x00;
13505
13506 #if (MYKONOS_VERBOSE == 1)
13507 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_checkArmState()\n");
13508 #endif
13509
13510 CMB_setTimeout_ms(device->spiSettings, timeoutMs);
13511
13512 do
13513 {
13514 if ((retVal = MYKONOS_getRadioState(device, &armStatus)) != MYKONOS_ERR_OK)
13515 {
13516 return retVal;
13517 }
13518
13519 /* Mapping of the armStatus bit to the enum value. */
13520 switch(armStatus)
13521 {
13522 case 0:
13523 armStatusMapped = (uint32_t)MYK_ARM_POWERUP;
13524 break;
13525 case 1:
13526 armStatusMapped = (uint32_t)MYK_ARM_READY;
13527 break;
13528 case 2:
13529 armStatusMapped = (uint32_t)MYK_ARM_IDLE;
13530 break;
13531 case 3:
13532 armStatusMapped = (uint32_t)MYK_ARM_RADIO_ON;
13533 break;
13534 case 4:
13535 armStatusMapped = (uint32_t)MYK_ARM_PROFILE_ERROR;
13536 break;
13537 default:
13538 armStatusMapped = armStatus;
13539 break;
13540 }
13541
13542 if (armStateCheck && armStatusMapped)
13543 {
13544 retVal = MYKONOS_ERR_OK;
13545 break;
13546 }
13547
13548 if (CMB_hasTimeoutExpired(device->spiSettings))
13549 {
13550 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAITARMCSTATE_TIMEOUT,
13551 getMykonosErrorMessage(MYKONOS_ERR_WAITARMCSTATE_TIMEOUT));
13552 retVal = MYKONOS_ERR_WAITARMCSTATE_TIMEOUT;
13553 break;
13554 }
13555
13556 switch (armStatusMapped)
13557 {
13558 /* this cases are not ARM errors */
13559 case MYK_ARM_POWERUP:
13560 case MYK_ARM_READY:
13561 case MYK_ARM_IDLE:
13562 case MYK_ARM_RADIO_ON:
13563 break;
13564
13565 case MYK_ARM_PROFILE_ERROR:
13566 /* return error directly */
13567 retVal = MYKONOS_ERR_ARMSTATE_PROFILE_ERROR;
13568 endCheck = 1;
13569 break;
13570
13571 case MYK_ARM_CAL_ERROR:
13572 /* return error directly */
13573 retVal = MYKONOS_ERR_ARMSTATE_CAL_ERROR;
13574 endCheck = 1;
13575 break;
13576
13577 case MYK_ARM_EXCEPTION:
13578 /* return error directly */
13579 retVal = MYKONOS_ERR_ARMSTATE_EXCEPTION;
13580 endCheck = 1;
13581 break;
13582
13583 case (uint32_t)MYK_ARM_EXCEPTION | (uint32_t)MYK_ARM_PROFILE_ERROR:
13584 /* return error directly */
13585 retVal = MYKONOS_ERR_ARMSTATE_EXCEPTION;
13586 endCheck = 1;
13587 break;
13588
13589 default:
13590 endCheck = 0;
13591 break;
13592 }
13593
13594 } while (!endCheck);
13595
13596 return retVal;
13597 }
13598
13599 /**
13600 * \brief Reads back the version of the ARM binary loaded into the Mykonos ARM memory
13601 *
13602 * This function reads the ARM memory to read back the major.minor.releaseCandidate
13603 * version for the ARM binary loaded into ARM memory.
13604 *
13605 * <B>Dependencies</B>
13606 * - device->spiSettings->chipSelectIndex
13607 *
13608 * \param device is structure pointer to the Mykonos data structure containing settings
13609 * \param majorVer The Major version is returned in this parameter
13610 * \param minorVer The Minor version is returned in this parameter
13611 * \param rcVer The release candidate version (build number) is returned in this parameter
13612 * \param buildType The Type of the build [Debug / Test_Object / Release]
13613 *
13614 * \retval MYKONOS_ERR_OK Function completed successfully
13615 * \retval MYKONOS_ERR_GETARMVER_NULL_PARM One of the function parameters has a NULL pointer
13616 */
MYKONOS_getArmVersion(mykonosDevice_t * device,uint8_t * majorVer,uint8_t * minorVer,uint8_t * rcVer,mykonosBuild_t * buildType)13617 mykonosErr_t MYKONOS_getArmVersion(mykonosDevice_t *device, uint8_t *majorVer, uint8_t *minorVer, uint8_t *rcVer, mykonosBuild_t *buildType)
13618 {
13619 mykonosErr_t retVal = MYKONOS_ERR_OK;
13620 uint8_t ver[5] = {0};
13621 uint32_t fullVersion = 0;
13622 uint8_t validBuilds = 0x05;
13623
13624 #if (MYKONOS_VERBOSE == 1)
13625 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getArmVersion()\n");
13626 #endif
13627
13628 if ((majorVer == NULL) || (minorVer == NULL) || (rcVer == NULL))
13629 {
13630 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETARMVER_NULL_PARM, getMykonosErrorMessage(MYKONOS_ERR_GETARMVER_NULL_PARM));
13631 return MYKONOS_ERR_GETARMVER_NULL_PARM;
13632 }
13633
13634 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_VERSION, &ver[0], sizeof(ver), 1);
13635 if (retVal != MYKONOS_ERR_OK)
13636 {
13637 return retVal;
13638 }
13639
13640 fullVersion = ((uint32_t)(ver[0]) | (uint32_t)((uint32_t)(ver[1]) << 8) | (uint32_t)((uint32_t)(ver[2]) << 16) | (uint32_t)((uint32_t)(ver[3]) << 24));
13641 *rcVer = (uint8_t)(fullVersion % 100);
13642 *minorVer = (uint8_t)((fullVersion / 100) % 100);
13643 *majorVer = (uint8_t)(fullVersion / 10000);
13644
13645 switch (ver[4] & validBuilds)
13646 {
13647 case MYK_BUILD_DEBUG:
13648 *buildType = MYK_BUILD_DEBUG;
13649 break;
13650 case MYK_BUILD_TEST_OBJECT:
13651 *buildType = MYK_BUILD_TEST_OBJECT;
13652 break;
13653 default:
13654 *buildType = MYK_BUILD_RELEASE;
13655 break;
13656 }
13657
13658 return MYKONOS_ERR_OK;
13659 }
13660
13661 /**
13662 * \brief This function will configure DPD settings
13663 *
13664 * A DPD-enabled transceiver is required for DPD to be enabled. The DPD has several user
13665 * adjustable settings that can be configured before running the runInitCals
13666 * with the calMask set for the DPD init cal. Call this function with desired
13667 * settings set before running the DPD init cal or enabling DPD tracking.
13668 *
13669 * This function can be called in either Radio On or Off state.
13670 *
13671 * <B>Dependencies</B>
13672 * - device->spiSettings->chipSelectIndex
13673 * - device->profilesValid
13674 * - device->tx->dpdConfig (All members)
13675 *
13676 *
13677 * \retval MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV ERROR: to use these features, a valid Tx and ORx profile must exist in the device data structure
13678 * \retval MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT ERROR: device->tx->dpdConfig is a NULL pointer
13679 * \retval MYKONOS_ERR_CFGDPD_INV_DPDDAMPING ERROR: damping parameter is out of range
13680 * \retval MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES ERROR: samples parameter is out of range
13681 * \retval MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS ERROR: numWeights parameter is out of range (0-3)
13682 * \retval MYKONOS_ERR_CFGDPD_INV_MODELVERSION ERROR: modelVersion parameter is out of range (0-3)
13683 * \retval MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH ERROR: outlierThreshold parameter is out of range
13684 * \retval MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY ERROR: additionalDelayOffset parameter is out of range
13685 * \retval MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL ERROR: pathDelayPnSeqLevel parameter is out of range
13686 * \retval MYKONOS_ERR_OK Function completed successfully
13687 */
MYKONOS_configDpd(mykonosDevice_t * device)13688 mykonosErr_t MYKONOS_configDpd(mykonosDevice_t *device)
13689 {
13690 mykonosErr_t retVal = MYKONOS_ERR_OK;
13691 uint8_t armFieldValue[6] = {0};
13692 uint8_t byteOffset = 0;
13693 uint16_t negPnLevel = 0;
13694 uint8_t highPowerModelUpdate = 0;
13695 uint8_t robustModeling = 0;
13696 uint32_t radioStatus = 0;
13697
13698 #if (MYKONOS_VERBOSE == 1)
13699 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_configDpd()\n");
13700 #endif
13701
13702 /* DPD requires Tx and ORx enabled, throw error if both are not enabled */
13703 if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID))
13704 {
13705 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV,
13706 getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV));
13707 return MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV;
13708 }
13709
13710 if (device->tx->dpdConfig == NULL)
13711 {
13712 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT,
13713 getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT));
13714 return MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT;
13715 }
13716
13717 /* check DPD damping and samples parameters */
13718 if (device->tx->dpdConfig->damping > 15)
13719 {
13720 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDDAMPING,
13721 getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDDAMPING));
13722 return MYKONOS_ERR_CFGDPD_INV_DPDDAMPING;
13723 }
13724
13725 if ((device->tx->dpdConfig->samples < 64) || (device->tx->dpdConfig->samples > 32768))
13726 {
13727 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES,
13728 getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES));
13729 return MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES;
13730 }
13731
13732 if (device->tx->dpdConfig->numWeights > 3)
13733 {
13734 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS,
13735 getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS));
13736 return MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS;
13737 }
13738
13739 if (device->tx->dpdConfig->modelVersion > 3)
13740 {
13741 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_MODELVERSION,
13742 getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_MODELVERSION));
13743 return MYKONOS_ERR_CFGDPD_INV_MODELVERSION;
13744 }
13745
13746 highPowerModelUpdate = (device->tx->dpdConfig->highPowerModelUpdate > 0) ? 1 : 0;
13747 robustModeling = (device->tx->dpdConfig->robustModeling > 0) ? 1 : 0;
13748
13749 armFieldValue[0] = (uint8_t)(((device->tx->dpdConfig->numWeights & 3) << 4) | (device->tx->dpdConfig->damping & 0xF));
13750 armFieldValue[1] = (uint8_t)((robustModeling << 3) | (highPowerModelUpdate << 2) | (device->tx->dpdConfig->modelVersion & 3));
13751 armFieldValue[2] = (device->tx->dpdConfig->samples & 0xFF);
13752 armFieldValue[3] = ((device->tx->dpdConfig->samples >> 8) & 0xFF);
13753 byteOffset = 0;
13754 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 4);
13755 if (retVal != MYKONOS_ERR_OK)
13756 {
13757 return retVal;
13758 }
13759
13760 /* set DPD outlier threshold parameter */
13761 if ((device->tx->dpdConfig->outlierThreshold < 1) || (device->tx->dpdConfig->outlierThreshold > 8192))
13762 {
13763 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH,
13764 getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH));
13765 return MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH;
13766 }
13767
13768 armFieldValue[0] = (device->tx->dpdConfig->outlierThreshold & 0xFF);
13769 armFieldValue[1] = ((device->tx->dpdConfig->outlierThreshold >> 8) & 0xFF);
13770 byteOffset = 10;
13771 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 2);
13772 if (retVal != MYKONOS_ERR_OK)
13773 {
13774 return retVal;
13775 }
13776
13777 /* set DPD Model Prior Weight parameter */
13778 if (device->tx->dpdConfig->modelPriorWeight > 32)
13779 {
13780 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT,
13781 getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT));
13782 return MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT;
13783 }
13784 armFieldValue[0] = (device->tx->dpdConfig->modelPriorWeight & 0xFF);
13785 armFieldValue[1] = 0;
13786 byteOffset = 12;
13787 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 2);
13788 if (retVal != MYKONOS_ERR_OK)
13789 {
13790 return retVal;
13791 }
13792
13793 /* no need to verify weights min/max as all int8 values are valid */
13794 armFieldValue[0] = (uint8_t)(device->tx->dpdConfig->weights[0].real);
13795 armFieldValue[1] = (uint8_t)(device->tx->dpdConfig->weights[0].imag);
13796 armFieldValue[2] = (uint8_t)(device->tx->dpdConfig->weights[1].real);
13797 armFieldValue[3] = (uint8_t)(device->tx->dpdConfig->weights[1].imag);
13798 armFieldValue[4] = (uint8_t)(device->tx->dpdConfig->weights[2].real);
13799 armFieldValue[5] = (uint8_t)(device->tx->dpdConfig->weights[2].imag);
13800
13801 byteOffset = 14;
13802 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 6);
13803 if (retVal != MYKONOS_ERR_OK)
13804 {
13805 return retVal;
13806 }
13807
13808 /* set DPD additional delay offset parameter */
13809 if ((device->tx->dpdConfig->additionalDelayOffset < -64) || (device->tx->dpdConfig->additionalDelayOffset > 64))
13810 {
13811 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY,
13812 getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY));
13813 return MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY;
13814 }
13815
13816 /* read radio state to make sure ARM is in radioOff /IDLE */
13817 retVal = MYKONOS_getRadioState(device, &radioStatus);
13818 if (retVal != MYKONOS_ERR_OK)
13819 {
13820 return retVal;
13821 }
13822
13823 /* Radio state check */
13824 if (((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_IDLE) || ((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_READY))
13825 {
13826 armFieldValue[0] = (uint8_t)(device->tx->dpdConfig->additionalDelayOffset & 0xFF);
13827 armFieldValue[1] = (uint8_t)(((uint16_t)device->tx->dpdConfig->additionalDelayOffset >> 8) & 0xFF);
13828 byteOffset = 2;
13829 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armFieldValue[0], 2);
13830 if (retVal != MYKONOS_ERR_OK)
13831 {
13832 return retVal;
13833 }
13834
13835 if ((device->tx->dpdConfig->pathDelayPnSeqLevel < 1) || (device->tx->dpdConfig->pathDelayPnSeqLevel > 8191))
13836 {
13837 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL,
13838 getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL));
13839 return MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL;
13840 }
13841
13842 /* Set Path Delay PN sequence amplitude - positive and negative */
13843 armFieldValue[0] = (uint8_t)(device->tx->dpdConfig->pathDelayPnSeqLevel & 0xFF);
13844 armFieldValue[1] = (uint8_t)((device->tx->dpdConfig->pathDelayPnSeqLevel >> 8) & 0xFF);
13845
13846 negPnLevel = ((~device->tx->dpdConfig->pathDelayPnSeqLevel) + 1); /* times -1 */
13847 armFieldValue[2] = (uint8_t)(negPnLevel & 0xFF);
13848 armFieldValue[3] = (uint8_t)(((negPnLevel) >> 8) & 0xFF);
13849 byteOffset = 10;
13850 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armFieldValue[0], 4);
13851 if (retVal != MYKONOS_ERR_OK)
13852 {
13853 return retVal;
13854 }
13855 }
13856 else
13857 {
13858 /* record warning about not updated members */
13859 CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE,
13860 getMykonosErrorMessage(MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE));
13861 }
13862
13863 return MYKONOS_ERR_OK;
13864 }
13865
13866 /* \brief Reads the DPD config structure from ARM memory
13867 *
13868 * This function reads the DPD structure
13869 * from ARM memory and returns in the device->tx->dpdConfig structure.
13870 *
13871 * A DPD-enabled transceiver is required for DPD to be enabled.
13872 *
13873 * <B>Dependencies</B>
13874 * - device->spiSettings->chipSelectIndex
13875 * - device->profilesValid
13876 * - device->tx->dpdConfig (All members)
13877 *
13878 * \param device is structure pointer to the Mykonos data structure containing settings
13879 *
13880 * \retval MYKONOS_ERR_OK Function completed successfully
13881 * \retval MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV Error: Tx and ORx profiles must be valid for DPD functions
13882 * \retval MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT Error: NULL pointer to device->tx->dpdConfig structure
13883 */
MYKONOS_getDpdConfig(mykonosDevice_t * device)13884 mykonosErr_t MYKONOS_getDpdConfig(mykonosDevice_t *device)
13885 {
13886 uint16_t byteOffset = 0;
13887 uint8_t armMem[20] = {0};
13888 mykonosErr_t retVal = MYKONOS_ERR_OK;
13889
13890 #if (MYKONOS_VERBOSE == 1)
13891 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdConfig()\n");
13892 #endif
13893
13894 /* DPD requires Tx and ORx enabled, throw error if both are not enabled */
13895 if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID))
13896 {
13897 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV,
13898 getMykonosErrorMessage(MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV));
13899 return MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV;
13900 }
13901
13902 if (device->tx->dpdConfig == NULL)
13903 {
13904 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT,
13905 getMykonosErrorMessage(MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT));
13906 return MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT;
13907 }
13908
13909 byteOffset = 0;
13910 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armMem[0], 20);
13911 if (retVal != MYKONOS_ERR_OK)
13912 {
13913 return retVal;
13914 }
13915
13916 device->tx->dpdConfig->damping = (armMem[0] & 0x0F);
13917 device->tx->dpdConfig->numWeights = ((armMem[0] >> 4) & 0x03);
13918
13919 device->tx->dpdConfig->modelVersion = (armMem[1] & 0x03);
13920 device->tx->dpdConfig->highPowerModelUpdate = ((armMem[1] >> 2) & 0x01);
13921 device->tx->dpdConfig->robustModeling = 0;
13922 device->tx->dpdConfig->samples = ((uint16_t)(armMem[3]) << 8) | (uint16_t)(armMem[2]);
13923
13924 device->tx->dpdConfig->outlierThreshold = ((uint16_t)(armMem[11]) << 8) | (uint16_t)(armMem[10]);
13925 device->tx->dpdConfig->modelPriorWeight = armMem[12];
13926 device->tx->dpdConfig->weights[0].real = (int8_t)(armMem[14]);
13927 device->tx->dpdConfig->weights[0].imag = (int8_t)(armMem[15]);
13928 device->tx->dpdConfig->weights[1].real = (int8_t)(armMem[16]);
13929 device->tx->dpdConfig->weights[1].imag = (int8_t)(armMem[17]);
13930 device->tx->dpdConfig->weights[2].real = (int8_t)(armMem[18]);
13931 device->tx->dpdConfig->weights[2].imag = (int8_t)(armMem[19]);
13932
13933 byteOffset = 2;
13934 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armMem[0], 2);
13935 if (retVal != MYKONOS_ERR_OK)
13936 {
13937 return retVal;
13938 }
13939
13940 device->tx->dpdConfig->additionalDelayOffset = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0]));
13941
13942 byteOffset = 10;
13943 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armMem[0], 2);
13944 if (retVal != MYKONOS_ERR_OK)
13945 {
13946 return retVal;
13947 }
13948
13949 device->tx->dpdConfig->pathDelayPnSeqLevel = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0]));
13950
13951 return MYKONOS_ERR_OK;
13952 }
13953
13954 /**
13955 * \brief This function reads the DPD calibration status from the Mykonos ARM processor.
13956 *
13957 * The dpdStatus is read back from the ARM processor and returned in the function
13958 * parameter dpdStatus.
13959 *
13960 * A DPD-enabled transceiver is required for this feature to be enabled.
13961 *
13962 * <B>Dependencies</B>
13963 * - device->spiSettings->chipSelectIndex
13964 *
13965 * \param device is structure pointer to the Mykonos data structure containing settings
13966 * \param txChannel Desired Transmit channel to read back DPD status for (Valid ENUM values: TX1 or TX2 only)
13967 * \param dpdStatus Pointer to a structure to return the status information to
13968 *
13969 * \retval MYKONOS_ERR_OK Function completed successfully
13970 * \retval MYKONOS_ERR_GETDPDSTATUS_NULLPARAM dpdStatus function parameter is a NULL pointer
13971 * \retval MYKONOS_ERR_GETDPDSTATUS_INV_CH txChannel parameter is a non-supported value.
13972 * \retval MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG ARM reported an error while processing the GET ARM command
13973 */
MYKONOS_getDpdStatus(mykonosDevice_t * device,mykonosTxChannels_t txChannel,mykonosDpdStatus_t * dpdStatus)13974 mykonosErr_t MYKONOS_getDpdStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdStatus_t *dpdStatus)
13975 {
13976 uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_DPDCONFIG, 0};
13977 uint8_t armData[64] = {0};
13978 uint32_t timeoutMs = 0;
13979 uint8_t cmdStatusByte = 0;
13980 uint8_t channelSelect = 0;
13981 mykonosErr_t retVal = MYKONOS_ERR_OK;
13982
13983 #if (MYKONOS_VERBOSE == 1)
13984 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdStatus()\n");
13985 #endif
13986
13987 if (dpdStatus == NULL)
13988 {
13989 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_NULLPARAM,
13990 getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_NULLPARAM));
13991 return MYKONOS_ERR_GETDPDSTATUS_NULLPARAM;
13992 }
13993
13994 switch (txChannel)
13995 {
13996 case TX1:
13997 channelSelect = 0;
13998 break;
13999 case TX2:
14000 channelSelect = 1;
14001 break;
14002 default:
14003 {
14004 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_INV_CH,
14005 getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_INV_CH));
14006 return MYKONOS_ERR_GETDPDSTATUS_INV_CH;
14007 }
14008 }
14009
14010 extData[2] = channelSelect;
14011
14012 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
14013 if (retVal != MYKONOS_ERR_OK)
14014 {
14015 return retVal;
14016 }
14017
14018 timeoutMs = 1000;
14019 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
14020 if (retVal != MYKONOS_ERR_OK)
14021 {
14022 if (cmdStatusByte > 0)
14023 {
14024 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG,
14025 getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG));
14026 return MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG;
14027 }
14028
14029 return retVal;
14030 }
14031
14032 if (cmdStatusByte > 0)
14033 {
14034 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG,
14035 getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG));
14036 return MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG;
14037 }
14038
14039 /* read status from ARM memory */
14040 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1);
14041 if (retVal != MYKONOS_ERR_OK)
14042 {
14043 return retVal;
14044 }
14045
14046 dpdStatus->dpdErrorStatus = ((uint32_t)(armData[1]) << 8) | (uint32_t)(armData[0]); /* Only lower 16 bits */
14047 dpdStatus->dpdTrackCount = ((uint32_t)(armData[11]) << 24) | ((uint32_t)(armData[10]) << 16) | ((uint32_t)(armData[9]) << 8) | (uint32_t)(armData[8]);
14048 dpdStatus->dpdModelErrorPercent = ((uint32_t)(armData[15]) << 24) | ((uint32_t)(armData[14]) << 16) | ((uint32_t)(armData[13]) << 8) | (uint32_t)(armData[12]);
14049 dpdStatus->dpdExtPathDelay = ((uint32_t)(armData[26]) * 16) + (uint32_t)(armData[24]);
14050 dpdStatus->dpdMaxAdaptationCurrent = ((uint16_t)(armData[41]) << 8) + (uint16_t)(armData[40]);
14051 dpdStatus->dpdMaxAdaptation = ((uint16_t)(armData[43]) << 8) + (uint16_t)(armData[42]);
14052 dpdStatus->dpdIterCount = ((uint32_t)(armData[47]) << 24) | ((uint32_t)(armData[46]) << 16) | ((uint32_t)(armData[45]) << 8) | (uint32_t)(armData[44]);
14053
14054 return MYKONOS_ERR_OK;
14055 }
14056
14057 /**
14058 * \brief This private helper function called during RadioOff, will allow DPD tracking to be scheduled
14059 * by the ARM when back in the RadioOn state.
14060 *
14061 * This function sets a flag in the ARM memory that if the enableDpd tracking cal mask
14062 * and this setting are both set, then the ARM will schedule DPD tracking to occur
14063 * in the radioOn ARM state.
14064 *
14065 * A DPD-enabled transceiver is required for DPD to be enabled.
14066 *
14067 * <B>Dependencies</B>
14068 * - device->spiSettings->chipSelectIndex
14069 * - device->tx->dpdConfig
14070 *
14071 * \param device is structure pointer to the Mykonos data structure containing settings
14072 * \param tx1Enable 0=disable DPD Tx1 tracking, 1= enable DPD Tx1 tracking
14073 * \param tx2Enable 0=disable DPD Tx2 tracking, 1= enable DPD Tx2 tracking
14074 *
14075 * \retval MYKONOS_ERR_OK Function completed successfully
14076 * \retval MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR ARM is not in the RadioOff state, call MYKONOS_radioOff()
14077 */
enableDpdTracking(mykonosDevice_t * device,uint8_t tx1Enable,uint8_t tx2Enable)14078 static mykonosErr_t enableDpdTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable)
14079 {
14080 uint32_t radioStatus = 0;
14081 mykonosErr_t retVal = MYKONOS_ERR_OK;
14082 uint8_t enableBit[4] = {0};
14083 uint8_t byteOffset = 20;
14084
14085 #if (MYKONOS_VERBOSE == 1)
14086 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableDpdTracking()\n");
14087 #endif
14088
14089 /* read radio state to make sure ARM is in radioOff /IDLE */
14090 retVal = MYKONOS_getRadioState(device, &radioStatus);
14091 if (retVal != MYKONOS_ERR_OK)
14092 {
14093 return retVal;
14094 }
14095
14096 /* throw error if not in radioOff/IDLE state */
14097 if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY))
14098 {
14099 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR,
14100 getMykonosErrorMessage(MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR));
14101 return MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR;
14102 }
14103
14104 enableBit[0] = (tx1Enable > 0) ? 1 : 0;
14105 enableBit[1] = 0;
14106 enableBit[2] = (tx2Enable > 0) ? 1 : 0;
14107 enableBit[3] = 0;
14108
14109 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &enableBit[0], 4);
14110 if (retVal != MYKONOS_ERR_OK)
14111 {
14112 return retVal;
14113 }
14114
14115 return MYKONOS_ERR_OK;
14116 }
14117
14118 /**
14119 * \brief This function will allow loading of the DPD model file.
14120 *
14121 * This function writes a copy of the user's DPD model to ARM memory and instructs the ARM to install that DPD model
14122 * into hardware. Note that initializing the device will over write DPD model data. Note that the DPD model being
14123 * restored must match the PA for which it is configured. Restoring a DPD model to a different PA than for which it
14124 * is configured will not yield the desired performance. The user is responsible to insure the DPD model matches the
14125 * PA configuration.
14126 *
14127 * \param device Structure pointer to the Mykonos data structure containing settings
14128 * \param txChannel Desired transmit channel to which to write the DPD model file (Valid ENUM type mykonosTxChannels_t: TX1 or TX2 or TX1_TX2)
14129 * \param modelDataBuffer Pointer to the user buffer containing the history/model data to be loaded to a txChannel
14130 * Valid sizes: 182 bytes for a single model load to either TX1 or TX2.
14131 * 364 bytes for a dual model load to both TX1_TX2, where the TX1 model data will occupy the first 182 bytes
14132 * and TX2 model data will occupy the second 182 bytes.
14133 * \param modelNumberBytes Total buffer size of the user history/model data buffer. Allowed sizes are 182 bytes for TX1 or TX2 and
14134 * 364 bytes for TX1_TX2.
14135 *
14136 *
14137 * \retval MYKONOS_ERR_OK Function completed successfully
14138 * \retval MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE User suppled modelNumberBytes size is incorrect. TX1 or TX2 = 182, TX1_TX2 = 364
14139 * \retval MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL User supplied txChannel does not match TX1 or TX2 or TX1_TX2
14140 * \retval MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG ARM returned error for Set ARM Command
14141 */
MYKONOS_restoreDpdModel(mykonosDevice_t * device,mykonosTxChannels_t txChannel,uint8_t * modelDataBuffer,uint32_t modelNumberBytes)14142 mykonosErr_t MYKONOS_restoreDpdModel(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t *modelDataBuffer, uint32_t modelNumberBytes)
14143 {
14144 uint32_t radioStatus = 0;
14145 mykonosErr_t retVal = MYKONOS_ERR_OK;
14146 uint8_t armData[4] = {0};
14147 uint32_t armBufferAddr = 0;
14148 uint8_t *bufferPtr = 0;
14149 uint8_t extendedData[4] = {0};
14150 uint8_t cmdStatusByte = 0;
14151
14152 const uint8_t RESTORE = 0x08;
14153 const uint32_t timeoutMs = 1000;
14154 const uint32_t MODEL_SIZE = 182;
14155
14156 #if (MYKONOS_VERBOSE == 1)
14157 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_restoreDpdModel()\n");
14158 #endif
14159
14160 /* read radio state to make sure ARM is in radioOff /IDLE */
14161 retVal = MYKONOS_getRadioState(device, &radioStatus);
14162 if (retVal != MYKONOS_ERR_OK)
14163 {
14164 return retVal;
14165 }
14166
14167 if (txChannel == TX1)
14168 {
14169 /* check for single valid provided buffer size */
14170 if (modelNumberBytes != MODEL_SIZE)
14171 {
14172 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE,
14173 getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE));
14174 return MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE;
14175 }
14176
14177 /* retrieve the arm TX1 model buffer address */
14178 retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1);
14179 if (retVal != MYKONOS_ERR_OK)
14180 {
14181 return retVal;
14182 }
14183 armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24));
14184
14185 /* write the TX1 model */
14186 bufferPtr = modelDataBuffer;
14187 retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE); /* write TX1 model */
14188 if (retVal != MYKONOS_ERR_OK)
14189 {
14190 return retVal;
14191 }
14192 }/*end TX1 */
14193
14194 else if (txChannel == TX2)
14195 {
14196 /* check for single valid provided buffer size */
14197 if (modelNumberBytes != MODEL_SIZE)
14198 {
14199 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE,
14200 getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE));
14201 return MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE;
14202 }
14203
14204 /* retrieve the arm TX2 model buffer address */
14205 retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1);
14206 if (retVal != MYKONOS_ERR_OK)
14207 {
14208 return retVal;
14209 }
14210 armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24));
14211
14212 /* write the TX2 model */
14213 bufferPtr = modelDataBuffer;
14214 retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE);
14215 if (retVal != MYKONOS_ERR_OK)
14216 {
14217 return retVal;
14218 }
14219 }/* end TX2 */
14220
14221 /* check for dual txChannel type */
14222 else if (txChannel == TX1_TX2)
14223 {
14224 /* check for single valid provided buffer size */
14225 if (modelNumberBytes != (2 * MODEL_SIZE))
14226 {
14227 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE,
14228 getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE));
14229 return MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE;
14230 }
14231
14232 /* retrieve the arm TX1 model buffer address */
14233 retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1);
14234 if (retVal != MYKONOS_ERR_OK)
14235 {
14236 return retVal;
14237 }
14238 armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24));
14239
14240 /* write the TX1 model */
14241 bufferPtr = modelDataBuffer;
14242 retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE); /* write TX1 model */
14243 if (retVal != MYKONOS_ERR_OK)
14244 {
14245 return retVal;
14246 }
14247 bufferPtr += MODEL_SIZE;
14248
14249 /* retrieve the arm TX2 model buffer address */
14250 retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1);
14251 if (retVal != MYKONOS_ERR_OK)
14252 {
14253 return retVal;
14254 }
14255 armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24));
14256
14257 /* write the TX2 model */
14258 retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE); /* write TX2 model */
14259 if (retVal != MYKONOS_ERR_OK)
14260 {
14261 return retVal;
14262 }
14263 }/*end two txChannel model data load */
14264
14265 /* invalid txChannel for this API command */
14266 else
14267 {
14268 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL,
14269 getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL));
14270 return MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL;
14271 }/* end invalid txChannel check */
14272
14273 /* instruct ARM to load DPD Model */
14274 extendedData[0] = MYKONOS_ARM_OBJECTID_GS_TRACKCALS;
14275 extendedData[1] = MYKONOS_ARM_DPD_RESET;
14276 extendedData[2] = (uint8_t)txChannel + RESTORE;
14277
14278 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extendedData[0], sizeof(extendedData));
14279 if (retVal != MYKONOS_ERR_OK)
14280 {
14281 return retVal;
14282 }
14283
14284 /* wait max of 1sec for command to complete */
14285 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte);
14286 if (retVal != MYKONOS_ERR_OK)
14287 {
14288 if (cmdStatusByte > 0)
14289 {
14290 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG,
14291 getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG));
14292 return MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG;
14293 }
14294 return retVal;
14295 }
14296
14297 return MYKONOS_ERR_OK;
14298 }
14299
14300
14301 /**
14302 * \brief This function called during RadioOff, will allow retrieval of the DPD model file.
14303 *
14304 * This function reads a copy of the DPD model from ARM memory to user memory specified by the modelDataBuffer pointer.
14305 * The user must provide the correct buffer size with the modelNumberBytes argument.
14306 *
14307 * \param device is structure pointer to the Mykonos data structure containing settings
14308 * \param txChannel Desired Transmit channel to read back DPD status for (Valid ENUM type mykonosTxChannels_t: TX1 or TX2 or TX1_TX2)
14309 * \param modelDataBuffer a pointer to the user buffer where the model data is to be written.
14310 * Valid sizes: 182 bytes for a single model load to either TX1 or TX2.
14311 * 364 bytes for a dual model load to both TX1_TX2, where the TX1 model data will occupy the first 182 bytes
14312 * and TX2 model data will occupy the second 182 bytes.
14313 * \param modelNumberBytes is the total buffer size of the user model data buffer. Allowed sizes are 182 bytes for TX1 or TX2 and
14314 * 364 bytes for TX1_TX2.
14315 *
14316 * \retval MYKONOS_ERR_OK Function completed successfully
14317 * \retval MYKONOS_ERR_SAVEDPDMODEL_ARMSTATE_ERROR ARM is not in the RadioOff state, call MYKONOS_radioOff()
14318 * \retval MYKONOS_ERR_SAVEDPDMODEL_BUFFERSIZE_ERROR suppled modelNumberBytes size is incorrect. TX1 or TX2 = 182, TX1_TX2 = 364
14319 * \retval MYKONOS_ERR_SAVEDPDMODEL_INVALID_TXCHANNEL_ERROR supplied txChannel does not match TX1 or TX2 or TX1_TX2
14320 */
MYKONOS_saveDpdModel(mykonosDevice_t * device,mykonosTxChannels_t txChannel,uint8_t * modelDataBuffer,uint32_t modelNumberBytes)14321 mykonosErr_t MYKONOS_saveDpdModel(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t *modelDataBuffer, uint32_t modelNumberBytes)
14322 {
14323 uint32_t radioStatus = 0;
14324 mykonosErr_t retVal = MYKONOS_ERR_OK;
14325 uint16_t modelSize = 0;
14326 uint8_t armData[4] = {0};
14327 uint32_t armBufferAddr = 0;
14328
14329 const uint32_t MODEL_SIZE = 182;
14330
14331 #if (MYKONOS_VERBOSE == 1)
14332 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_saveDpdModel()\n");
14333 #endif
14334
14335 /* read radio state to make sure ARM is in radioOff /IDLE */
14336 retVal = MYKONOS_getRadioState(device, &radioStatus);
14337 if (retVal != MYKONOS_ERR_OK)
14338 {
14339 return retVal;
14340 }
14341
14342 /* throw error if not in radioOff/IDLE state */
14343 if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY))
14344 {
14345 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_ARMSTATE, getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_ARMSTATE)); /* radio not off or initialized */
14346 return MYKONOS_ERR_SAVDPDMOD_ARMSTATE;
14347 }
14348
14349 if (txChannel == TX1)
14350 {
14351 /* check for single valid provided buffer size */
14352 if (modelNumberBytes != MODEL_SIZE)
14353 {
14354 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE,
14355 getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE));
14356 return MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE; /* wrong buffer size */
14357 }
14358
14359 /* retrieve the arm TX1 model buffer address */
14360 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1);
14361 if (retVal != MYKONOS_ERR_OK)
14362 {
14363 return retVal;
14364 }
14365 armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24));
14366
14367 /* read the TX1 model */
14368 retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1);
14369 if (retVal != MYKONOS_ERR_OK)
14370 {
14371 return retVal;
14372 }
14373 modelDataBuffer += modelSize;
14374 }/*end TX1 */
14375
14376 else if (txChannel == TX2)
14377 {
14378 /* check for single valid provided buffer size */
14379 if (modelNumberBytes != MODEL_SIZE)
14380 {
14381 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE,
14382 getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE));
14383 return MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE; /* wrong buffer size */
14384 }
14385
14386 /* retrieve the arm TX2 model buffer address */
14387 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1);
14388 if (retVal != MYKONOS_ERR_OK)
14389 {
14390 return retVal;
14391 }
14392 armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24));
14393
14394 /* read the TX2 model */
14395 retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1);
14396 if (retVal != MYKONOS_ERR_OK)
14397 {
14398 return retVal;
14399 }
14400 }/*end TX2 */
14401
14402 /* check for dual txChannel type */
14403 else if (txChannel == TX1_TX2)
14404 {
14405 /* check for single valid provided buffer size */
14406 if (modelNumberBytes != (2 * MODEL_SIZE))
14407 {
14408 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE,
14409 getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE));
14410 return MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE; /* wrong buffer size */
14411 }
14412
14413 /* retrieve the arm TX1 model buffer address */
14414 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1);
14415 if (retVal != MYKONOS_ERR_OK)
14416 {
14417 return retVal;
14418 }
14419 armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24));
14420
14421 /* read the TX1 model */
14422 retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1);
14423 if (retVal != MYKONOS_ERR_OK)
14424 {
14425 return retVal;
14426 }
14427 modelDataBuffer += MODEL_SIZE;
14428
14429 /* retrieve the arm TX2 model buffer address */
14430 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1);
14431 if (retVal != MYKONOS_ERR_OK)
14432 {
14433 return retVal;
14434 }
14435 armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24));
14436
14437 /* read the TX2 model */
14438 retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1);
14439 if (retVal != MYKONOS_ERR_OK)
14440 {
14441 return retVal;
14442 }
14443 }/* end TX1_TX2 txChannel */
14444
14445 /* invalid txChannel for this API command */
14446 else
14447 {
14448 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL,
14449 getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL));
14450 return MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL; /* invalid txChannel */
14451 }/* end invalid txChannel check */
14452
14453 return MYKONOS_ERR_OK;
14454 }
14455
14456 /**
14457 * \brief This function sets the state of the DPD actuator.
14458 *
14459 * This function can be called in either Radio On or Off state.
14460 *
14461 * \pre A DPD-enabled transceiver is required for DPD to be enabled. DPD init cal has been run and DPD tracking enable.
14462 *
14463 * <B>Dependencies</B>
14464 * - device->spiSettings->chipSelectIndex
14465 *
14466 * \param device is structure pointer to the Mykonos data structure containing settings
14467 * \param txChannel Desired Transmit channel to set the Actuator State (Valid ENUM values: TX1, TX2 or TX1_TX2)
14468 * \param actState Desired actuator state for the DPD, valid states are 0-disable and 1-enable
14469 *
14470 * \retval MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL ERROR: Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2)
14471 * \retval MYKONOS_ERR_SETDPDACT_INV_STATE ERROR: Invalid Actuator state, valid states are 0-disable and 1-enable.
14472 * \retval MYKONOS_ERR_SETDPDACT_ARMERRFLAG ERROR: ARM command flag error set
14473 * \retval MYKONOS_ERR_OK Function completed successfully
14474 */
MYKONOS_setDpdActState(mykonosDevice_t * device,mykonosTxChannels_t txChannel,uint8_t actState)14475 mykonosErr_t MYKONOS_setDpdActState(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t actState)
14476 {
14477 mykonosErr_t retVal = MYKONOS_ERR_OK;
14478 uint32_t timeoutMs = 1000;
14479 uint8_t extData[3] = {0};
14480 uint8_t actuatorSet = 0x00;
14481 uint8_t cmdStatusByte = 0;
14482
14483 #if (MYKONOS_VERBOSE == 1)
14484 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDpdActState()\n");
14485 #endif
14486
14487 switch (txChannel)
14488 {
14489 case TX1:
14490 break;
14491 case TX2:
14492 break;
14493 case TX1_TX2:
14494 break;
14495
14496 default:
14497 /* this function allow single channel gain only */
14498 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL,
14499 getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL));
14500 return MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL;
14501 }
14502 switch (actState)
14503 {
14504 case 0:
14505 actuatorSet = DISABLE_DPD_ACTUATOR;
14506 break;
14507 case 1:
14508 actuatorSet = ENABLE_DPD_ACTUATOR;
14509 break;
14510
14511 default:
14512 /* this function allow single channel gain only */
14513 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_STATE,
14514 getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_STATE));
14515 return MYKONOS_ERR_SETDPDACT_INV_STATE;
14516 }
14517
14518 extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_CONTROL;
14519 extData[1] = actuatorSet;
14520 extData[2] = (uint8_t)txChannel;
14521
14522 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData));
14523 if (retVal != MYKONOS_ERR_OK)
14524 {
14525 return retVal;
14526 }
14527
14528 /* check for completion */
14529 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte);
14530 if (retVal != MYKONOS_ERR_OK)
14531 {
14532 if (cmdStatusByte > 0)
14533 {
14534 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_ARMERRFLAG,
14535 getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_ARMERRFLAG));
14536 return MYKONOS_ERR_SETDPDACT_ARMERRFLAG;
14537 }
14538
14539 return retVal;
14540 }
14541
14542 if (cmdStatusByte > 0)
14543 {
14544 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_ARMERRFLAG,
14545 getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_ARMERRFLAG));
14546 return MYKONOS_ERR_SETDPDACT_ARMERRFLAG;
14547 }
14548
14549 return MYKONOS_ERR_OK;
14550 }
14551
14552 /**
14553 * \brief This function resets the DPD model.
14554 *
14555 * This function allows the user to reset the DPD actuator and prior model in radioOn or radioOff mode.
14556 * The reset can restore prior model if the parameter passed is set to 2: this resets DPD first and then restores the previously loaded
14557 * model into ARM memory for use with subsequent iterations of DPD.
14558 *
14559 * If reset is 1 then the reset function just reset the DPD actuator and not use any model.
14560 *
14561 * \pre A DPD-enabled transceiver is required for DPD to be enabled. DPD init cal has been run and DPD tracking enable.
14562 *
14563 * <B>Dependencies</B>
14564 * - device->spiSettings->chipSelectIndex
14565 *
14566 * \param device is structure pointer to the Mykonos data structure containing settings
14567 * \param txChannel Desired Transmit channel to be reseted (Valid ENUM values: TX1, TX2 or TX1_TX2)
14568 * \param reset is the required reset condition that is needed, the available options are given by the enum
14569 * ::mykonosDpdResetMode_t
14570 *
14571 * \retval MYKONOS_ERR_RESETDPD_INV_TXCHANNEL: Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2)
14572 * \retval MYKONOS_ERR_RESETDPD_WRONG_PARAM ERROR: reset parameter is not valid (Valid values: MYK_DPD_RESET_FULL, MYK_DPD_RESET_PRIOR or MYK_DPD_RESET_CORRELATOR)
14573 * \retval MYKONOS_ERR_RESETDPD_ARMERRFLAG ERROR: ARM command flag error set
14574 * \retval MYKONOS_ERR_OK Function completed successfully
14575 */
MYKONOS_resetDpd(mykonosDevice_t * device,mykonosTxChannels_t txChannel,mykonosDpdResetMode_t reset)14576 mykonosErr_t MYKONOS_resetDpd(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdResetMode_t reset)
14577 {
14578 mykonosErr_t retVal = MYKONOS_ERR_OK;
14579 uint32_t timeoutMs = 1000;
14580 uint8_t extData[3] = {0};
14581 uint8_t cmdStatusByte = 0;
14582
14583 #if (MYKONOS_VERBOSE == 1)
14584 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetDpd()\n");
14585 #endif
14586
14587 switch (txChannel)
14588 {
14589 case TX1:
14590 break;
14591 case TX2:
14592 break;
14593 case TX1_TX2:
14594 break;
14595
14596 default:
14597 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESETDPD_INV_TXCHANNEL,
14598 getMykonosErrorMessage(MYKONOS_ERR_RESETDPD_INV_TXCHANNEL));
14599 return MYKONOS_ERR_RESETDPD_INV_TXCHANNEL;
14600 }
14601
14602 if ((reset >= MYK_DPD_RESET_END) || (reset == MYK_DPD_NO_ACTION))
14603 {
14604 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESETDPD_WRONG_PARAM,
14605 getMykonosErrorMessage(MYKONOS_ERR_RESETDPD_WRONG_PARAM));
14606 return MYKONOS_ERR_RESETDPD_WRONG_PARAM;
14607 }
14608
14609 /* instruct ARM to reset DPD Model */
14610 extData[0] = MYKONOS_ARM_OBJECTID_GS_TRACKCALS;
14611 extData[1] = MYKONOS_ARM_DPD_RESET;
14612 extData[2] = (uint8_t)(reset << 2) + (uint8_t)txChannel;
14613
14614 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData));
14615 if (retVal != MYKONOS_ERR_OK)
14616 {
14617 return retVal;
14618 }
14619
14620 /* wait max of 1sec for command to complete */
14621 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte);
14622 if (retVal != MYKONOS_ERR_OK)
14623 {
14624 if (cmdStatusByte > 0)
14625 {
14626 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESETDPD_ARMERRFLAG,
14627 getMykonosErrorMessage(MYKONOS_ERR_RESETDPD_ARMERRFLAG));
14628 return MYKONOS_ERR_RESETDPD_ARMERRFLAG;
14629 }
14630 return retVal;
14631 }
14632
14633 return MYKONOS_ERR_OK;
14634 }
14635 /**
14636 * \brief This function will configure CLGC settings
14637 *
14638 * A DPD-enabled transceiver is required for CLGC to be enabled. The CLGC has several user
14639 * adjustable settings that can be configured before running the runInitCals
14640 * with the calMask set for the CLGC init cal. Call this function with desired
14641 * settings set before running the CLGC init cal or enabling CLGC tracking.
14642 *
14643 * This function can be called in either Radio On or Off state.
14644 *
14645 * <B>Dependencies</B>
14646 * - device->spiSettings->chipSelectIndex
14647 * - device->profilesValid
14648 * - device->tx->clgcConfig (All members)
14649 *
14650 * \retval MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV ERROR: Tx and ObsRx profiles must be valid to use the CLGC feature
14651 * \retval MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT ERROR: CLGC config structure pointer is null in device->tx->clgcConfig
14652 * \retval MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN ERROR: CLGC tx1DesiredGain or tx2DesiredGain parameter is out of range
14653 * \retval MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT ERROR: CLGC tx1AttenLimit or tx2AttenLimit parameter is out of range
14654 * \retval MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO ERROR: clgcControlRatio parameter is out of range
14655 * \retval MYKONOS_ERR_CFGCLGC_INV_THRESHOLD Error: tx1RelThreshold or tx2RelThreshold parameter is out of range
14656 * \retval MYKONOS_ERR_OK Function completed successfully
14657 */
MYKONOS_configClgc(mykonosDevice_t * device)14658 mykonosErr_t MYKONOS_configClgc(mykonosDevice_t *device)
14659 {
14660 mykonosErr_t retVal = MYKONOS_ERR_OK;
14661 uint8_t armFieldValue[4] = {0};
14662 uint8_t byteOffset = 0;
14663 uint16_t negPnLevel = 0;
14664 uint32_t radioStatus = 0x00;
14665
14666 #if (MYKONOS_VERBOSE == 1)
14667 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_configClgc()\n");
14668 #endif
14669
14670 /* CLGC requires Tx and ORx enabled, throw error if both are not enabled */
14671 if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID))
14672 {
14673 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV,
14674 getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV));
14675 return MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV;
14676 }
14677
14678 if (device->tx->clgcConfig == NULL)
14679 {
14680 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT,
14681 getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT));
14682 return MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT;
14683 }
14684
14685 /* set CLGC desired gain parameter */
14686 if ((device->tx->clgcConfig->tx1DesiredGain < -10000) || (device->tx->clgcConfig->tx1DesiredGain > 10000) || (device->tx->clgcConfig->tx2DesiredGain < -10000)
14687 || (device->tx->clgcConfig->tx2DesiredGain > 10000))
14688 {
14689 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN,
14690 getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN));
14691 return MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN;
14692 }
14693
14694 armFieldValue[0] = (device->tx->clgcConfig->tx1DesiredGain & 0xFF);
14695 armFieldValue[1] = (((uint16_t)device->tx->clgcConfig->tx1DesiredGain >> 8) & 0xFF);
14696 armFieldValue[2] = (device->tx->clgcConfig->tx2DesiredGain & 0xFF);
14697 armFieldValue[3] = (((uint16_t)device->tx->clgcConfig->tx2DesiredGain >> 8) & 0xFF);
14698
14699 byteOffset = 0;
14700 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue));
14701 if (retVal != MYKONOS_ERR_OK)
14702 {
14703 return retVal;
14704 }
14705
14706 /* set CLGC Tx Atten limit parameter */
14707 if ((device->tx->clgcConfig->tx1AttenLimit > 40) || (device->tx->clgcConfig->tx2AttenLimit > 40))
14708 {
14709 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT,
14710 getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT));
14711 return MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT;
14712 }
14713
14714 armFieldValue[0] = (device->tx->clgcConfig->tx1AttenLimit & 0xFF);
14715 armFieldValue[1] = ((device->tx->clgcConfig->tx1AttenLimit >> 8) & 0xFF);
14716 armFieldValue[2] = (device->tx->clgcConfig->tx2AttenLimit & 0xFF);
14717 armFieldValue[3] = ((device->tx->clgcConfig->tx2AttenLimit >> 8) & 0xFF);
14718
14719 byteOffset = 8;
14720 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue));
14721 if (retVal != MYKONOS_ERR_OK)
14722 {
14723 return retVal;
14724 }
14725
14726 /* set CLGC Control Ratio parameter */
14727 if ((device->tx->clgcConfig->tx1ControlRatio < 1) || (device->tx->clgcConfig->tx1ControlRatio > 100) || (device->tx->clgcConfig->tx2ControlRatio < 1)
14728 || (device->tx->clgcConfig->tx2ControlRatio > 100))
14729 {
14730 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO,
14731 getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO));
14732 return MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO;
14733 }
14734
14735 armFieldValue[0] = (device->tx->clgcConfig->tx1ControlRatio & 0xFF);
14736 armFieldValue[1] = ((device->tx->clgcConfig->tx1ControlRatio >> 8) & 0xFF);
14737 armFieldValue[2] = (device->tx->clgcConfig->tx2ControlRatio & 0xFF);
14738 armFieldValue[3] = ((device->tx->clgcConfig->tx2ControlRatio >> 8) & 0xFF);
14739
14740 byteOffset = 12;
14741 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue));
14742 if (retVal != MYKONOS_ERR_OK)
14743 {
14744 return retVal;
14745 }
14746
14747 /* set enable threshold for channel 1 */
14748 armFieldValue[0] = (device->tx->clgcConfig->tx1RelThresholdEn > 0) ? 1 : 0;
14749 byteOffset = 0x24;
14750 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 1);
14751 if (retVal != MYKONOS_ERR_OK)
14752 {
14753 return retVal;
14754 }
14755
14756 /* set enable threshold for channel 2 */
14757 armFieldValue[0] = (device->tx->clgcConfig->tx2RelThresholdEn > 0) ? 1 : 0;
14758 byteOffset = 0x26;
14759 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 1);
14760 if (retVal != MYKONOS_ERR_OK)
14761 {
14762 return retVal;
14763 }
14764
14765 /* set thresholds */
14766 if ((device->tx->clgcConfig->tx1RelThreshold > 10000) || (device->tx->clgcConfig->tx2RelThreshold > 10000))
14767 {
14768 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_THRESHOLD,
14769 getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_THRESHOLD));
14770 return MYKONOS_ERR_CFGCLGC_INV_THRESHOLD;
14771 }
14772
14773 /* set threshold for channel 1 */
14774 armFieldValue[0] = (device->tx->clgcConfig->tx1RelThreshold & 0xFF);
14775 armFieldValue[1] = ((device->tx->clgcConfig->tx1RelThreshold >> 8) & 0xFF);
14776 byteOffset = 0x28;
14777 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 2);
14778 if (retVal != MYKONOS_ERR_OK)
14779 {
14780 return retVal;
14781 }
14782
14783 /* set threshold for channel 2 */
14784 armFieldValue[0] = (device->tx->clgcConfig->tx2RelThreshold & 0xFF);
14785 armFieldValue[1] = ((device->tx->clgcConfig->tx2RelThreshold >> 8) & 0xFF);
14786 byteOffset = 0x2A;
14787 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 2);
14788 if (retVal != MYKONOS_ERR_OK)
14789 {
14790 return retVal;
14791 }
14792
14793 if ((device->tx->clgcConfig->pathDelayPnSeqLevel < 1) || (device->tx->clgcConfig->pathDelayPnSeqLevel > 8191))
14794 {
14795 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL,
14796 getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL));
14797 return MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL;
14798 }
14799
14800 /* read radio state to make sure ARM is in radioOff /IDLE */
14801 retVal = MYKONOS_getRadioState(device, &radioStatus);
14802 if (retVal != MYKONOS_ERR_OK)
14803 {
14804 return retVal;
14805 }
14806
14807 /* Radio state check */
14808 if (((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_IDLE) || ((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_READY))
14809 {
14810 /* set CLGC additional delay offset parameter (init cal)*/
14811 if ((device->tx->clgcConfig->additionalDelayOffset < -64) || (device->tx->clgcConfig->additionalDelayOffset > 64))
14812 {
14813 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY,
14814 getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY));
14815 return MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY;
14816 }
14817
14818 armFieldValue[0] = (device->tx->clgcConfig->additionalDelayOffset & 0xFF);
14819 armFieldValue[1] = (((uint16_t)device->tx->clgcConfig->additionalDelayOffset >> 8) & 0xFF);
14820 byteOffset = 2;
14821 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armFieldValue[0], 2);
14822 if (retVal != MYKONOS_ERR_OK)
14823 {
14824 return retVal;
14825 }
14826
14827 if ((device->tx->clgcConfig->pathDelayPnSeqLevel < 1) || (device->tx->clgcConfig->pathDelayPnSeqLevel > 8191))
14828 {
14829 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL,
14830 getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL));
14831 return MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL;
14832 }
14833
14834 /* Can not be changed in radio on */
14835 /* Set Path Delay PN sequence amplitude - positive and negative (init cal)*/
14836 armFieldValue[0] = (device->tx->clgcConfig->pathDelayPnSeqLevel & 0xFF);
14837 armFieldValue[1] = ((device->tx->clgcConfig->pathDelayPnSeqLevel >> 8) & 0xFF);
14838
14839 negPnLevel = ((~device->tx->clgcConfig->pathDelayPnSeqLevel) + 1); /* times -1 */
14840 armFieldValue[2] = (negPnLevel & 0xFF);
14841 armFieldValue[3] = (((negPnLevel) >> 8) & 0xFF);
14842 byteOffset = 10;
14843 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue));
14844 if (retVal != MYKONOS_ERR_OK)
14845 {
14846 return retVal;
14847 }
14848
14849 retVal = enableClgcTracking(device, ((device->tx->clgcConfig->allowTx1AttenUpdates > 0) ? 1 : 0), ((device->tx->clgcConfig->allowTx2AttenUpdates > 0) ? 1 : 0));
14850 if (retVal != MYKONOS_ERR_OK)
14851 {
14852 return retVal;
14853 }
14854 }
14855 else
14856 {
14857 /* record warning about not updated members */
14858 CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE,
14859 getMykonosErrorMessage(MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE));
14860 }
14861
14862 return MYKONOS_ERR_OK;
14863 }
14864
14865 /* \brief Reads the CLGC config structure from ARM memory
14866 *
14867 * This function reads the Closed Loop Gain Control structure
14868 * from ARM memory and returns in the device->tx->clgcConfig structure.
14869 *
14870 * A DPD-enabled transceiver is required for CLGC to be enabled.
14871 *
14872 * <B>Dependencies</B>
14873 * - device->spiSettings->chipSelectIndex
14874 * - device->profilesValid
14875 * - device->tx->clgcConfig (All members)
14876 *
14877 * \param device is structure pointer to the Mykonos data structure containing settings
14878 *
14879 * \retval MYKONOS_ERR_OK Function completed successfully
14880 * \retval MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV Error: Tx and ORx profiles must be valid for CLGC functions
14881 * \retval MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT Error: NULL pointer to device->tx->clgcConfig structure
14882 */
MYKONOS_getClgcConfig(mykonosDevice_t * device)14883 mykonosErr_t MYKONOS_getClgcConfig(mykonosDevice_t *device)
14884 {
14885 uint16_t byteOffset = 0;
14886 uint8_t armMem[16] = {0};
14887 mykonosErr_t retVal = MYKONOS_ERR_OK;
14888
14889 #if (MYKONOS_VERBOSE == 1)
14890 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getClgcConfig()\n");
14891 #endif
14892
14893 /* CLGC requires Tx and ORx enabled, throw error if both are not enabled */
14894 if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID))
14895 {
14896 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV,
14897 getMykonosErrorMessage(MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV));
14898 return MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV;
14899 }
14900
14901 if (device->tx->clgcConfig == NULL)
14902 {
14903 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT,
14904 getMykonosErrorMessage(MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT));
14905 return MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT;
14906 }
14907
14908 byteOffset = 0;
14909 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], sizeof(armMem));
14910 if (retVal != MYKONOS_ERR_OK)
14911 {
14912 return retVal;
14913 }
14914
14915 device->tx->clgcConfig->tx1DesiredGain = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0]));
14916 device->tx->clgcConfig->tx2DesiredGain = (int16_t)(((uint16_t)(armMem[3]) << 8) | (uint16_t)(armMem[2]));
14917 device->tx->clgcConfig->tx1AttenLimit = (((uint16_t)(armMem[9]) << 8) | (uint16_t)(armMem[8]));
14918 device->tx->clgcConfig->tx2AttenLimit = (((uint16_t)(armMem[11]) << 8) | (uint16_t)(armMem[10]));
14919 device->tx->clgcConfig->tx1ControlRatio = (((uint16_t)(armMem[13]) << 8) | (uint16_t)(armMem[12]));
14920 device->tx->clgcConfig->tx2ControlRatio = (((uint16_t)(armMem[15]) << 8) | (uint16_t)(armMem[14]));
14921
14922 byteOffset = 2;
14923 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armMem[0], 2);
14924 if (retVal != MYKONOS_ERR_OK)
14925 {
14926 return retVal;
14927 }
14928
14929 device->tx->clgcConfig->additionalDelayOffset = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0]));
14930
14931 byteOffset = 10;
14932 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armMem[0], 2);
14933 if (retVal != MYKONOS_ERR_OK)
14934 {
14935 return retVal;
14936 }
14937
14938 device->tx->clgcConfig->pathDelayPnSeqLevel = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0]));
14939
14940 /* need to figure out if this are the right addresses */
14941 byteOffset = 0x24;
14942 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 1);
14943 if (retVal != MYKONOS_ERR_OK)
14944 {
14945 return retVal;
14946 }
14947
14948 device->tx->clgcConfig->tx1RelThresholdEn = (uint8_t)armMem[0];
14949
14950 byteOffset = 0x26;
14951 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 1);
14952 if (retVal != MYKONOS_ERR_OK)
14953 {
14954 return retVal;
14955 }
14956
14957 device->tx->clgcConfig->tx2RelThresholdEn = (uint8_t)armMem[0];
14958
14959 byteOffset = 0x28;
14960 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 2);
14961 if (retVal != MYKONOS_ERR_OK)
14962 {
14963 return retVal;
14964 }
14965
14966 device->tx->clgcConfig->tx1RelThreshold = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0]));
14967
14968 byteOffset = 0x2A;
14969 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 2);
14970 if (retVal != MYKONOS_ERR_OK)
14971 {
14972 return retVal;
14973 }
14974
14975 device->tx->clgcConfig->tx2RelThreshold = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0]));
14976
14977 return MYKONOS_ERR_OK;
14978 }
14979
14980 /**
14981 * \brief This function reads the CLGC calibration status from the Mykonos ARM processor.
14982 *
14983 * The Closed Loop Gain Control Status is read back from the ARM processor and
14984 * returned in the function parameter clgcStatus.
14985 *
14986 * A DPD-enabled transceiver is required for this feature to be enabled.
14987 *
14988 * <B>Dependencies</B>
14989 * - device->spiSettings->chipSelectIndex
14990 *
14991 * \param device is structure pointer to the Mykonos data structure containing settings
14992 * \param txChannel Desired Transmit channel to read back CLGC status for (Valid ENUM values: TX1 or TX2 only)
14993 * \param clgcStatus Pointer to a structure to return the status information to
14994 *
14995 * \retval MYKONOS_ERR_OK Function completed successfully
14996 * \retval MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM clgcStatus function parameter is a NULL pointer
14997 * \retval MYKONOS_ERR_GETCLGCSTATUS_INV_CH txChannel parameter is a non supported value.
14998 * \retval MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG ARM reported an error while processing the GET ARM command
14999 */
MYKONOS_getClgcStatus(mykonosDevice_t * device,mykonosTxChannels_t txChannel,mykonosClgcStatus_t * clgcStatus)15000 mykonosErr_t MYKONOS_getClgcStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosClgcStatus_t *clgcStatus)
15001 {
15002 uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_CLGCCONFIG, 0};
15003 uint8_t armData[52] = {0};
15004 uint32_t timeoutMs = 0;
15005 uint8_t cmdStatusByte = 0;
15006 uint32_t offset = 0;
15007 mykonosErr_t retVal = MYKONOS_ERR_OK;
15008 uint8_t channelSelect = 0;
15009
15010 #if (MYKONOS_VERBOSE == 1)
15011 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getClgcStatus()\n");
15012 #endif
15013
15014 if (clgcStatus == NULL)
15015 {
15016 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM,
15017 getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM));
15018 return MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM;
15019 }
15020
15021 switch (txChannel)
15022 {
15023 case TX1:
15024 channelSelect = 0;
15025 break;
15026 case TX2:
15027 channelSelect = 1;
15028 break;
15029 default:
15030 {
15031 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_INV_CH,
15032 getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_INV_CH));
15033 return MYKONOS_ERR_GETCLGCSTATUS_INV_CH;
15034 }
15035 }
15036
15037 extData[2] = channelSelect;
15038
15039 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
15040 if (retVal != MYKONOS_ERR_OK)
15041 {
15042 return retVal;
15043 }
15044
15045 timeoutMs = 1000;
15046 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
15047 if (retVal != MYKONOS_ERR_OK)
15048 {
15049 if (cmdStatusByte > 0)
15050 {
15051 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG,
15052 getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG));
15053 return MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG;
15054 }
15055
15056 return retVal;
15057 }
15058
15059 if (cmdStatusByte > 0)
15060 {
15061 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG,
15062 getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG));
15063 return MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG;
15064 }
15065
15066 /* read status from ARM memory */
15067 offset = 0;
15068 retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armData[0], sizeof(armData), 1);
15069 if (retVal != MYKONOS_ERR_OK)
15070 {
15071 return retVal;
15072 }
15073
15074 clgcStatus->errorStatus = ((uint32_t)(armData[3]) << 24) | ((uint32_t)(armData[2]) << 16) | ((uint32_t)(armData[1]) << 8) | (uint32_t)(armData[0]);
15075 clgcStatus->desiredGain = (int32_t)(((uint32_t)(armData[23]) << 24) | ((uint32_t)(armData[22]) << 16) | ((uint32_t)(armData[21]) << 8) | (uint32_t)(armData[20]));
15076 clgcStatus->currentGain = (int32_t)(((uint32_t)(armData[27]) << 24) | ((uint32_t)(armData[26]) << 16) | ((uint32_t)(armData[25]) << 8) | (uint32_t)(armData[24]));
15077 clgcStatus->txGain = ((uint32_t)(armData[39]) << 24) | ((uint32_t)(armData[38]) << 16) | ((uint32_t)(armData[37]) << 8) | (uint32_t)(armData[36]);
15078 clgcStatus->txRms = (int32_t)(((uint32_t)(armData[43]) << 24) | ((uint32_t)(armData[42]) << 16) | ((uint32_t)(armData[41]) << 8) | (uint32_t)(armData[40]));
15079 clgcStatus->orxRms = (int32_t)(((uint32_t)(armData[47]) << 24) | ((uint32_t)(armData[46]) << 16) | ((uint32_t)(armData[45]) << 8) | (uint32_t)(armData[44]));
15080 clgcStatus->trackCount = ((uint32_t)(armData[51]) << 24) | ((uint32_t)(armData[50]) << 16) | ((uint32_t)(armData[49]) << 8) | (uint32_t)(armData[48]);
15081
15082 return retVal;
15083 }
15084
15085 /**
15086 * \brief This private helper function called during RadioOff, will allow CLGC tracking to be scheduled
15087 * by the ARM when back in the RadioOn state.
15088 *
15089 * This function sets a flag in the ARM memory that if the enableDpd tracking cal mask
15090 * and this setting are both set, then the ARM will schedule closed loop gain control
15091 * tracking to occur in the radioOn ARM state.
15092 *
15093 * A DPD-enabled transceiver is required for this feature to be enabled.
15094 *
15095 * <B>Dependencies</B>
15096 * - device->spiSettings->chipSelectIndex
15097 * - device->tx->dpdConfig
15098 *
15099 * \param device is structure pointer to the Mykonos data structure containing settings
15100 * \param tx1Enable 0=disable CLGC Tx1 tracking, 1= enable CLGC Tx1 tracking
15101 * \param tx2Enable 0=disable CLGC Tx2 tracking, 1= enable CLGC Tx2 tracking
15102 *
15103 * \retval MYKONOS_ERR_OK Function completed successfully
15104 * \retval MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR ARM is not in the RadioOff state, call MYKONOS_radioOff()
15105 */
enableClgcTracking(mykonosDevice_t * device,uint8_t tx1Enable,uint8_t tx2Enable)15106 static mykonosErr_t enableClgcTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable)
15107 {
15108 uint32_t radioStatus = 0;
15109 mykonosErr_t retVal = MYKONOS_ERR_OK;
15110 uint8_t enableBit[4] = {0};
15111 uint8_t byteOffset = 4;
15112
15113 #if (MYKONOS_VERBOSE == 1)
15114 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableClgcTracking()\n");
15115 #endif
15116
15117 /* read radio state to make sure ARM is in radioOff /IDLE */
15118 retVal = MYKONOS_getRadioState(device, &radioStatus);
15119 if (retVal != MYKONOS_ERR_OK)
15120 {
15121 return retVal;
15122 }
15123
15124 /* throw error if not in radioOff/IDLE state */
15125 if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY))
15126 {
15127 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR,
15128 getMykonosErrorMessage(MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR));
15129 return MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR;
15130 }
15131
15132 enableBit[0] = (tx1Enable > 0) ? 1 : 0;
15133 enableBit[1] = 0;
15134 enableBit[2] = (tx2Enable > 0) ? 1 : 0;
15135 enableBit[3] = 0;
15136
15137 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &enableBit[0], 4);
15138 if (retVal != MYKONOS_ERR_OK)
15139 {
15140 return retVal;
15141 }
15142
15143 return MYKONOS_ERR_OK;
15144 }
15145
15146 /**
15147 * \brief This function updates the CLGC desired gain parameter.
15148 *
15149 * This function can be called in either Radio On or Off state.
15150 *
15151 * \pre A DPD-enabled transceiver is required for CLGC to be enabled. CLGC init cal has been run and CLGC tracking enable.
15152 *
15153 * <B>Dependencies</B>
15154 * - device->spiSettings->chipSelectIndex
15155 *
15156 * \param device is structure pointer to the Mykonos data structure containing settings
15157 * \param txChannel Desired Transmit channel to set the (Valid ENUM values: TX1 or TX2 only)
15158 * \param gain Total gain and attenuation (dB * 100) for the selected channel txChannel
15159 *
15160 * \retval MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL ERROR: Tx channel is not valid (Valid ENUM values: TX1 or TX2 only)
15161 * \retval MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG ERROR: ARM command flag error set
15162 * \retval MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN ERROR: CLGC gain parameter is out of range, valid range is from -10000 to 10000.
15163 * \retval MYKONOS_ERR_OK Function completed successfully
15164 */
MYKONOS_setClgcGain(mykonosDevice_t * device,mykonosTxChannels_t txChannel,int16_t gain)15165 mykonosErr_t MYKONOS_setClgcGain(mykonosDevice_t *device, mykonosTxChannels_t txChannel, int16_t gain)
15166 {
15167 mykonosErr_t retVal = MYKONOS_ERR_OK;
15168 uint32_t timeoutMs = 1000;
15169 uint8_t extData[4] = {0};
15170 uint8_t clcgChannel = 0x00;
15171 uint8_t cmdStatusByte = 0;
15172
15173 #if (MYKONOS_VERBOSE == 1)
15174 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setClgcGain()\n");
15175 #endif
15176
15177 /* Range check for desired gain parameter */
15178 if ((gain < -10000) || (gain > 10000))
15179 {
15180 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN,
15181 getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN));
15182 return MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN;
15183 }
15184
15185 switch (txChannel)
15186 {
15187 case TX1:
15188 clcgChannel = SET_CLGC_DESIRED_GAIN_1;
15189 break;
15190 case TX2:
15191 clcgChannel = SET_CLGC_DESIRED_GAIN_2;
15192 break;
15193
15194 default:
15195 /* this function allow single channel gain only */
15196 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL,
15197 getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL));
15198 return MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL;
15199 }
15200
15201 extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_CONTROL;
15202 extData[1] = clcgChannel;
15203 extData[2] = (gain & 0xFF);
15204 extData[3] = (((uint16_t)gain >> 8) & 0xFF);
15205
15206 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData));
15207 if (retVal != MYKONOS_ERR_OK)
15208 {
15209 return retVal;
15210 }
15211
15212 /* check for completion */
15213 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte);
15214 if (retVal != MYKONOS_ERR_OK)
15215 {
15216 if (cmdStatusByte > 0)
15217 {
15218 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG,
15219 getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG));
15220 return MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG;
15221 }
15222
15223 return retVal;
15224 }
15225
15226 if (cmdStatusByte > 0)
15227 {
15228 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG,
15229 getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG));
15230 return MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG;
15231 }
15232
15233 return MYKONOS_ERR_OK;
15234 }
15235
15236 /**
15237 * \brief This function, when called during RadioOff, will configure VSWR settings
15238 *
15239 * A DPD-enabled transceiver is required for VSWR to be enabled. The VSWR has several user
15240 * adjustable settings that can be configured before running the runInitCals
15241 * with the calMask set for the VSWR init cal. Call this function with desired
15242 * settings set before running the VSWR init cal or enabling VSWR tracking.
15243 *
15244 * <B>Dependencies</B>
15245 * - device->spiSettings->chipSelectIndex
15246 * - device->profilesValid
15247 * - device->tx->vswrConfig (All members)
15248 *
15249 * \retval MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV ERROR: Tx and ObsRx profiles must be valid to use the VSWR feature
15250 * \retval MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT ERROR: CLGC config structure pointer is null in device->tx->clgcConfig
15251 * \retval MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR ERROR: ARM is not in the IDLE(radioOff) or Ready state.
15252 */
MYKONOS_configVswr(mykonosDevice_t * device)15253 mykonosErr_t MYKONOS_configVswr(mykonosDevice_t *device)
15254 {
15255 uint32_t radioStatus = 0;
15256 mykonosErr_t retVal = MYKONOS_ERR_OK;
15257 uint8_t armFieldValue[16] = {0};
15258 uint8_t byteOffset = 0;
15259 uint16_t negPnLevel = 0;
15260
15261 const uint8_t ENABLE_VSWR = 1;
15262
15263 #if (MYKONOS_VERBOSE == 1)
15264 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_configVswr()\n");
15265 #endif
15266
15267 /* VSWR requires Tx and ORx enabled, throw error if both are not enabled */
15268 if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID))
15269 {
15270 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV,
15271 getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV));
15272 return MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV;
15273 }
15274
15275 if (device->tx->vswrConfig == NULL)
15276 {
15277 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT,
15278 getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT));
15279 return MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT;
15280 }
15281
15282 /* read radio state to make sure ARM is in radioOff /IDLE */
15283 retVal = MYKONOS_getRadioState(device, &radioStatus);
15284 if (retVal != MYKONOS_ERR_OK)
15285 {
15286 return retVal;
15287 }
15288
15289 /* throw error if not in radioOff/IDLE state */
15290 if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY))
15291 {
15292 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR,
15293 getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR));
15294 return MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR;
15295 }
15296
15297 /* range check valid 3p3 GPIO pin */
15298 if ((device->tx->vswrConfig->tx1VswrSwitchGpio3p3Pin > 11) || (device->tx->vswrConfig->tx2VswrSwitchGpio3p3Pin > 11))
15299 {
15300 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN,
15301 getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN));
15302 return MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN;
15303 }
15304
15305 armFieldValue[0] = ENABLE_VSWR;
15306 armFieldValue[1] = 0;
15307 armFieldValue[2] = ENABLE_VSWR;
15308 armFieldValue[3] = 0;
15309 armFieldValue[4] = (device->tx->vswrConfig->tx1VswrSwitchGpio3p3Pin & 0xFF);
15310 armFieldValue[5] = 0;
15311 armFieldValue[6] = (device->tx->vswrConfig->tx2VswrSwitchGpio3p3Pin & 0xFF);
15312 armFieldValue[7] = 0;
15313 armFieldValue[8] = (device->tx->vswrConfig->tx1VswrSwitchPolarity > 0) ? 1 : 0;
15314 armFieldValue[9] = 0;
15315 armFieldValue[10] = (device->tx->vswrConfig->tx2VswrSwitchPolarity > 0) ? 1 : 0;
15316 armFieldValue[11] = 0;
15317 armFieldValue[12] = device->tx->vswrConfig->tx1VswrSwitchDelay_us; /* support full 0 to 255 us range */
15318 armFieldValue[13] = 0;
15319 armFieldValue[14] = device->tx->vswrConfig->tx2VswrSwitchDelay_us; /* support full 0 to 255 us range */
15320 armFieldValue[15] = 0;
15321 byteOffset = 0;
15322 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRCONFIG, byteOffset, &armFieldValue[0], 16);
15323 if (retVal != MYKONOS_ERR_OK)
15324 {
15325 return retVal;
15326 }
15327
15328 /* set VSWR additional delay offset parameter (init cal)*/
15329 if ((device->tx->vswrConfig->additionalDelayOffset < -64) || (device->tx->vswrConfig->additionalDelayOffset > 64))
15330 {
15331 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY,
15332 getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY));
15333 return MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY;
15334 }
15335
15336 armFieldValue[0] = (device->tx->vswrConfig->additionalDelayOffset & 0xFF);
15337 armFieldValue[1] = (((uint16_t)device->tx->vswrConfig->additionalDelayOffset >> 8) & 0xFF);
15338 byteOffset = 2;
15339 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armFieldValue[0], 2);
15340 if (retVal != MYKONOS_ERR_OK)
15341 {
15342 return retVal;
15343 }
15344
15345 if ((device->tx->vswrConfig->pathDelayPnSeqLevel < 1) || (device->tx->vswrConfig->pathDelayPnSeqLevel > 8191))
15346 {
15347 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL,
15348 getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL));
15349 return MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL;
15350 }
15351
15352 /* Set Path Delay PN sequence amplitude - positive and negative (init cal)*/
15353 armFieldValue[0] = (device->tx->vswrConfig->pathDelayPnSeqLevel & 0xFF);
15354 armFieldValue[1] = ((device->tx->vswrConfig->pathDelayPnSeqLevel >> 8) & 0xFF);
15355
15356 negPnLevel = ((~device->tx->vswrConfig->pathDelayPnSeqLevel) + 1); /* times -1 */
15357 armFieldValue[2] = (negPnLevel & 0xFF);
15358 armFieldValue[3] = (((negPnLevel) >> 8) & 0xFF);
15359 byteOffset = 10;
15360
15361 /* Set for Tx1 channel */
15362 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armFieldValue[0], 4);
15363 if (retVal != MYKONOS_ERR_OK)
15364 {
15365 return retVal;
15366 }
15367
15368 /* Set for Tx2 channel */
15369 byteOffset = 30;
15370 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armFieldValue[0], 4);
15371 if (retVal != MYKONOS_ERR_OK)
15372 {
15373 return retVal;
15374 }
15375
15376 return MYKONOS_ERR_OK;
15377 }
15378
15379 /* \brief Reads the VSWR config structure from ARM memory
15380 *
15381 * This function reads the VSWR structure
15382 * from ARM memory and returns in the device->tx->vswrConfig structure.
15383 *
15384 * A DPD-enabled transceiver is required for VSWR to be enabled.
15385 *
15386 * <B>Dependencies</B>
15387 * - device->spiSettings->chipSelectIndex
15388 * - device->profilesValid
15389 * - device->tx->vswrConfig (All members)
15390 *
15391 * \param device is structure pointer to the Mykonos data structure containing settings
15392 *
15393 * \retval MYKONOS_ERR_OK Function completed successfully
15394 * \retval MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV Error: Tx and ORx profiles must be valid for VSWR functions
15395 * \retval MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT Error: NULL pointer to device->tx->vswrConfig structure
15396 */
MYKONOS_getVswrConfig(mykonosDevice_t * device)15397 mykonosErr_t MYKONOS_getVswrConfig(mykonosDevice_t *device)
15398 {
15399 uint16_t byteOffset = 0;
15400 uint8_t armMem[12] = {0};
15401 mykonosErr_t retVal = MYKONOS_ERR_OK;
15402
15403 #if (MYKONOS_VERBOSE == 1)
15404 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getVswrConfig()\n");
15405 #endif
15406
15407 /* VSWR requires Tx and ORx enabled, throw error if both are not enabled */
15408 if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID))
15409 {
15410 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV,
15411 getMykonosErrorMessage(MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV));
15412 return MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV;
15413 }
15414
15415 if (device->tx->vswrConfig == NULL)
15416 {
15417 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT,
15418 getMykonosErrorMessage(MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT));
15419 return MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT;
15420 }
15421
15422 byteOffset = 4;
15423 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRCONFIG, byteOffset, &armMem[0], sizeof(armMem));
15424 if (retVal != MYKONOS_ERR_OK)
15425 {
15426 return retVal;
15427 }
15428
15429 device->tx->vswrConfig->tx1VswrSwitchGpio3p3Pin = armMem[0];
15430 device->tx->vswrConfig->tx2VswrSwitchGpio3p3Pin = armMem[2];
15431 device->tx->vswrConfig->tx1VswrSwitchPolarity = armMem[4];
15432 device->tx->vswrConfig->tx2VswrSwitchPolarity = armMem[6];
15433 device->tx->vswrConfig->tx1VswrSwitchDelay_us = armMem[8];
15434 device->tx->vswrConfig->tx2VswrSwitchDelay_us = armMem[10];
15435
15436 byteOffset = 2;
15437 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armMem[0], 2);
15438 if (retVal != MYKONOS_ERR_OK)
15439 {
15440 return retVal;
15441 }
15442
15443 device->tx->vswrConfig->additionalDelayOffset = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0]));
15444
15445 byteOffset = 10;
15446 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armMem[0], 2);
15447 if (retVal != MYKONOS_ERR_OK)
15448 {
15449 return retVal;
15450 }
15451
15452 device->tx->vswrConfig->pathDelayPnSeqLevel = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0]));
15453
15454 return MYKONOS_ERR_OK;
15455 }
15456
15457 /**
15458 * \brief This function reads the VSWR calibration status from the Mykonos ARM processor.
15459 *
15460 * The VSWR Status is read back from the ARM processor and
15461 * returned in the function parameter vswrStatus.
15462 *
15463 * A DPD-enabled transceiver is required for this feature to be enabled.
15464 *
15465 * <B>Dependencies</B>
15466 * - device->spiSettings->chipSelectIndex
15467 *
15468 * \param device is structure pointer to the Mykonos data structure containing settings
15469 * \param txChannel Desired Transmit channel to read back VSWR status for (Valid ENUM values: TX1 or TX2 only)
15470 * \param vswrStatus Pointer to a structure to return the status information to
15471 *
15472 * \retval MYKONOS_ERR_OK Function completed successfully
15473 * \retval MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM vswrStatus function parameter is a NULL pointer
15474 * \retval MYKONOS_ERR_GETVSWRSTATUS_INV_CH txChannel parameter is a non supported value.
15475 * \retval MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG ARM reported an error while processing the GET ARM command
15476 */
MYKONOS_getVswrStatus(mykonosDevice_t * device,mykonosTxChannels_t txChannel,mykonosVswrStatus_t * vswrStatus)15477 mykonosErr_t MYKONOS_getVswrStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosVswrStatus_t *vswrStatus)
15478 {
15479 uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_VSWRCONFIG, 0};
15480 uint8_t armData[64] = {0};
15481 uint32_t timeoutMs = 0;
15482 uint8_t cmdStatusByte = 0;
15483 uint32_t offset = 0;
15484 mykonosErr_t retVal = MYKONOS_ERR_OK;
15485 uint8_t channelSelect = 0;
15486
15487 #if (MYKONOS_VERBOSE == 1)
15488 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getVswrStatus()\n");
15489 #endif
15490
15491 if (vswrStatus == NULL)
15492 {
15493 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM,
15494 getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM));
15495 return MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM;
15496 }
15497
15498 switch (txChannel)
15499 {
15500 case TX1:
15501 channelSelect = 0;
15502 break;
15503 case TX2:
15504 channelSelect = 1;
15505 break;
15506 default:
15507 {
15508 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_INV_CH,
15509 getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_INV_CH));
15510 return MYKONOS_ERR_GETVSWRSTATUS_INV_CH;
15511 }
15512 }
15513
15514 extData[2] = channelSelect;
15515
15516 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
15517 if (retVal != MYKONOS_ERR_OK)
15518 {
15519 return retVal;
15520 }
15521
15522 timeoutMs = 1000;
15523 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
15524 if (retVal != MYKONOS_ERR_OK)
15525 {
15526 /* throw more specific error message instead of returning error code from waitArmCmdStatus */
15527 if (cmdStatusByte > 0)
15528 {
15529 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG,
15530 getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG));
15531 return MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG;
15532 }
15533
15534 return retVal;
15535 }
15536
15537 if (cmdStatusByte > 0)
15538 {
15539 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG,
15540 getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG));
15541 return MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG;
15542 }
15543
15544 /* read status from ARM memory */
15545 offset = 0;
15546 retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armData[0], sizeof(armData), 1);
15547 if (retVal != MYKONOS_ERR_OK)
15548 {
15549 return retVal;
15550 }
15551
15552 vswrStatus->errorStatus = ((uint32_t)(armData[3]) << 24) | ((uint32_t)(armData[2]) << 16) | ((uint32_t)(armData[1]) << 8) | (uint32_t)(armData[0]);
15553 vswrStatus->forwardGainRms_dB = (int32_t)(((uint32_t)(armData[23]) << 24) | ((uint32_t)(armData[22]) << 16) | ((uint32_t)(armData[21]) << 8) | (uint32_t)(armData[20]));
15554 vswrStatus->forwardGainReal = (int32_t)(((uint32_t)(armData[27]) << 24) | ((uint32_t)(armData[26]) << 16) | ((uint32_t)(armData[25]) << 8) | (uint32_t)(armData[24]));
15555 vswrStatus->forwardGainImag = (int32_t)(((uint32_t)(armData[31]) << 24) | ((uint32_t)(armData[30]) << 16) | ((uint32_t)(armData[29]) << 8) | (uint32_t)(armData[28]));
15556 vswrStatus->reflectedGainRms_dB = (int32_t)(((uint32_t)(armData[35]) << 24) | ((uint32_t)(armData[34]) << 16) | ((uint32_t)(armData[33]) << 8) | (uint32_t)(armData[32]));
15557 vswrStatus->reflectedGainReal = (int32_t)(((uint32_t)(armData[39]) << 24) | ((uint32_t)(armData[38]) << 16) | ((uint32_t)(armData[37]) << 8) | (uint32_t)(armData[36]));
15558 vswrStatus->reflectedGainImag = (int32_t)(((uint32_t)(armData[43]) << 24) | ((uint32_t)(armData[42]) << 16) | ((uint32_t)(armData[41]) << 8) | (uint32_t)(armData[40]));
15559 vswrStatus->trackCount = ((uint32_t)(armData[63]) << 24) | ((uint32_t)(armData[62]) << 16) | ((uint32_t)(armData[61]) << 8) | (uint32_t)(armData[60]);
15560 vswrStatus->vswr_forward_tx_rms = (int32_t)(((uint32_t)(armData[47]) << 24) | ((uint32_t)(armData[46]) << 16) | ((uint32_t)(armData[45]) << 8) | (uint32_t)(armData[44]));
15561 vswrStatus->vswr_forward_orx_rms = (int32_t)(((uint32_t)(armData[51]) << 24) | ((uint32_t)(armData[50]) << 16) | ((uint32_t)(armData[49]) << 8) | (uint32_t)(armData[48]));
15562 vswrStatus->vswr_reflection_tx_rms = (int32_t)(((uint32_t)(armData[55]) << 24) | ((uint32_t)(armData[54]) << 16) | ((uint32_t)(armData[53]) << 8) | (uint32_t)(armData[52]));
15563 vswrStatus->vswr_reflection_orx_rms = (int32_t)(((uint32_t)(armData[59]) << 24) | ((uint32_t)(armData[58]) << 16) | ((uint32_t)(armData[57]) << 8) | (uint32_t)(armData[56]));
15564
15565 return MYKONOS_ERR_OK;
15566 }
15567
15568 /**
15569 * \brief Read from the Mykonos ARM program or data memory
15570 *
15571 * Valid memory addresses are: Program Memory (0x01000000 - 0x01017FFF),
15572 * Data Memory (0x20000000 - 0x2000FFFF)
15573 *
15574 * <B>Dependencies</B>
15575 * - device->spiSettings->chipSelectIndex
15576 * - device->spiSettings
15577 *
15578 * \param device is structure pointer to the Mykonos data structure containing settings
15579 * \param address The 32bit ARM address to read from.
15580 * \param returnData Byte(uint8_t) array containing the data read from the ARM memory.
15581 * \param bytesToRead Number of bytes in the returnData array.
15582 * \param autoIncrement is boolean flag to enable or disable autoincrement of ARM register address
15583 *
15584 * \retval MYKONOS_ERR_OK Function completed successfully
15585 * \retval MYKONOS_ERR_READARMMEM_INV_ADDR_PARM ARM memory address is out of range
15586 *
15587 */
MYKONOS_readArmMem(mykonosDevice_t * device,uint32_t address,uint8_t * returnData,uint32_t bytesToRead,uint8_t autoIncrement)15588 mykonosErr_t MYKONOS_readArmMem(mykonosDevice_t *device, uint32_t address, uint8_t *returnData, uint32_t bytesToRead, uint8_t autoIncrement)
15589 {
15590 uint8_t dataMem;
15591 uint32_t i;
15592
15593 #if (MYKONOS_VERBOSE == 1)
15594 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readArmMem()\n");
15595 #endif
15596
15597 /* check that start and stop address are in valid range */
15598 if ((!(address >= MYKONOS_ADDR_ARM_START_PROG_ADDR && address <= MYKONOS_ADDR_ARM_END_PROG_ADDR))
15599 && !(address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR))
15600 {
15601 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMMEM_INV_ADDR_PARM,
15602 getMykonosErrorMessage(MYKONOS_ERR_READARMMEM_INV_ADDR_PARM));
15603 return MYKONOS_ERR_READARMMEM_INV_ADDR_PARM;
15604 }
15605
15606 if ((!(((address + bytesToRead - 1) >= MYKONOS_ADDR_ARM_START_PROG_ADDR) && (address + bytesToRead - 1) <= MYKONOS_ADDR_ARM_END_PROG_ADDR))
15607 && (!(((address + bytesToRead - 1) >= MYKONOS_ADDR_ARM_START_DATA_ADDR) && (address + bytesToRead - 1) <= MYKONOS_ADDR_ARM_END_DATA_ADDR)))
15608 {
15609 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMMEM_INV_ADDR_PARM,
15610 getMykonosErrorMessage(MYKONOS_ERR_READARMMEM_INV_ADDR_PARM));
15611 return MYKONOS_ERR_READARMMEM_INV_ADDR_PARM;
15612 }
15613
15614 if (address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR)
15615 {
15616 dataMem = 1;
15617 }
15618 else
15619 {
15620 dataMem = 0;
15621 }
15622
15623 /* NOT assuming auto increment bit is already set from MYKONOS_initARM function call */
15624 /* setting auto increment address bit if autoIncrement evaluates true */
15625 if (autoIncrement)
15626 {
15627 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x01, 0x04, 2);
15628 }
15629 else
15630 {
15631 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x00, 0x04, 2);
15632 }
15633
15634 /* setting up for ARM read */
15635 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x01, 0x20, 5);
15636 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)((address) >> 2)); /* write address[9:2] */
15637 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, (uint8_t)(address >> 10) | (uint8_t)(dataMem << 7)); /* write address[15:10] */
15638
15639 /* start read-back at correct byte offset */
15640 /* read data is located at SPI address 0xD04=data[7:0], 0xD05=data[15:8], 0xD06=data[23:16], 0xD07=data[31:24]. */
15641 /* with address auto increment set, after xD07 is read, the address will automatically increment */
15642 /* without address auto increment set, 0x4 must be added to the address for correct indexing */
15643 if (autoIncrement)
15644 {
15645 for (i = 0; i < bytesToRead; i++)
15646 {
15647 CMB_SPIReadByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), &returnData[i]);
15648 }
15649 }
15650 else
15651 {
15652 for (i = 0; i < bytesToRead; i++)
15653 {
15654 CMB_SPIReadByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), &returnData[i]);
15655
15656 if ((MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)) == MYKONOS_ADDR_ARM_DATA_BYTE_3)
15657 {
15658 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)(((address + 0x4) & 0x3FF) >> 2));
15659 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, ((address + 0x4) & 0x1FC00U) >> 10 | (uint8_t)(dataMem << 7));
15660 }
15661 }
15662 }
15663
15664 return MYKONOS_ERR_OK;
15665 }
15666
15667 /**
15668 * \brief Write to the Mykonos ARM program or data memory
15669 *
15670 * Valid memory addresses are: Program Memory (0x01000000 - 0x01017FFF),
15671 * Data Memory (0x20000000 - 0x2000FFFF)
15672 *
15673 * <B>Dependencies</B>
15674 * - device->spiSettings->chipSelectIndex
15675 * - device->spiSettings
15676 *
15677 * \param device is structure pointer to the Mykonos data structure containing settings
15678 * \param address The 32bit ARM address to write to.
15679 * \param data Byte(uint8_t) array containing the data to write to the ARM memory.
15680 * \param byteCount Number of bytes in the data array.
15681 *
15682 * \retval MYKONOS_ERR_OK Function completed successfully
15683 * \retval MYKONOS_ERR_WRITEARMMEM_NULL_PARM Function parameter data has NULL pointer when byteCount is >0
15684 * \retval MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM ARM memory address is out of range of valid ARM memory
15685 */
MYKONOS_writeArmMem(mykonosDevice_t * device,uint32_t address,uint8_t * data,uint32_t byteCount)15686 mykonosErr_t MYKONOS_writeArmMem(mykonosDevice_t *device, uint32_t address, uint8_t *data, uint32_t byteCount)
15687 {
15688 /* write address, then data with auto increment enabled. */
15689 uint8_t dataMem;
15690 uint32_t i;
15691
15692 #if MYK_ENABLE_SPIWRITEARRAY == 1
15693 uint32_t addrIndex = 0;
15694 uint32_t dataIndex = 0;
15695 uint32_t spiBufferSize = MYK_SPIWRITEARRAY_BUFFERSIZE;
15696 uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0};
15697 #endif
15698
15699 #if (MYKONOS_VERBOSE == 1)
15700 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_writeArmMem()\n");
15701 #endif
15702
15703 if ((data == NULL) && (byteCount > 0))
15704 {
15705 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMMEM_NULL_PARM,
15706 getMykonosErrorMessage(MYKONOS_ERR_WRITEARMMEM_NULL_PARM));
15707 return MYKONOS_ERR_WRITEARMMEM_NULL_PARM;
15708 }
15709
15710 if ((!(address >= MYKONOS_ADDR_ARM_START_PROG_ADDR && address <= MYKONOS_ADDR_ARM_END_PROG_ADDR))
15711 && !(address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR))
15712 {
15713 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM,
15714 getMykonosErrorMessage(MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM));
15715 return MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM;
15716 }
15717
15718 if ((!(((address + byteCount - 1) >= MYKONOS_ADDR_ARM_START_PROG_ADDR) && ((address + byteCount - 1) <= MYKONOS_ADDR_ARM_END_PROG_ADDR)))
15719 && (!(((address + byteCount - 1) >= MYKONOS_ADDR_ARM_START_DATA_ADDR) && ((address + byteCount - 1) <= MYKONOS_ADDR_ARM_END_DATA_ADDR))))
15720 {
15721 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM,
15722 getMykonosErrorMessage(MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM));
15723 return MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM;
15724 }
15725
15726 if (address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR)
15727 {
15728 dataMem = 1;
15729 }
15730 else
15731 {
15732 dataMem = 0;
15733 }
15734
15735 /* set auto increment address bit */
15736 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x01, 0x04, 2);
15737
15738 /* writing the address */
15739 CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x00, 0x20, 5);
15740 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)((address) >> 2));
15741 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, (uint8_t)(address >> 10) | (uint8_t)(dataMem << 7));
15742
15743 /* start write at correct byte offset */
15744 /* write data is located at SPI address 0xD04=data[7:0], 0xD05=data[15:8], 0xD06=data[23:16], 0xD07=data[31:24] */
15745 /* with address auto increment set, after x407 is written, the address will automatically increment */
15746
15747 #if (MYK_ENABLE_SPIWRITEARRAY == 0)
15748
15749 for (i = 0; i < byteCount; i++)
15750 {
15751 CMB_SPIWriteByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), data[i]);
15752 }
15753
15754 #elif (MYK_ENABLE_SPIWRITEARRAY == 1)
15755
15756 addrIndex = 0;
15757 dataIndex = 0;
15758 for (i = 0; i < byteCount; i++)
15759 {
15760 addrArray[addrIndex++] = (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4));
15761
15762 if (addrIndex == spiBufferSize)
15763 {
15764 CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &data[dataIndex], addrIndex);
15765 dataIndex = dataIndex + addrIndex;
15766 addrIndex = 0;
15767 }
15768 }
15769
15770 if (addrIndex > 0)
15771 {
15772 CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &data[dataIndex], addrIndex);
15773 }
15774
15775 #endif
15776
15777 return MYKONOS_ERR_OK;
15778 }
15779
15780 /**
15781 * \brief Low level helper function used by Mykonos API to write the ARM memory config structures
15782 *
15783 * Normally this function should not be required to be used directly by the BBIC. This is a helper
15784 * function used by other Mykonos API commands to write settings into the ARM memory.
15785 *
15786 * <B>Dependencies</B>
15787 * - device->spiSettings->chipSelectIndex
15788 * - device->spiSettings
15789 *
15790 * \param device is structure pointer to the Mykonos data structure containing settings
15791 * \param objectId ARM id of a particular structure or setting in ARM memory
15792 * \param offset Byte offset from the start of the objectId's memory location in ARM memory
15793 * \param data A byte array containing data to write to the ARM memory buffer.
15794 * \param byteCount Number of bytes in the data array (Valid size = 1-255 bytes)
15795 *
15796 * \retval MYKONOS_ERR_OK Function completed successfully
15797 * \retval MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG ARM write config command failed with a nonzero error code
15798 */
MYKONOS_writeArmConfig(mykonosDevice_t * device,uint8_t objectId,uint16_t offset,uint8_t * data,uint8_t byteCount)15799 mykonosErr_t MYKONOS_writeArmConfig(mykonosDevice_t *device, uint8_t objectId, uint16_t offset, uint8_t *data, uint8_t byteCount)
15800 {
15801 mykonosErr_t retVal = MYKONOS_ERR_OK;
15802 uint8_t extendedData[4] = {0}; /* ARM Object id, byte offset LSB, offset MSB = 0, copy 2 bytes */
15803 uint32_t timeoutMs = 1000;
15804 uint8_t cmdStatusByte = 0;
15805
15806 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &data[0], byteCount);
15807 if (retVal != MYKONOS_ERR_OK)
15808 {
15809 return retVal;
15810 }
15811
15812 extendedData[0] = objectId;
15813 extendedData[1] = (offset & 0xFF);
15814 extendedData[2] = ((offset >> 8) & 0xFF);
15815 extendedData[3] = byteCount;
15816 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_WRITECFG_OPCODE, &extendedData[0], sizeof(extendedData));
15817 if (retVal != MYKONOS_ERR_OK)
15818 {
15819 return retVal;
15820 }
15821
15822 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_WRITECFG_OPCODE, timeoutMs, &cmdStatusByte);
15823 if (retVal != MYKONOS_ERR_OK)
15824 {
15825 if (cmdStatusByte > 0)
15826 {
15827 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG,
15828 getMykonosErrorMessage(MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG));
15829 return MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG;
15830 }
15831
15832 return retVal;
15833 }
15834
15835 if (cmdStatusByte > 0)
15836 {
15837 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG,
15838 getMykonosErrorMessage(MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG));
15839 return MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG;
15840 }
15841
15842 return MYKONOS_ERR_OK;
15843 }
15844
15845 /**
15846 * \brief Low level helper function used by Mykonos API to read the ARM memory config structures
15847 *
15848 * Normally this function should not be required to be used directly by the BBIC. This is a helper
15849 * function used by other Mykonos API commands to read settings from the ARM memory.
15850 *
15851 * <B>Dependencies</B>
15852 * - device->spiSettings->chipSelectIndex
15853 * - device->spiSettings
15854 *
15855 * \param device is structure pointer to the Mykonos data structure containing settings
15856 * \param objectId ARM id of a particular structure or setting in ARM memory
15857 * \param offset Byte offset from the start of the objectId's memory location in ARM memory
15858 * \param data A byte array containing data to write to the ARM memory buffer.
15859 * \param byteCount Number of bytes in the data array (Valid size = 1-255 bytes)
15860 *
15861 * \retval MYKONOS_ERR_OK Function completed successfully
15862 * \retval MYKONOS_ERR_READARMCFG_ARMERRFLAG ARM read config command failed with a nonzero error code
15863 */
MYKONOS_readArmConfig(mykonosDevice_t * device,uint8_t objectId,uint16_t offset,uint8_t * data,uint8_t byteCount)15864 mykonosErr_t MYKONOS_readArmConfig(mykonosDevice_t *device, uint8_t objectId, uint16_t offset, uint8_t *data, uint8_t byteCount)
15865 {
15866 mykonosErr_t retVal = MYKONOS_ERR_OK;
15867 uint8_t extendedData[4] = {0}; /* ARM Object id, byte offset LSB, offset MSB = 0, copy 2 bytes */
15868 uint32_t timeoutMs = 1000;
15869 uint8_t cmdStatusByte = 0;
15870 const uint8_t AUTO_INCREMENT = 1;
15871 extendedData[0] = objectId;
15872 extendedData[1] = (offset & 0xFF);
15873 extendedData[2] = ((offset >> 8) & 0xFF);
15874 extendedData[3] = byteCount;
15875
15876 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_READCFG_OPCODE, &extendedData[0], sizeof(extendedData));
15877 if (retVal != MYKONOS_ERR_OK)
15878 {
15879 return retVal;
15880 }
15881
15882 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_READCFG_OPCODE, timeoutMs, &cmdStatusByte);
15883 if (retVal != MYKONOS_ERR_OK)
15884 {
15885 if (cmdStatusByte > 0)
15886 {
15887 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCFG_ARMERRFLAG,
15888 getMykonosErrorMessage(MYKONOS_ERR_READARMCFG_ARMERRFLAG));
15889 return MYKONOS_ERR_READARMCFG_ARMERRFLAG;
15890 }
15891
15892 return retVal;
15893 }
15894
15895 if (cmdStatusByte > 0)
15896 {
15897 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCFG_ARMERRFLAG,
15898 getMykonosErrorMessage(MYKONOS_ERR_READARMCFG_ARMERRFLAG));
15899 return MYKONOS_ERR_READARMCFG_ARMERRFLAG;
15900 }
15901
15902 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &data[0], byteCount, AUTO_INCREMENT);
15903
15904 return retVal;
15905 }
15906
15907 /**
15908 * \brief Sends a command to the Mykonos ARM processor
15909 *
15910 * <B>Dependencies</B>
15911 * - device->spiSettings->chipSelectIndex
15912 * - device->spiSettings
15913 *
15914 * \param device is structure pointer to the Mykonos data structure containing settings
15915 * \param opCode Value (0-30, even only) indicating the desired function to run in the ARM.
15916 * \param extendedData A byte array containing extended data to write to the ARM command interface.
15917 * \param extendedDataNumBytes Number of bytes in the extendedData array (Valid size = 0-4 bytes)
15918 *
15919 * \retval MYKONOS_ERR_OK Function completed successfully
15920 * \retval MYKONOS_ERR_ARMCMD_NULL_PARM Function parameter extendedData is NULL and extendedDataNumBytes is positive
15921 * \retval MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM ARM opcode is out of range (valid 0-30, even only)
15922 * \retval MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM Number of extended bytes parameter is out of range (valid 0-4)
15923 * \retval MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY ARM control interface is busy, command could not be executed by ARM
15924 */
MYKONOS_sendArmCommand(mykonosDevice_t * device,uint8_t opCode,uint8_t * extendedData,uint8_t extendedDataNumBytes)15925 mykonosErr_t MYKONOS_sendArmCommand(mykonosDevice_t *device, uint8_t opCode, uint8_t *extendedData, uint8_t extendedDataNumBytes)
15926 {
15927 uint8_t armCommandBusy = 0;
15928 uint8_t i = 0;
15929 uint16_t extCmdByteStartAddr = MYKONOS_ADDR_ARM_EXT_CMD_BYTE_1;
15930
15931 #if (MYKONOS_VERBOSE == 1)
15932 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_sendArmCommand()\n");
15933 #endif
15934
15935 if ((extendedData == NULL) && (extendedDataNumBytes > 0))
15936 {
15937 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMD_NULL_PARM, getMykonosErrorMessage(MYKONOS_ERR_ARMCMD_NULL_PARM));
15938 return MYKONOS_ERR_ARMCMD_NULL_PARM;
15939 }
15940
15941 /* check for even-numbered opCodes only including opcode 0, but not must be greater than opCode 30 */
15942 if ((opCode != 0) && ((opCode % 2) || (opCode > 30)))
15943 {
15944 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM,
15945 getMykonosErrorMessage(MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM));
15946 return MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM;
15947 }
15948
15949 /* the number of valid extended data bytes is from 0-4 */
15950 if (extendedDataNumBytes > 4)
15951 {
15952 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM,
15953 getMykonosErrorMessage(MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM));
15954 return MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM;
15955 }
15956
15957 /* setting a 2 sec timeout for mailbox busy bit to be clear (can't send an arm mailbox command until mailbox is ready) */
15958 CMB_setTimeout_ms(device->spiSettings, 2000);
15959
15960 do
15961 {
15962 CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_ARM_CMD, &armCommandBusy, 0x80, 7);
15963
15964 if (CMB_hasTimeoutExpired(device->spiSettings))
15965 {
15966 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY,
15967 getMykonosErrorMessage(MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY));
15968 return MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY;
15969 }
15970 } while (armCommandBusy);
15971
15972 if (extendedDataNumBytes)
15973 {
15974 for (i = 0; i < extendedDataNumBytes; i++)
15975 {
15976 CMB_SPIWriteByte(device->spiSettings, extCmdByteStartAddr + i, extendedData[i]);
15977 }
15978 }
15979
15980 CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CMD, opCode);
15981
15982 return MYKONOS_ERR_OK;
15983 }
15984
15985 /**
15986 * \brief Reads the Mykonos ARM 64-bit command status register
15987 *
15988 * A 64-bit status register consisting of a pending bit and three-bit error type is read one byte at
15989 * a time for opcodes 0-30. The function parses the pending bits and error bits into
15990 * two (2) separate 16-bit words containing pending bits, and error bits if the error type > 0
15991 * The words are weighted according to each even-numbered opcode from 0-30,
15992 * where, 0x0001 = opcode '0', 0x0002 = opcode '2', 0x0004 = opcode '4', 0x0008 = opcode '6' and so on.
15993 *
15994 * <B>Dependencies</B>
15995 * - device->spiSettings->chipSelectIndex
15996 *
15997 * \param device is a pointer to the device settings structure
15998 * \param errorWord 16-bit error word comprised of weighted bits according to each opcode number
15999 * The weighted bit = '1' if error type > 0, '0' if OK
16000 * \param statusWord 16-bit pending bits word comprised of weighted bits according to each opcode number
16001 *
16002 * \retval MYKONOS_ERR_OK Function completed successfully
16003 * \retval MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM Function parameters errorWord or statusWord have a NULL pointer
16004 */
MYKONOS_readArmCmdStatus(mykonosDevice_t * device,uint16_t * errorWord,uint16_t * statusWord)16005 mykonosErr_t MYKONOS_readArmCmdStatus(mykonosDevice_t *device, uint16_t *errorWord, uint16_t *statusWord)
16006 {
16007 uint8_t i = 0;
16008 uint8_t bytes[8] = {0};
16009
16010 #if (MYKONOS_VERBOSE == 1)
16011 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readArmCmdStatus()\n");
16012 #endif
16013
16014 if (errorWord == NULL || statusWord == NULL)
16015 {
16016 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM,
16017 getMykonosErrorMessage(MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM));
16018 return MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM;
16019 }
16020
16021 /* making sure the errorWord and statusWord are clear */
16022 *errorWord = 0;
16023 *statusWord = 0;
16024
16025 /* read in the entire 64-bit status register into a byte array for parsing */
16026 for (i = 0; i < 8; i++)
16027 {
16028 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_CMD_STATUS_0 + i, &bytes[i]);
16029 }
16030
16031 /* parse the byte array for pending bits and error types and generate statusWord and errorWord bits */
16032 for (i = 0; i < 8; i++)
16033 {
16034 *statusWord |= (uint16_t)((uint16_t)(((bytes[i] & 0x10) >> 3) | (bytes[i] & 0x01)) << (i * 2));
16035
16036 if (bytes[i] & 0x0E)
16037 {
16038 *errorWord |= (uint16_t)(0x0001 << (i * 2));
16039 }
16040 else if (bytes[i] & 0xE0)
16041 {
16042 *errorWord |= (uint16_t)(0x0002 << (i * 2));
16043 }
16044 }
16045
16046 return MYKONOS_ERR_OK;
16047 }
16048
16049 /**
16050 * \brief Isolated byte read of the Mykonos ARM 64-bit command status register based on the opcode
16051 *
16052 * A single byte read is performed on the 64-bit command status register according to
16053 * the opcode of interest. The pending bit and the error type are extracted from the status
16054 * register and returned as a single byte in the lower nibble.
16055 *
16056 * <B>Dependencies</B>
16057 * - device->spiSettings->chipSelectIndex
16058 *
16059 * \param device is a pointer to the device settings structure
16060 * \param opCode Valid values are even increments from 0-30. The ARM opCode is used to determine which status register byte to read
16061 * \param cmdStatByte returns cmdStatByte[3:1] = error type, cmdStatByte[0] = pending flag for selected opCode
16062 *
16063 * \retval MYKONOS_ERR_OK Function completed successfully
16064 * \retval MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM Function parameter cmdStatByte has NULL pointer
16065 * \retval MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM ARM opcode is out of range (valid 0-30, even only)
16066 */
MYKONOS_readArmCmdStatusByte(mykonosDevice_t * device,uint8_t opCode,uint8_t * cmdStatByte)16067 mykonosErr_t MYKONOS_readArmCmdStatusByte(mykonosDevice_t *device, uint8_t opCode, uint8_t *cmdStatByte)
16068 {
16069 uint8_t cmdByteIndex = 0;
16070 uint8_t cmdByte = 0;
16071
16072 #if 0
16073 #if (MYKONOS_VERBOSE == 1)
16074 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readArmCmdStatByte()\n");
16075 #endif
16076 #endif
16077
16078 if (cmdStatByte == NULL)
16079 {
16080 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM,
16081 getMykonosErrorMessage(MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM));
16082 return MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM;
16083 }
16084
16085 /* check for even-numbered opCodes only including opcode 0, but not must be greater than opCode 30 */
16086 if ((opCode != 0) && ((opCode % 2) || (opCode > 30)))
16087 {
16088 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM,
16089 getMykonosErrorMessage(MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM));
16090 return MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM;
16091 }
16092 else
16093 {
16094 cmdByteIndex = (opCode / 4);
16095
16096 CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_CMD_STATUS_0 + cmdByteIndex, &cmdByte);
16097
16098 if ((opCode / 2) % 2)
16099 {
16100 *cmdStatByte = ((cmdByte >> 4) & 0x0F);
16101 }
16102 else
16103 {
16104 *cmdStatByte = (cmdByte & 0x0F);
16105 }
16106
16107 return MYKONOS_ERR_OK;
16108 }
16109 }
16110
16111 /**
16112 * \brief Mykonos ARM command status wait function polls command status until opcode completes
16113 *
16114 * <B>Dependencies</B>
16115 * - device->spiSettings->chipSelectIndex
16116 *
16117 * \param device is a pointer to the device settings structure
16118 * \param opCode Valid values are even increments from 0-30. The ARM opCode is used to determine which pending bit to wait for
16119 * \param timeoutMs conveys the time-out period in milliseconds
16120 * \param cmdStatByte returns cmdStatByte[3:1] = error type, cmdStatByte[0] = pending flag for selected opCode
16121 *
16122 * \retval MYKONOS_ERR_OK Function completed successfully
16123 * \retval MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM Function parameter cmdStatByte has NULL pointer
16124 * \retval MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM Invalid ARM opcode (valid 0-30, even numbers only)
16125 * \retval MYKONOS_ERR_ARMCMDSTATUS_ARMERROR ARM Mailbox error flag for requested opcode returned a nonzero error flag
16126 * \retval MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT Timeout occurred before ARM command completed
16127 */
MYKONOS_waitArmCmdStatus(mykonosDevice_t * device,uint8_t opCode,uint32_t timeoutMs,uint8_t * cmdStatByte)16128 mykonosErr_t MYKONOS_waitArmCmdStatus(mykonosDevice_t *device, uint8_t opCode, uint32_t timeoutMs, uint8_t *cmdStatByte)
16129 {
16130 mykonosErr_t retVal = MYKONOS_ERR_OK;
16131
16132 #if (MYKONOS_VERBOSE == 1)
16133 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_waitArmCmdStatus()\n");
16134 #endif
16135
16136 if (cmdStatByte == NULL)
16137 {
16138 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM,
16139 getMykonosErrorMessage(MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM));
16140 return MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM;
16141 }
16142
16143 /* check for even-numbered opCodes only including opcode 0, but not must be greater than opCode 30 */
16144 if ((opCode != 0) && ((opCode % 2) || (opCode > 30)))
16145 {
16146 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM,
16147 getMykonosErrorMessage(MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM));
16148 return MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM;
16149 }
16150
16151 /* start wait */
16152 CMB_setTimeout_ms(device->spiSettings, timeoutMs);
16153
16154 do
16155 {
16156 retVal = MYKONOS_readArmCmdStatusByte(device, opCode, cmdStatByte);
16157 if (retVal != MYKONOS_ERR_OK)
16158 {
16159 return retVal;
16160 }
16161
16162 /* If error flag is non zero in [3:1], - return error */
16163 if ((*cmdStatByte & 0x0E) > 0)
16164 {
16165 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMDSTATUS_ARMERROR,
16166 getMykonosErrorMessage(MYKONOS_ERR_ARMCMDSTATUS_ARMERROR));
16167 return MYKONOS_ERR_ARMCMDSTATUS_ARMERROR;
16168 }
16169
16170 if (CMB_hasTimeoutExpired(device->spiSettings))
16171 {
16172 return MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT;
16173 }
16174 } while (*cmdStatByte & 0x01);
16175
16176 return MYKONOS_ERR_OK;
16177 }
16178
16179 /**
16180 * \brief Mykonos ARM configuration write
16181 *
16182 * <B>Dependencies</B>
16183 * - device->spiSettings->chipSelectIndex
16184 *
16185 * \param device is a pointer to the device settings structure
16186 *
16187 * \retval MYKONOS_ERR_OK Function completed successfully
16188 */
MYKONOS_writeArmProfile(mykonosDevice_t * device)16189 mykonosErr_t MYKONOS_writeArmProfile(mykonosDevice_t *device)
16190 {
16191 const uint8_t length = 100;
16192
16193 int32_t i = 0;
16194 uint8_t vcoDiv = 0;
16195 uint8_t hsDiv = 0;
16196 uint16_t channelsEnabled = 0;
16197 uint8_t cfgData[100] = {0};
16198
16199 mykonosErr_t retVal = MYKONOS_ERR_OK;
16200
16201 #if (MYKONOS_VERBOSE == 1)
16202 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_writeArmConfig()\n");
16203 #endif
16204
16205 /* reading in required mykonosDevice_t structure data into array - not pretty but it works */
16206 for (i = 0; i < 4; i++)
16207 {
16208 cfgData[i] = (uint8_t)(((device->clocks->deviceClock_kHz * 1000) >> (i * 8)) & 0x000000FF);
16209 }
16210
16211 for (i = 4; i < 8; i++)
16212 {
16213 cfgData[i] = (uint8_t)(((device->clocks->clkPllVcoFreq_kHz) >> ((i - 4) * 8)) & 0x000000FF);
16214 }
16215
16216 vcoDiv = (uint8_t)(device->clocks->clkPllVcoDiv);
16217 hsDiv = device->clocks->clkPllHsDiv;
16218
16219 cfgData[8] = vcoDiv; /* uint8_t vco_div */
16220 cfgData[9] = hsDiv; /* uint8_t hs_div */
16221
16222 channelsEnabled |= ((uint16_t)device->tx->txChannels & 0x03);
16223 channelsEnabled |= ((uint16_t)device->rx->rxChannels & 0x03) << 2;
16224 if (device->profilesValid & ORX_PROFILE_VALID)
16225 {
16226 channelsEnabled |= (((uint16_t)device->obsRx->obsRxChannelsEnable & 3) << 4);
16227 }
16228
16229 if (device->profilesValid & SNIFF_PROFILE_VALID)
16230 {
16231 channelsEnabled |= ((((uint16_t)device->obsRx->obsRxChannelsEnable >> 2) & 7) << 6);
16232 }
16233
16234 for (i = 10; i < 12; i++)
16235 {
16236 cfgData[i] = (uint8_t)((channelsEnabled >> ((i - 10) * 8)) & 0xFF);
16237 }
16238
16239 cfgData[12] = ((device->rx->rxPllUseExternalLo & 0x01) << 1) | (device->tx->txPllUseExternalLo & 0x01);
16240 cfgData[13] = 0x00; /* Not used...padding */
16241 cfgData[14] = 0x00; /* Not used...padding */
16242 cfgData[15] = 0x00; /* Not used...padding */
16243
16244 if (device->profilesValid & TX_PROFILE_VALID)
16245 {
16246 /* start of Tx profile data */
16247 cfgData[16] = (uint8_t)device->tx->txProfile->dacDiv;
16248 cfgData[17] = device->tx->txProfile->txFirInterpolation;
16249 cfgData[18] = device->tx->txProfile->thb1Interpolation;
16250 cfgData[19] = device->tx->txProfile->thb2Interpolation;
16251
16252 for (i = 20; i < 24; i++)
16253 {
16254 cfgData[i] = (uint8_t)(((device->tx->txProfile->iqRate_kHz * 1000) >> ((i - 20) * 8)) & 0x000000FF);
16255 }
16256
16257 for (i = 24; i < 28; i++)
16258 {
16259 cfgData[i] = (uint8_t)(((device->tx->txProfile->primarySigBandwidth_Hz) >> ((i - 24) * 8)) & 0x000000FF);
16260 }
16261
16262 for (i = 28; i < 32; i++)
16263 {
16264 cfgData[i] = (uint8_t)(((device->tx->txProfile->rfBandwidth_Hz) >> ((i - 28) * 8)) & 0x000000FF);
16265 }
16266
16267 for (i = 32; i < 36; i++)
16268 {
16269 cfgData[i] = (uint8_t)(((device->tx->txProfile->txDac3dBCorner_kHz) >> ((i - 32) * 8)) & 0x000000FF);
16270 }
16271
16272 for (i = 36; i < 40; i++)
16273 {
16274 cfgData[i] = (uint8_t)(((device->tx->txProfile->txBbf3dBCorner_kHz * 1000) >> ((i - 36) * 8)) & 0x000000FF);
16275 }
16276 }
16277 else
16278 {
16279 cfgData[16] = 0;
16280 cfgData[17] = 0;
16281 cfgData[18] = 0;
16282 cfgData[19] = 0;
16283 cfgData[20] = 0;
16284 cfgData[21] = 0;
16285 cfgData[22] = 0;
16286 cfgData[23] = 0;
16287 cfgData[24] = 0;
16288 cfgData[25] = 0;
16289 cfgData[26] = 0;
16290 cfgData[27] = 0;
16291 cfgData[28] = 0;
16292 cfgData[29] = 0;
16293 cfgData[30] = 0;
16294 cfgData[31] = 0;
16295 cfgData[32] = 0;
16296 cfgData[33] = 0;
16297 cfgData[34] = 0;
16298 cfgData[35] = 0;
16299 cfgData[36] = 0;
16300 cfgData[37] = 0;
16301 cfgData[38] = 0;
16302 cfgData[39] = 0;
16303 }
16304
16305 if (device->profilesValid & RX_PROFILE_VALID)
16306 {
16307 /* start of Rx profile data */
16308 cfgData[40] = device->rx->rxProfile->adcDiv;
16309 cfgData[41] = device->rx->rxProfile->rxFirDecimation;
16310 cfgData[42] = device->rx->rxProfile->rxDec5Decimation;
16311 cfgData[43] = device->rx->rxProfile->rhb1Decimation;
16312
16313 for (i = 44; i < 48; i++)
16314 {
16315 cfgData[i] = (uint8_t)(((device->rx->rxProfile->iqRate_kHz * 1000) >> ((i - 44) * 8)) & 0x000000FF);
16316 }
16317
16318 for (i = 48; i < 52; i++)
16319 {
16320 /* sig bw placeholder */
16321 cfgData[i] = (uint8_t)(((device->rx->rxProfile->rfBandwidth_Hz) >> ((i - 48) * 8)) & 0x000000FF);
16322 }
16323
16324 for (i = 52; i < 56; i++)
16325 {
16326 cfgData[i] = (uint8_t)(((device->rx->rxProfile->rfBandwidth_Hz) >> ((i - 52) * 8)) & 0x000000FF);
16327 }
16328
16329 for (i = 56; i < 60; i++)
16330 {
16331 cfgData[i] = (uint8_t)(((device->rx->rxProfile->rxBbf3dBCorner_kHz * 1000) >> ((i - 56) * 8)) & 0x000000FF);
16332 }
16333 }
16334 else
16335 {
16336 cfgData[40] = 0;
16337 cfgData[41] = 0;
16338 cfgData[42] = 0;
16339 cfgData[43] = 0;
16340 cfgData[44] = 0;
16341 cfgData[45] = 0;
16342 cfgData[46] = 0;
16343 cfgData[47] = 0;
16344 cfgData[48] = 0;
16345 cfgData[49] = 0;
16346 cfgData[50] = 0;
16347 cfgData[51] = 0;
16348 cfgData[52] = 0;
16349 cfgData[53] = 0;
16350 cfgData[54] = 0;
16351 cfgData[55] = 0;
16352 cfgData[56] = 0;
16353 cfgData[57] = 0;
16354 cfgData[58] = 0;
16355 cfgData[59] = 0;
16356 }
16357
16358 if (device->profilesValid & ORX_PROFILE_VALID)
16359 {
16360 /* start of ObsRx profile data */
16361 cfgData[60] = device->obsRx->orxProfile->adcDiv;
16362 cfgData[61] = device->obsRx->orxProfile->rxFirDecimation;
16363 cfgData[62] = device->obsRx->orxProfile->rxDec5Decimation;
16364 cfgData[63] = device->obsRx->orxProfile->rhb1Decimation;
16365
16366 for (i = 64; i < 68; i++)
16367 {
16368 cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->iqRate_kHz * 1000) >> ((i - 64) * 8)) & 0x000000FF);
16369 }
16370
16371 for (i = 68; i < 72; i++)
16372 {
16373 /* sig bw placeholder */
16374 cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->rfBandwidth_Hz) >> ((i - 68) * 8)) & 0x000000FF);
16375 }
16376
16377 for (i = 72; i < 76; i++)
16378 {
16379 cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->rfBandwidth_Hz) >> ((i - 72) * 8)) & 0x000000FF);
16380 }
16381
16382 for (i = 76; i < 80; i++)
16383 {
16384 cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->rxBbf3dBCorner_kHz * 1000) >> ((i - 76) * 8)) & 0x000000FF);
16385 }
16386 }
16387 else
16388 {
16389 cfgData[60] = 0;
16390 cfgData[61] = 0;
16391 cfgData[62] = 0;
16392 cfgData[63] = 0;
16393 cfgData[64] = 0;
16394 cfgData[65] = 0;
16395 cfgData[66] = 0;
16396 cfgData[67] = 0;
16397 cfgData[68] = 0;
16398 cfgData[69] = 0;
16399 cfgData[70] = 0;
16400 cfgData[71] = 0;
16401 cfgData[72] = 0;
16402 cfgData[73] = 0;
16403 cfgData[74] = 0;
16404 cfgData[75] = 0;
16405 cfgData[76] = 0;
16406 cfgData[77] = 0;
16407 cfgData[78] = 0;
16408 cfgData[79] = 0;
16409 }
16410
16411 if (device->profilesValid & SNIFF_PROFILE_VALID)
16412 {
16413 /* start of SnRx profile data */
16414 cfgData[80] = device->obsRx->snifferProfile->adcDiv;
16415 cfgData[81] = device->obsRx->snifferProfile->rxFirDecimation;
16416 cfgData[82] = device->obsRx->snifferProfile->rxDec5Decimation;
16417 cfgData[83] = device->obsRx->snifferProfile->rhb1Decimation;
16418
16419 for (i = 84; i < 88; i++)
16420 {
16421 cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->iqRate_kHz * 1000) >> ((i - 84) * 8)) & 0x000000FF);
16422 }
16423
16424 for (i = 88; i < 92; i++)
16425 {
16426 /* sig bw placeholder */
16427 cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->rfBandwidth_Hz) >> ((i - 88) * 8)) & 0x000000FF);
16428 }
16429
16430 for (i = 92; i < 96; i++)
16431 {
16432 cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->rfBandwidth_Hz) >> ((i - 92) * 8)) & 0x000000FF);
16433 }
16434
16435 for (i = 96; i < 100; i++)
16436 {
16437 cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->rxBbf3dBCorner_kHz * 1000) >> ((i - 96) * 8)) & 0x000000FF);
16438 }
16439 }
16440 else
16441 {
16442 cfgData[80] = 0;
16443 cfgData[81] = 0;
16444 cfgData[82] = 0;
16445 cfgData[83] = 0;
16446 cfgData[84] = 0;
16447 cfgData[85] = 0;
16448 cfgData[86] = 0;
16449 cfgData[87] = 0;
16450 cfgData[88] = 0;
16451 cfgData[89] = 0;
16452 cfgData[90] = 0;
16453 cfgData[91] = 0;
16454 cfgData[92] = 0;
16455 cfgData[93] = 0;
16456 cfgData[94] = 0;
16457 cfgData[95] = 0;
16458 cfgData[96] = 0;
16459 cfgData[97] = 0;
16460 cfgData[98] = 0;
16461 cfgData[99] = 0;
16462 }
16463
16464 /* writing to the ARM memory with the array data */
16465 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &cfgData[0], length);
16466
16467 return retVal;
16468 }
16469
16470 /**
16471 * \brief Function called automatically that loads the ADC profiles into the ARM
16472 *
16473 * User should not need to call this function normally. It is called automatically
16474 * during MYKONOS_initArm() to load the ADC profiles (tunes the ADC performance).
16475 *
16476 * Rx ADC profile is only loaded if the Rx Profile is valid, ORx ADC profile is
16477 * only loaded if the ORx Profile is valid. Sniffer ADC profile is only loaded
16478 * if the Sniffer profile is valid. The Loopback ADC profile is always
16479 * loaded. If Tx profile is valid, the loopback ADC profile is chosen based
16480 * on the Tx Primary Signal bandwidth. If no valid Tx Profile, the Rx profile
16481 * is used to set the Loopback ADC profile. Else, ORx, then sniffer profiles
16482 * are used to set the loopback ADC profile.
16483 *
16484 * <B>Dependencies</B>
16485 * - device->spiSettings->chipSelectIndex
16486 *
16487 * \param device Pointer to the device settings structure
16488 *
16489 * \retval MYKONOS_ERR_OK Function completed successfully
16490 * \retval MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV Mykonos CLKPLL has invalid VCO divider in the clocks structure
16491 * \retval MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE When Tx Profile used, a matching ORx Profile must be provided with a valid ADC divider.
16492 * The ORx digital filters and clock dividers are used with the Loopback Rx path for Tx calibrations.
16493 * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED ADC Profile Lookup table does not have a match
16494 * for current Rx Profile settings. Custom ADC profile required
16495 * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED ADC Profile Lookup table does not have a match
16496 * for current ORx Profile settings. Custom ADC profile required
16497 * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED ADC Profile Lookup table does not have a match
16498 * for current Sniffer Rx Profile settings. Custom ADC profile required
16499 * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED ADC Profile Lookup table does not have a match
16500 * for Loopback passband BW and ADC Clock frequency settings. Custom ADC profile required
16501 * \retval MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO Rx Profile has invalid ADC divider = 0, causing a divide by zero error
16502 * \retval MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO ORx profile has invalid ADC divider = 0, causing a divide by zero error
16503 * \retval MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO Sniffer profile has invalid ADC divider = 0, causing a divide by zero error
16504 * \retval MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED Error returned while trying to write Rx ADC profile to ARM memory
16505 * \retval MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED Error returned while trying to write ORx ADC profile to ARM memory
16506 * \retval MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED Error returned while trying to write Sniffer ADC profile into ARM memory
16507 * \retval MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED Error returned while trying to write Loopback ADC profile into ARM memory
16508 */
MYKONOS_loadAdcProfiles(mykonosDevice_t * device)16509 mykonosErr_t MYKONOS_loadAdcProfiles(mykonosDevice_t *device)
16510 {
16511 uint8_t adcProfile[32] = {0};
16512 uint8_t i = 0;
16513 mykonosErr_t retVal = MYKONOS_ERR_OK;
16514 uint32_t hsDigClk_MHz = 0;
16515 uint32_t adcClk_MHz = 0;
16516 uint32_t vcoDiv = 0;
16517 uint32_t vcoDivTimes10 = 10;
16518 uint8_t profileIndex = 0;
16519 const uint8_t ARM_CONFIG_OFFSET = 100; /* number of bytes written in MYKONOS_writeArmProfile() to ARM memory */
16520
16521 const uint8_t NUM_ADCPROFILE_COEFS = 16;
16522 const uint8_t NUM_ADC_PROFILES = 20;
16523 static const uint16_t adcProfileLut[20][18] = {
16524 /* Max RFBW, ADCCLK_MHz, adcProfile[16] */
16525 { 20, 491, 1494, 564, 201, 98, 1280, 134, 945, 40, 529, 10, 326, 39, 30, 16, 9, 201},
16526 { 60, 983, 712, 462, 201, 98, 1280, 291, 1541, 149, 1054, 46, 645, 34, 48, 32, 18, 193},
16527 { 75, 983, 680, 477, 201, 98, 1280, 438, 1577, 242, 1046, 73, 636, 30, 48, 31, 18, 192},
16528 {100, 983, 655, 446, 201, 98, 1280, 336, 1631, 334, 1152, 207, 733, 33, 48, 32, 21, 212},
16529 { 75, 1228, 569, 369, 201, 98, 1280, 291, 1541, 149, 1320, 58, 807, 34, 48, 40, 23, 189},
16530 {100, 1228, 534, 386, 201, 98, 1280, 491, 1591, 279, 1306, 104, 792, 28, 48, 39, 23, 187},
16531 {160, 1228, 491, 375, 201, 98, 1280, 514, 1728, 570, 1455, 443, 882, 27, 48, 39, 25, 205},
16532 {200, 1228, 450, 349, 201, 98, 1280, 730, 1626, 818, 1476, 732, 834, 20, 41, 36, 24, 200},
16533 { 80, 1250, 555, 365, 201, 98, 1280, 317, 1547, 165, 1341, 65, 819, 33, 48, 40, 24, 188},
16534 {102, 1250, 524, 379, 201, 98, 1280, 494, 1592, 281, 1328, 107, 805, 28, 48, 40, 23, 187},
16535 { 80, 1333, 526, 339, 201, 98, 1280, 281, 1539, 143, 1433, 60, 877, 35, 48, 43, 25, 188},
16536 {217, 1333, 414, 321, 201, 98, 1280, 730, 1626, 818, 1603, 794, 905, 20, 41, 40, 26, 199},
16537 { 75, 1474, 486, 302, 199, 98, 1280, 206, 1523, 101, 1578, 47, 977, 37, 48, 48, 28, 186},
16538 {100, 1474, 465, 311, 201, 98, 1280, 353, 1556, 187, 1581, 86, 964, 32, 48, 47, 28, 185},
16539 {150, 1474, 436, 296, 190, 98, 1280, 336, 1631, 334, 1638, 293, 1102, 33, 48, 46, 31, 205},
16540 { 40, 1536, 479, 285, 190, 98, 1280, 112, 1505, 53, 1574, 25, 1026, 40, 48, 48, 29, 186},
16541 {100, 1536, 450, 297, 193, 98, 1280, 328, 1550, 171, 1586, 79, 1006, 33, 48, 48, 29, 184},
16542 {150, 1536, 421, 283, 182, 98, 1280, 313, 1620, 306, 1638, 269, 1153, 34, 48, 46, 33, 204},
16543 {200, 1536, 392, 299, 180, 98, 1280, 514, 1728, 570, 1638, 498, 1104, 27, 48, 44, 32, 200},
16544 {240, 1536, 366, 301, 178, 98, 1280, 686, 1755, 818, 1638, 742, 1056, 22, 45, 41, 31, 196}};
16545
16546 #if (MYKONOS_VERBOSE == 1)
16547 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_loadAdcProfiles\n");
16548 #endif
16549
16550 vcoDiv = (uint32_t)device->clocks->clkPllVcoDiv;
16551 switch (vcoDiv)
16552 {
16553 case VCODIV_1:
16554 vcoDivTimes10 = 10;
16555 break;
16556 case VCODIV_1p5:
16557 vcoDivTimes10 = 15;
16558 break;
16559 case VCODIV_2:
16560 vcoDivTimes10 = 20;
16561 break;
16562 case VCODIV_3:
16563 vcoDivTimes10 = 30;
16564 break;
16565 default:
16566 {
16567 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV,
16568 getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV));
16569 return MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV;
16570 }
16571 }
16572
16573 hsDigClk_MHz = device->clocks->clkPllVcoFreq_kHz / vcoDivTimes10 / 100 / device->clocks->clkPllHsDiv;
16574
16575 /* If Tx Profile is valid, set loopback ADC profile based on Tx primary signal BW */
16576 if ((device->profilesValid & TX_PROFILE_VALID) > 0)
16577 {
16578 /* If custom profile, load it */
16579 if (device->obsRx->customLoopbackAdcProfile != NULL)
16580 {
16581 for (i = 0; i < NUM_ADCPROFILE_COEFS; i++)
16582 {
16583 adcProfile[i * 2] = device->obsRx->customLoopbackAdcProfile[i] & 0xFF;
16584 adcProfile[i * 2 + 1] = (device->obsRx->customLoopbackAdcProfile[i] >> 8) & 0xFF;
16585 }
16586 }
16587 else
16588 {
16589 /* Tx requires ORx profile is configured */
16590 if (((device->profilesValid & TX_PROFILE_VALID) > 0) && ((device->profilesValid & ORX_PROFILE_VALID) == 0))
16591 {
16592 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE,
16593 getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE));
16594 return MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE;
16595 }
16596
16597 if (device->obsRx->orxProfile->adcDiv == 0)
16598 {
16599 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO,
16600 getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO));
16601 return MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO;
16602 }
16603
16604 adcClk_MHz = hsDigClk_MHz / device->obsRx->orxProfile->adcDiv;
16605
16606 /* find correct ADC profile in the LUT */
16607 profileIndex = NUM_ADC_PROFILES;
16608 for (i = 0; i < NUM_ADC_PROFILES; i++)
16609 {
16610 /* Find a row in the LUT that matches the ADC clock frequency */
16611 if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->tx->txProfile->primarySigBandwidth_Hz / 1000000)))
16612 {
16613 profileIndex = i;
16614 break;
16615 }
16616 }
16617
16618 /* Verify that a profile was found in the LUT, if not return error */
16619 /* In this case a custom profile would need to be passed in */
16620 if (profileIndex >= NUM_ADC_PROFILES)
16621 {
16622 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED,
16623 getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED));
16624 return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED;
16625 }
16626
16627 for (i = 0; i < NUM_ADCPROFILE_COEFS; i++)
16628 {
16629 adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF;
16630 adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF;
16631 }
16632 }
16633
16634 /* writing to the ARM memory: Set Loopback ADC Profile based on Tx Primary signal Bandwidth */
16635 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile));
16636 if (retVal)
16637 {
16638 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED,
16639 getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED));
16640 return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED;
16641 }
16642 }
16643
16644 if ((device->profilesValid & RX_PROFILE_VALID) > 0)
16645 {
16646 /* If custom profile, load it */
16647 if (device->rx->rxProfile->customAdcProfile != NULL)
16648 {
16649 for (i = 0; i < NUM_ADCPROFILE_COEFS; i++)
16650 {
16651 adcProfile[i * 2] = device->rx->rxProfile->customAdcProfile[i] & 0xFF;
16652 adcProfile[i * 2 + 1] = (device->rx->rxProfile->customAdcProfile[i] >> 8) & 0xFF;
16653 }
16654 }
16655 else
16656 {
16657 if (device->rx->rxProfile->adcDiv == 0)
16658 {
16659 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO,
16660 getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO));
16661 return MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO;
16662 }
16663
16664 adcClk_MHz = hsDigClk_MHz / device->rx->rxProfile->adcDiv;
16665
16666 /* find correct ADC profile in the LUT */
16667 profileIndex = NUM_ADC_PROFILES;
16668 for (i = 0; i < NUM_ADC_PROFILES; i++)
16669 {
16670 /* Find a row in the LUT that matches the ADC clock frequency */
16671 if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->rx->rxProfile->rfBandwidth_Hz / 1000000)))
16672 {
16673 profileIndex = i;
16674 break;
16675 }
16676 }
16677
16678 /* Verify that a profile was found in the LUT, if not return error */
16679 /* In this case a custom profile would need to be passed in */
16680 if (profileIndex >= NUM_ADC_PROFILES)
16681 {
16682 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED,
16683 getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED));
16684 return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED;
16685 }
16686
16687 for (i = 0; i < NUM_ADCPROFILE_COEFS; i++)
16688 {
16689 adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF;
16690 adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF;
16691 }
16692 }
16693
16694 /* writing to the ARM memory with ADC Profile for Rx path */
16695 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET, &adcProfile[0], sizeof(adcProfile));
16696 if (retVal)
16697 {
16698 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED,
16699 getMykonosErrorMessage(MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED));
16700 return MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED;
16701 }
16702
16703 /* writing to the ARM memory: Set Loopback ADC Profile = Rx ADC Profile ONLY if Tx profile is not valid */
16704 if ((device->profilesValid & TX_PROFILE_VALID) == 0)
16705 {
16706 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile));
16707 if (retVal)
16708 {
16709 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED,
16710 getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED));
16711 return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED;
16712 }
16713 }
16714 }
16715
16716 if ((device->profilesValid & ORX_PROFILE_VALID) > 0)
16717 {
16718 /* If custom profile, load it */
16719 if (device->obsRx->orxProfile->customAdcProfile != NULL)
16720 {
16721 for (i = 0; i < NUM_ADCPROFILE_COEFS; i++)
16722 {
16723 adcProfile[i * 2] = device->obsRx->orxProfile->customAdcProfile[i] & 0xFF;
16724 adcProfile[i * 2 + 1] = (device->obsRx->orxProfile->customAdcProfile[i] >> 8) & 0xFF;
16725 }
16726 }
16727 else
16728 {
16729 if (device->obsRx->orxProfile->adcDiv == 0)
16730 {
16731 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO,
16732 getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO));
16733 return MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO;
16734 }
16735
16736 adcClk_MHz = hsDigClk_MHz / device->obsRx->orxProfile->adcDiv;
16737
16738 /* find correct ADC profile in the LUT */
16739 profileIndex = NUM_ADC_PROFILES;
16740 for (i = 0; i < NUM_ADC_PROFILES; i++)
16741 {
16742 /* Find a row in the LUT that matches the ADC clock frequency */
16743 if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->obsRx->orxProfile->rfBandwidth_Hz / 1000000)))
16744 {
16745 profileIndex = i;
16746 break;
16747 }
16748 }
16749
16750 /* Verify that a profile was found in the LUT, if not return error */
16751 /* In this case a custom profile would need to be passed in */
16752 if (profileIndex >= NUM_ADC_PROFILES)
16753 {
16754 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED,
16755 getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED));
16756 return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED;
16757 }
16758
16759 for (i = 0; i < NUM_ADCPROFILE_COEFS; i++)
16760 {
16761 adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF;
16762 adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF;
16763 }
16764 }
16765
16766 /* writing to the ARM memory with ADC Profile for ORx path */
16767 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 32, &adcProfile[0], sizeof(adcProfile));
16768 if (retVal)
16769 {
16770 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED,
16771 getMykonosErrorMessage(MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED));
16772 return MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED;
16773 }
16774
16775 /* If Rx and Tx Profiles are not valid, set Loopback ADC profile to ORx ADC Profile */
16776 if (((device->profilesValid & TX_PROFILE_VALID) == 0) && ((device->profilesValid & RX_PROFILE_VALID) == 0))
16777 {
16778 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile));
16779 if (retVal)
16780 {
16781 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED,
16782 getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED));
16783 return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED;
16784 }
16785 }
16786 }
16787
16788 if ((device->profilesValid & SNIFF_PROFILE_VALID) > 0)
16789 {
16790 /* If custom profile, load it */
16791 if (device->obsRx->snifferProfile->customAdcProfile != NULL)
16792 {
16793 for (i = 0; i < NUM_ADCPROFILE_COEFS; i++)
16794 {
16795 adcProfile[i * 2] = device->obsRx->snifferProfile->customAdcProfile[i] & 0xFF;
16796 adcProfile[i * 2 + 1] = (device->obsRx->snifferProfile->customAdcProfile[i] >> 8) & 0xFF;
16797 }
16798 }
16799 else
16800 {
16801
16802 if (device->obsRx->snifferProfile->adcDiv == 0)
16803 {
16804 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO,
16805 getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO));
16806 return MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO;
16807 }
16808
16809 adcClk_MHz = hsDigClk_MHz / device->obsRx->snifferProfile->adcDiv;
16810
16811 /* find correct ADC profile in the LUT */
16812 profileIndex = NUM_ADC_PROFILES;
16813 for (i = 0; i < NUM_ADC_PROFILES; i++)
16814 {
16815 /* Find a row in the LUT that matches the ADC clock frequency */
16816 if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->obsRx->snifferProfile->rfBandwidth_Hz / 1000000)))
16817 {
16818 profileIndex = i;
16819 break;
16820 }
16821 }
16822
16823 /* Verify that a profile was found in the LUT, if not return error */
16824 /* In this case a custom profile would need to be passed in */
16825 if (profileIndex >= NUM_ADC_PROFILES)
16826 {
16827 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED,
16828 getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED));
16829 return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED;
16830 }
16831
16832 for (i = 0; i < NUM_ADCPROFILE_COEFS; i++)
16833 {
16834 adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF;
16835 adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF;
16836 }
16837 }
16838
16839 /* writing to the ARM memory with ADC Profile for sniffer Rx path */
16840 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 64, &adcProfile[0], sizeof(adcProfile));
16841 if (retVal)
16842 {
16843 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED,
16844 getMykonosErrorMessage(MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED));
16845 return MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED;
16846 }
16847
16848 /* If Tx, Rx, and ORx Profiles are not valid, set Loopback ADC profile to Sniffer Rx ADC Profile */
16849 if (((device->profilesValid & TX_PROFILE_VALID) == 0) && ((device->profilesValid & RX_PROFILE_VALID) == 0) && ((device->profilesValid & ORX_PROFILE_VALID) == 0))
16850 {
16851 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile));
16852 if (retVal)
16853 {
16854 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED,
16855 getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED));
16856 return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED;
16857 }
16858 }
16859 }
16860
16861 return MYKONOS_ERR_OK;
16862 }
16863
16864 /**
16865 * \brief Helper function to calculate commonly used digital clock frequencies in the device
16866 *
16867 * User should not need to call this function normally. It is called automatically
16868 * within other API functions to calculate the main digital clock. If the pointers
16869 * to the return parameters are NULL, that calculation will be skipped and not
16870 * returned.
16871 *
16872 *
16873 * <B>Dependencies</B>
16874 * -device->clocks->clkPllVcoFreq_kHz;
16875 * -device->clocks->clkPllVcoDiv;
16876 * -device->clocks->clkPllHsDiv;
16877 *
16878 * \param device Pointer to the device settings structure
16879 * \param hsDigClk_kHz Return value for the calculated Mykonos high speed Digital clock at the output of the CLKPLL in kHz
16880 * \param hsDigClkDiv4or5_kHz Return value for the Mykonos high speed digital clock divided by 4 or 5 in kHz
16881 *
16882 * \retval MYKONOS_ERR_OK Function completed successfully
16883 * \retval MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM device parameter is a NULL pointer
16884 * \retval MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT device->clocks structure is a NULL pointer
16885 * \retval MYKONOS_ERR_CLKPLL_INV_VCODIV Invalid CLKPLL VCO divider in device->clocks->clkPllVcoDiv
16886 * \retval MYKONOS_ERR_CLKPLL_INV_HSDIV Invalid CLKPLL High speed divider in device->clocks->clkPllHsDiv
16887 */
MYKONOS_calculateDigitalClocks(mykonosDevice_t * device,uint32_t * hsDigClk_kHz,uint32_t * hsDigClkDiv4or5_kHz)16888 static mykonosErr_t MYKONOS_calculateDigitalClocks(mykonosDevice_t *device, uint32_t *hsDigClk_kHz, uint32_t *hsDigClkDiv4or5_kHz)
16889 {
16890 uint32_t hsclkRate_kHz = 0;
16891 uint32_t clkPllVcoFrequency_kHz = 0;
16892 mykonosVcoDiv_t vcoDiv = VCODIV_1;
16893 uint8_t hsDiv = 4;
16894
16895 if (device == NULL)
16896 {
16897 CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM, getMykonosErrorMessage(MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM));
16898 return MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM;
16899 }
16900
16901 if ((device->clocks == NULL))
16902 {
16903 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT,
16904 getMykonosErrorMessage(MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT));
16905 return MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT;
16906 }
16907
16908 clkPllVcoFrequency_kHz = device->clocks->clkPllVcoFreq_kHz;
16909 vcoDiv = device->clocks->clkPllVcoDiv;
16910 hsDiv = device->clocks->clkPllHsDiv;
16911
16912 switch (vcoDiv)
16913 {
16914 case VCODIV_1:
16915 hsclkRate_kHz = clkPllVcoFrequency_kHz;
16916 break;
16917 case VCODIV_1p5:
16918 hsclkRate_kHz = (clkPllVcoFrequency_kHz / 15) * 10;
16919 break;
16920 case VCODIV_2:
16921 hsclkRate_kHz = clkPllVcoFrequency_kHz >> 1;
16922 break;
16923 case VCODIV_3:
16924 hsclkRate_kHz = (clkPllVcoFrequency_kHz / 30) * 10;
16925 break;
16926 default:
16927 {
16928 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_VCODIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_VCODIV));
16929 return MYKONOS_ERR_CLKPLL_INV_VCODIV;
16930 }
16931 }
16932
16933 switch (hsDiv)
16934 {
16935 case 4:
16936 hsDiv = 4;
16937 break;
16938 case 5:
16939 hsDiv = 5;
16940 break;
16941 default:
16942 {
16943 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_HSDIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_HSDIV));
16944 return MYKONOS_ERR_CLKPLL_INV_HSDIV;
16945 }
16946 }
16947
16948 if (hsDigClk_kHz != NULL)
16949 {
16950 *hsDigClk_kHz = hsclkRate_kHz / hsDiv;
16951 }
16952
16953 if (hsDigClkDiv4or5_kHz != NULL)
16954 {
16955 /* This digital div 4 or 5 is always mutually exclusive with the HS Divider (4 or 5) to always
16956 * create a /20 from the hsclk.
16957 */
16958 *hsDigClkDiv4or5_kHz = hsclkRate_kHz / 20;
16959 }
16960
16961 return MYKONOS_ERR_OK;
16962 }
16963
16964 /**
16965 * \brief Performs reset to the External Tx LO Leakage tracking calibration channel estimate
16966 *
16967 * <B>Dependencies</B>
16968 * - device->spiSettings->chipSelectIndex
16969 *
16970 * \param device Pointer to the Mykonos device data structure containing settings
16971 * \param channelSel Enum selects the channel to reset
16972 *
16973 * \retval MYKONOS_ERR_RESET_TXLOL_INV_PARAM Selected channel is not valid
16974 * \retval MYKONOS_ERR_RESET_TXLOL_ARMERROR ARM error
16975 * \retval MYKONOS_ERR_OK Function completed successfully
16976 */
MYKONOS_resetExtTxLolChannel(mykonosDevice_t * device,mykonosTxChannels_t channelSel)16977 mykonosErr_t MYKONOS_resetExtTxLolChannel(mykonosDevice_t *device, mykonosTxChannels_t channelSel)
16978 {
16979 const uint8_t TXLOL_RESET_CHANNEL_ESTIMATE = 0x01;
16980 const uint32_t GETTXLOLSTATUS_TIMEOUT_MS = 1000;
16981
16982 mykonosErr_t retVal = MYKONOS_ERR_OK;
16983 uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_GS_TRACKCALS, TXLOL_RESET_CHANNEL_ESTIMATE, 0};
16984 uint8_t cmdStatusByte = 0;
16985 uint8_t armErrorFlag = 0;
16986
16987 #if (MYKONOS_VERBOSE == 1)
16988 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetExtTxLolChannel()\n");
16989 #endif
16990
16991 /* Check Channel */
16992 switch (channelSel)
16993 {
16994 case TX1:
16995 extData[2] = 0x01;
16996 break;
16997 case TX2:
16998 extData[2] = 0x02;
16999 break;
17000 case TX1_TX2:
17001 extData[2] = 0x03;
17002 break;
17003 default:
17004 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESET_TXLOL_INV_PARAM,
17005 getMykonosErrorMessage(MYKONOS_ERR_RESET_TXLOL_INV_PARAM));
17006 return MYKONOS_ERR_RESET_TXLOL_INV_PARAM;
17007 }
17008
17009 /* throw error if not in the right state */
17010 retVal = MYKONOS_checkArmState(device, (MYK_ARM_IDLE | MYK_ARM_RADIO_ON));
17011 if (retVal)
17012 {
17013 return retVal;
17014 }
17015
17016 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData));
17017 if (retVal)
17018 {
17019 return retVal;
17020 }
17021 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, GETTXLOLSTATUS_TIMEOUT_MS, &cmdStatusByte);
17022
17023 /* Error check WaitArmCmdStatus return */
17024 armErrorFlag = (cmdStatusByte >> 1);
17025 if (armErrorFlag > 0)
17026 {
17027 return MYKONOS_ERR_RESET_TXLOL_ARMERROR;
17028 }
17029
17030 return retVal;
17031 }
17032
17033 /**
17034 * \brief Configures the Radio power up/down control for Rx and Tx paths to be controlled by pins
17035 * (TX1/2_ENABLE, RX1/2_ENABLE, and GPIO pins) or an API function call.
17036 *
17037 * The BBP should not have to call this as it will automatically be setup at the end of the
17038 * MYKONOS_loadArmFromBinary() function call. If the BBP wishes to change the radio power up/down
17039 * control method this function can be called again to change the configuration while
17040 * the ARM is in the radioOff state.
17041 *
17042 * <B>Dependencies</B>
17043 * - device->spiSettings->chipSelectIndex
17044 * - device->auxIo->armGpio->useRx2EnablePin
17045 * - device->auxIo->armGpio->useTx2EnablePin
17046 * - device->auxIo->armGpio->txRxPinMode
17047 * - device->auxIo->armGpio->orxPinMode
17048 *
17049 * \param device is a pointer to the device settings structure
17050 *
17051 * \retval MYKONOS_ERR_OK Function completed successfully
17052 * \retval MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR ARM returned an error and did not accept the command.
17053 */
MYKONOS_setRadioControlPinMode(mykonosDevice_t * device)17054 mykonosErr_t MYKONOS_setRadioControlPinMode(mykonosDevice_t *device)
17055 {
17056 uint8_t extData[4] = {0x81, 0, 0, 4}; /*Object ID 0x81 (radio control structure), offset lsb, offset msb, length*/
17057 uint8_t armRadioControlStruct[4] = {0};
17058 uint32_t timeoutMs = 0;
17059 uint8_t cmdStatusByte = 0;
17060 mykonosErr_t retval = MYKONOS_ERR_OK;
17061
17062 #if MYKONOS_VERBOSE == 1
17063 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRadioControlPinMode()\n");
17064 #endif
17065
17066 /* write ARM radio control structure to enable pin mode/command mode */
17067 if (device->auxIo->armGpio->useRx2EnablePin > 0)
17068 {
17069 armRadioControlStruct[0] = 0x01;
17070 }
17071
17072 if (device->auxIo->armGpio->useTx2EnablePin > 0)
17073 {
17074 armRadioControlStruct[1] = 0x01;
17075 }
17076
17077 if (device->auxIo->armGpio->txRxPinMode > 0)
17078 {
17079 armRadioControlStruct[2] = 0x01;
17080 }
17081
17082 if (device->auxIo->armGpio->orxPinMode > 0)
17083 {
17084 armRadioControlStruct[3] = 0x01;
17085 }
17086
17087 retval = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armRadioControlStruct[0], sizeof(armRadioControlStruct));
17088 if (retval != MYKONOS_ERR_OK)
17089 {
17090 return retval;
17091 }
17092
17093 retval = MYKONOS_sendArmCommand(device, MYKONOS_ARM_WRITECFG_OPCODE, &extData[0], sizeof(extData));
17094 if (retval != MYKONOS_ERR_OK)
17095 {
17096 return retval;
17097 }
17098
17099 timeoutMs = 1000;
17100 retval = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_WRITECFG_OPCODE, timeoutMs, &cmdStatusByte);
17101 if (retval != MYKONOS_ERR_OK)
17102 {
17103 return retval;
17104 }
17105
17106 if (cmdStatusByte > 0)
17107 {
17108 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR,
17109 getMykonosErrorMessage(MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR));
17110 return MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR;
17111 }
17112
17113 return MYKONOS_ERR_OK;
17114 }
17115
17116 /**
17117 * \brief Sets the measure count which is the number of samples taken before DC offset correction is applied for the given Rf channel.
17118 * This value cannot be changed after ARM initialization.
17119 * channel can be one of the following ( ::mykonosDcOffsetChannels_t ).
17120 *
17121 * Channel | Channel description
17122 * ------------------------|--------------------------------
17123 * MYK_DC_OFFSET_RX_CHN | Selects Rx channel
17124 * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel
17125 * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel
17126 *
17127 * The total duration 'tCount' is calculated as,
17128 * [tCount = (measureCount * 1024) / IQ data rate of the channel].
17129 * There is a minimum limit for the value of measureCount, the value passed should satisfy the condition 'tCount > 800us'.
17130 *
17131 * <B>Dependencies</B>
17132 * - device->spiSettings->chipSelectIndex
17133 *
17134 * \param device Pointer to the Mykonos device data structure containing settings
17135 * \param channel receive channel to be selected.
17136 * \param measureCount value to be configured for the selected channel which is the number of samples taken before DC offset correction is applied.
17137 *
17138 * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels.
17139 * \retval MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT measurement count value passed is invalid
17140 * \retval MYKONOS_ERR_OK Function completed successfully
17141 * \retval MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT The measureCount value passed is less than the minimum limit allowed.
17142 */
MYKONOS_setRfDcOffsetCnt(mykonosDevice_t * device,mykonosDcOffsetChannels_t channel,uint16_t measureCount)17143 mykonosErr_t MYKONOS_setRfDcOffsetCnt(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint16_t measureCount)
17144 {
17145 mykonosErr_t retVal = MYKONOS_ERR_OK;
17146 uint16_t REG_ADDRESS_H = 0; /* Address for Higher byte */
17147 uint16_t REG_ADDRESS_L = 0; /* Address for Lower byte */
17148 uint16_t MEASURE_CNT_RANGE = 0xFFFF; /* Mask for measure count range checking */
17149
17150 const uint8_t MEASURE_CNT_H = (measureCount & 0xFF00) >> 8; /* Higher byte of the measure count */
17151 const uint8_t MEASURE_CNT_L = measureCount & 0x00FF; /* Lower byte of the measure count */
17152
17153 /* Calculation of Total Duration [ tCount = (measureCount * 0x400) / IQ data rate cycles ] */
17154 const uint8_t FACTOR = 10;
17155 uint32_t tCount = (measureCount << FACTOR); /* precalculations for Total duration in us */
17156 uint32_t IQ_RATE = 0;
17157
17158 #if (MYKONOS_VERBOSE == 1)
17159 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRfDcOffsetCnt()\n");
17160 #endif
17161
17162 /* check for channel and update the appropriate register address */
17163 switch (channel)
17164 {
17165 case MYK_DC_OFFSET_RX_CHN:
17166 REG_ADDRESS_H = MYKONOS_ADDR_RFDC_MEASURE_COUNT_2;
17167 REG_ADDRESS_L = MYKONOS_ADDR_RFDC_MEASURE_COUNT_1;
17168 IQ_RATE = device->rx->rxProfile->iqRate_kHz / 1000; /* IQ Rate to calculate total duration */
17169 break;
17170 case MYK_DC_OFFSET_ORX_CHN:
17171 REG_ADDRESS_H = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_2;
17172 REG_ADDRESS_L = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_1;
17173 IQ_RATE = device->obsRx->orxProfile->iqRate_kHz / 1000; /* IQ Rate to calculate total duration */
17174 break;
17175 case MYK_DC_OFFSET_SNF_CHN:
17176 REG_ADDRESS_H = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_2;
17177 REG_ADDRESS_L = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_1;
17178 /* measureCount for Sniffer should be 10 bit */
17179 MEASURE_CNT_RANGE= 0x03FF;
17180 IQ_RATE = device->obsRx->snifferProfile->iqRate_kHz / 1000; /* IQ Rate to calculate total duration */
17181 break;
17182
17183 default:
17184 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN,
17185 getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN));
17186 return MYKONOS_ERR_DC_OFFSET_INV_CHAN;
17187 }
17188
17189 tCount = (tCount / IQ_RATE); /* Calculating total duration in us */
17190 if (tCount < 800)
17191 {
17192 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT,
17193 getMykonosErrorMessage(MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT));
17194 return MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT ;
17195 }
17196
17197 if ((measureCount < 0x11) || (measureCount & ~MEASURE_CNT_RANGE))
17198 {
17199 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT,
17200 getMykonosErrorMessage(MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT));
17201 return MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT ;
17202 }
17203
17204 CMB_SPIWriteField(device->spiSettings, REG_ADDRESS_H, MEASURE_CNT_H, ((MEASURE_CNT_RANGE >>8) & 0xFF),0);
17205 CMB_SPIWriteByte(device->spiSettings, REG_ADDRESS_L, MEASURE_CNT_L);
17206
17207 return retVal;
17208 }
17209
17210 /**
17211 * \brief retrieves the measure count which is the number of samples taken before DC offset correction is applied for the given Rf channel.
17212 * channel can be one of the following ( ::mykonosDcOffsetChannels_t ).
17213 *
17214 * Channel | Channel description
17215 * ------------------------|--------------------------------
17216 * MYK_DC_OFFSET_RX_CHN | Selects Rx channel
17217 * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel
17218 * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel
17219 *
17220 * <B>Dependencies</B>
17221 * - device->spiSettings->chipSelectIndex
17222 *
17223 * \param device Pointer to the Mykonos device data structure containing settings
17224 * \param channel receive channel to be selected.
17225 * \param measureCount pointer to the variable to store the read value.
17226 *
17227 * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels.
17228 * \retval MYKONOS_ERR_SET_RF_DC_OFFSET_NULL_MEASURECNT passed pointer of measureCount is NULL
17229 * \retval MYKONOS_ERR_OK Function completed successfully
17230 */
MYKONOS_getRfDcOffsetCnt(mykonosDevice_t * device,mykonosDcOffsetChannels_t channel,uint16_t * measureCount)17231 mykonosErr_t MYKONOS_getRfDcOffsetCnt(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint16_t *measureCount)
17232 {
17233 mykonosErr_t retVal = MYKONOS_ERR_OK;
17234 uint16_t REG_ADDRESS_H = 0; /* Address for Higher byte */
17235 uint16_t REG_ADDRESS_L = 0; /* Address for Lower byte */
17236 uint16_t MEASURE_CNT_RANGE = 0xFFFF; /* Mask for measure count range checking */
17237 uint16_t mCount = 0; /* Temporary variable to store readback from register. */
17238 uint8_t readbackData = 0;
17239
17240 #if (MYKONOS_VERBOSE == 1)
17241 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRfDcOffsetCnt()\n");
17242 #endif
17243
17244 switch (channel)
17245 {
17246 case MYK_DC_OFFSET_RX_CHN:
17247 REG_ADDRESS_H = MYKONOS_ADDR_RFDC_MEASURE_COUNT_2;
17248 REG_ADDRESS_L = MYKONOS_ADDR_RFDC_MEASURE_COUNT_1;
17249 break;
17250 case MYK_DC_OFFSET_ORX_CHN:
17251 REG_ADDRESS_H = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_2;
17252 REG_ADDRESS_L = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_1;
17253 break;
17254 case MYK_DC_OFFSET_SNF_CHN:
17255 REG_ADDRESS_H = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_2;
17256 REG_ADDRESS_L = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_1;
17257 /* measureCount for Sniffer should be 10 bit */
17258 MEASURE_CNT_RANGE= 0x03FF;
17259 break;
17260
17261 default:
17262 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN,
17263 getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN));
17264 return MYKONOS_ERR_DC_OFFSET_INV_CHAN;
17265 }
17266
17267 if (measureCount == NULL)
17268 {
17269 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT,
17270 getMykonosErrorMessage(MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT));
17271 return MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT;
17272 }
17273
17274 /* Store Higher byte of measureCount */
17275 CMB_SPIReadField(device->spiSettings, REG_ADDRESS_H, &readbackData, ((MEASURE_CNT_RANGE >>8) & 0xFF),0);
17276 mCount = readbackData;
17277 mCount = mCount << 8;
17278
17279 /* Store Lower byte of measureCount */
17280 readbackData = 0;
17281 CMB_SPIReadByte(device->spiSettings, REG_ADDRESS_L, &readbackData);
17282 mCount = mCount | readbackData;
17283
17284 *measureCount = mCount;
17285
17286 return retVal;
17287 }
17288
17289 /**
17290 * \brief Sets M-Shift value which is the Corner frequency of Rx notch filter for the given channel.
17291 * channel can be one of the following ( ::mykonosDcOffsetChannels_t ).
17292 *
17293 * Channel | Channel description
17294 * ------------------------|--------------------------------
17295 * MYK_DC_OFFSET_RX_CHN | Selects Rx channel
17296 * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel
17297 * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel
17298 *
17299 * <B>Dependencies</B>
17300 * - device->spiSettings->chipSelectIndex
17301 *
17302 * \param device Pointer to the Mykonos device data structure containing settings
17303 * \param channel receive channel to be selected.
17304 * \param mShift value to be configured for the given channel
17305 *
17306 * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels.
17307 * \retval MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT mShift value passed is invalid.
17308 * \retval MYKONOS_ERR_OK Function completed successfully
17309 */
MYKONOS_setDigDcOffsetMShift(mykonosDevice_t * device,mykonosDcOffsetChannels_t channel,uint8_t mShift)17310 mykonosErr_t MYKONOS_setDigDcOffsetMShift(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint8_t mShift)
17311 {
17312 mykonosErr_t retVal = MYKONOS_ERR_OK;
17313 uint16_t REG_ADDRESS = 0;
17314
17315 const uint8_t MSHIFT_MIN_RANGE= 0x08;
17316 const uint8_t MSHIFT_MAX_RANGE= 0x14;
17317
17318 #if (MYKONOS_VERBOSE == 1)
17319 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDigDcOffsetMShift()\n");
17320 #endif
17321
17322 if ((mShift < MSHIFT_MIN_RANGE) || (mShift > MSHIFT_MAX_RANGE))
17323 {
17324 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT,
17325 getMykonosErrorMessage(MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT));
17326 return MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT;
17327 }
17328
17329 /* check channel and set the address */
17330 switch (channel)
17331 {
17332 case MYK_DC_OFFSET_RX_CHN:
17333 REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SHIFT;
17334 break;
17335 case MYK_DC_OFFSET_ORX_CHN:
17336 REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CH3_DPD_M_SHIFT;
17337 break;
17338 case MYK_DC_OFFSET_SNF_CHN:
17339 REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SNF;
17340 break;
17341
17342 default:
17343 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN,
17344 getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN));
17345 return MYKONOS_ERR_DC_OFFSET_INV_CHAN;
17346 }
17347
17348 CMB_SPIWriteField(device->spiSettings, REG_ADDRESS, mShift, 0x1F, 0);
17349
17350 return retVal;
17351 }
17352
17353 /**
17354 * \brief retrieves the M-Shift value which is the Corner frequency of Rx notch filter for the given channel.
17355 * channel can be one of the following ( ::mykonosDcOffsetChannels_t ).
17356 *
17357 * Channel | Channel description
17358 * ------------------------|--------------------------------
17359 * MYK_DC_OFFSET_RX_CHN | Selects Rx channel
17360 * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel
17361 * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel
17362 *
17363 * <B>Dependencies</B>
17364 * - device->spiSettings->chipSelectIndex
17365 *
17366 * \param device Pointer to the Mykonos device data structure containing settings
17367 * \param channel receive channel to be selected.
17368 * \param mShift Pointer to the variable to store mshift value of the given channel
17369 *
17370 * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels.
17371 * \retval MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT mShift pointer is NULL
17372 * \retval MYKONOS_ERR_OK Function completed successfully
17373 */
MYKONOS_getDigDcOffsetMShift(mykonosDevice_t * device,mykonosDcOffsetChannels_t channel,uint8_t * mShift)17374 mykonosErr_t MYKONOS_getDigDcOffsetMShift(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint8_t *mShift)
17375 {
17376 mykonosErr_t retVal = MYKONOS_ERR_OK;
17377 uint16_t REG_ADDRESS = 0x0;
17378 uint8_t readbackData = 0x0;
17379
17380 #if (MYKONOS_VERBOSE == 1)
17381 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDigDcOffsetMShift()\n");
17382 #endif
17383
17384 if (mShift == NULL)
17385 {
17386 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT,
17387 getMykonosErrorMessage(MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT));
17388 return MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT;
17389 }
17390
17391 /* check for the channel and set the address */
17392 switch (channel)
17393 {
17394 case MYK_DC_OFFSET_RX_CHN:
17395 REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SHIFT;
17396 break;
17397 case MYK_DC_OFFSET_ORX_CHN:
17398 REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CH3_DPD_M_SHIFT;
17399 break;
17400 case MYK_DC_OFFSET_SNF_CHN:
17401 REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SNF;
17402 break;
17403
17404 default:
17405 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN,
17406 getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN));
17407 return MYKONOS_ERR_DC_OFFSET_INV_CHAN;
17408 }
17409
17410 CMB_SPIReadField(device->spiSettings, REG_ADDRESS, &readbackData, 0x1F,0);
17411
17412 *mShift = readbackData;
17413
17414 return retVal;
17415 }
17416
17417 /**
17418 * \brief Sets the RF PLL loop filter bandwith.
17419 *
17420 * \pre Command should be called in Radio Off state. ARM must be initialized.
17421 *
17422 * \post Loop filter should lock successfully
17423 *
17424 * <B>Dependencies</B>
17425 * - device->spiSettings->chipSelectIndex
17426 * - device->spiSettings
17427 *
17428 * \param device is structure pointer to the MYKONOS data structure containing settings
17429 * \param pllName Name of the PLL to configure.RX_PLL and TX_PLL can be configured.SNIFFER_PLL can not be configured.
17430 * \param loopBandwidth_kHz Desired RF pll bandwith to be set. The valid values range of loopBandwidth_kHz for Rx and Tx is 50 to 750.For SRX valid values lies from 500 to 750.
17431 * \param stability PLL Loop stability to be set.The valid values range of stability is from 3 to 15.
17432 *
17433 * \return MYKONOS_ERR_OK Function completed successfully
17434 * \return MYKONOS_ERR_SETRFPLL_LF_ARMERROR ARM Command to set RF PLL loop filter bandwidth failed
17435 * \return MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH Invalid Tx/Rx value bandwith
17436 * \return MYKONOS_ERR_SETRFPLL_LF_PLLNAME Invalid pllName requested
17437 * \return MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY Invalid stability range, valid range is 3-15
17438 */
MYKONOS_setRfPllLoopFilter(mykonosDevice_t * device,mykonosRfPllName_t pllName,uint16_t loopBandwidth_kHz,uint8_t stability)17439 mykonosErr_t MYKONOS_setRfPllLoopFilter(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint16_t loopBandwidth_kHz, uint8_t stability)
17440 {
17441 const uint8_t SETCMD_OPCODE = 0x0A;
17442 const uint8_t SET_PLL_BANDWIDTH = 0x6D;
17443 const uint16_t LOOP_BW_HIGH = 750;
17444
17445 uint16_t LOOP_BW_LOW = 50;
17446 uint8_t extData[4] = {0};
17447 uint8_t cmdStatusByte = 0;
17448 mykonosErr_t retVal = MYKONOS_ERR_OK;
17449 mykonosErr_t errLoopBw = MYKONOS_ERR_OK;
17450 uint32_t timeoutMs = 1000;
17451
17452 #if (MYKONOS_VERBOSE == 1)
17453 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRfPllLoopFilter()\n");
17454 #endif
17455
17456 switch (pllName)
17457 {
17458 case RX_PLL:
17459 extData[1] = 0x00;
17460 LOOP_BW_LOW = 50;
17461 errLoopBw = MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH;
17462 break;
17463 case TX_PLL:
17464 extData[1] = 0x10;
17465 LOOP_BW_LOW = 50;
17466 errLoopBw = MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH;
17467 break;
17468 case SNIFFER_PLL:
17469 #if 0 /* Set for Sniffer PLL loop bandwidth is not supported */
17470 extData[1] = 0x20;
17471 LOOP_BW_LOW = 500;
17472 errLoopBw = MYKONOS_ERR_SETRFPLL_LF_INV_SNF_LOOPBANDWIDTH;
17473 break;
17474 #endif
17475 default:
17476 {
17477 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_LF_PLLNAME,
17478 getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_LF_PLLNAME));
17479 return MYKONOS_ERR_SETRFPLL_LF_PLLNAME;
17480 }
17481 }
17482
17483 /* Range check for loopBandwidth - Should be between 50kHz and 750kHz for TX/RX and between 500kHz and 750 for SRX*/
17484 if ((loopBandwidth_kHz< LOOP_BW_LOW) || (loopBandwidth_kHz >LOOP_BW_HIGH))
17485 {
17486 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, errLoopBw,
17487 getMykonosErrorMessage(errLoopBw));
17488 return errLoopBw;
17489 }
17490
17491 /* Range check for stability - Should be between 3 and 15 */
17492 if ((stability < 3) || (stability > 15))
17493 {
17494 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY,
17495 getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY));
17496 return MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY;
17497 }
17498
17499 /* Generate payload for SET command */
17500 extData[0] = SET_PLL_BANDWIDTH;
17501 /*left shift and truncate left side*/
17502 extData[1] |= stability;
17503 extData[2] = (uint8_t)(loopBandwidth_kHz & 0xFF); //full first byte
17504 extData[3] = (uint8_t)(loopBandwidth_kHz >> 8); //two extra bits
17505
17506 /* executing the SET command */
17507 retVal = MYKONOS_sendArmCommand(device, SETCMD_OPCODE, &extData[0], sizeof(extData));
17508 if (retVal != MYKONOS_ERR_OK)
17509 {
17510 return retVal;
17511 }
17512
17513 /* waiting for command to complete */
17514 retVal = MYKONOS_waitArmCmdStatus(device, SETCMD_OPCODE, timeoutMs, &cmdStatusByte);
17515
17516 /* performing command status check */
17517 if (retVal != MYKONOS_ERR_OK)
17518 {
17519 if (cmdStatusByte > 0)
17520 {
17521 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_LF_ARMERROR,
17522 getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_LF_ARMERROR));
17523 return MYKONOS_ERR_SETRFPLL_LF_ARMERROR;
17524 }
17525
17526 return retVal;
17527 }
17528
17529 return retVal;
17530 }
17531
17532 /**
17533 * \brief Gets the RF PLL loop filter bandwidth and stability.
17534 *
17535 * This function is used to get the RF PLL loop bandwidth. It can get the RX PLL, TX PLL
17536 * Sniffer PLL.
17537 *
17538 * \pre Command can be called in Radio Off state or On state. ARM must be initialized.
17539 *
17540 * <B>Dependencies</B>
17541 * - device->spiSettings->chipSelectIndex
17542 * - device->spiSettings
17543 * - device->clocks->deviceClock_kHz
17544 *
17545 * \param device is structure pointer to the MYKONOS data structure containing settings
17546 * \param pllName Name of the PLL for which to read the frequency
17547 * \param loopBandwidth_kHz RF PLL loop bandwidth for the PLL specified
17548 * \param stability RF PLL loop stability
17549 *
17550 * \retval MYKONOS_ERR_OK Function completed successfully
17551 * \retval MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME Invalid PLL name, can not get PLL frequency. Use PLL name ENUM.
17552 * \retval MYKONOS_ERR_GETRFPLL_LF_ARMERROR ARM Command to get RF PLL frequency failed
17553 * \retval MYKONOS_ERR_GETRFPLL_LF_NULLPARAM input parameter is NULL
17554 */
MYKONOS_getRfPllLoopFilter(mykonosDevice_t * device,mykonosRfPllName_t pllName,uint16_t * loopBandwidth_kHz,uint8_t * stability)17555 mykonosErr_t MYKONOS_getRfPllLoopFilter(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint16_t *loopBandwidth_kHz, uint8_t *stability)
17556 {
17557 const uint8_t GET_PLL_BANDWIDTH = 0x6D;
17558
17559 mykonosErr_t retVal = MYKONOS_ERR_OK;
17560 uint8_t armData[8] = {0, 0, 0, 0, 0, 0, 0, 0};
17561 uint8_t extData[2] = {GET_PLL_BANDWIDTH, 0};
17562 uint32_t timeoutMs = 0;
17563 uint8_t cmdStatusByte = 0;
17564
17565 #if (MYKONOS_VERBOSE == 1)
17566 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRfPllLoopFilter()\n");
17567 #endif
17568
17569 /* Check for NULL */
17570 if ((loopBandwidth_kHz == NULL)|| (stability == NULL))
17571 {
17572 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_LF_NULLPARAM,
17573 getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_LF_NULLPARAM));
17574 return MYKONOS_ERR_GETRFPLL_LF_NULLPARAM;
17575 }
17576
17577 switch(pllName)
17578 {
17579 case RX_PLL: extData[1] = 0x00; break;
17580 case TX_PLL: extData[1] = 0x10; break;
17581 case SNIFFER_PLL: extData[1] = 0x20; break;
17582 default:
17583 {
17584 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME,
17585 getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME));
17586 return MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME;
17587 }
17588 }
17589 /* executing the GET command */
17590 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
17591 if (retVal != MYKONOS_ERR_OK)
17592 {
17593 return retVal;
17594 }
17595
17596 timeoutMs = 1000;
17597
17598 /* waiting for command to complete */
17599 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
17600
17601 /* performing command status check */
17602 if (retVal != MYKONOS_ERR_OK)
17603 {
17604 if (cmdStatusByte > 0)
17605 {
17606 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_LF_ARMERROR,
17607 getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_LF_ARMERROR));
17608 return MYKONOS_ERR_GETRFPLL_LF_ARMERROR;
17609 }
17610
17611 return retVal;
17612 }
17613
17614 /* Read from ARM memory */
17615 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 8, 1);
17616 if (retVal != MYKONOS_ERR_OK)
17617 {
17618 return retVal;
17619 }
17620
17621 /* Assign to variables */
17622 *stability = armData[3];
17623 *loopBandwidth_kHz = (((uint16_t)armData[1]) << 8) | ((uint16_t)armData[0]);
17624
17625 return MYKONOS_ERR_OK;
17626 }
17627
17628 /**
17629 * \brief Enable/ Disable Digital DC Offset channels using the channel mask.
17630 * The mask can be a combination of the following channel values ( ::mykonosRxDcOffsettEn_t ).
17631 *
17632 * Channel | Value | Channel description
17633 * -------------------------|---------|--------------------------
17634 * MYK_DC_OFFSET_ALL_OFF | 0x00 | Disable all the channels
17635 * MYK_DC_OFFSET_RX1 | 0x01 | Enables Rx1
17636 * MYK_DC_OFFSET_RX2 | 0x02 | Enables Rx1
17637 * MYK_DC_OFFSET_SNF | 0x04 | Enables Sniffer
17638 * MYK_DC_OFFSET_ORX | 0x08 | Enables ORx
17639 * MYK_DC_OFFSET_AVAILABLE | 0x0F | Enables all the channels
17640 *
17641 * <B>Dependencies</B>
17642 * - device->spiSettings->chipSelectIndex
17643 *
17644 * \param device Pointer to the Mykonos device data structure containing settings
17645 * \param enableMask with bits of channels to be enabled.
17646 *
17647 * \retval MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK enable mask passed to the function is invalid, refer mykonosRxDcOffsettEn_t enum.
17648 * \retval MYKONOS_ERR_OK Function completed successfully
17649 */
MYKONOS_setDigDcOffsetEn(mykonosDevice_t * device,uint8_t enableMask)17650 mykonosErr_t MYKONOS_setDigDcOffsetEn(mykonosDevice_t *device, uint8_t enableMask)
17651 {
17652 mykonosErr_t retVal = MYKONOS_ERR_OK;
17653 uint16_t REG_ADDRESS = 0x00;
17654 uint8_t dataToWrite = 0x00;
17655
17656
17657 #if (MYKONOS_VERBOSE == 1)
17658 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDigDcOffsetEn()\n");
17659 #endif
17660
17661 if (enableMask & ~((uint8_t)MYK_DC_OFFSET_AVAILABLE))
17662 {
17663 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK,
17664 getMykonosErrorMessage(MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK));
17665 return MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK;
17666 }
17667
17668 REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CONFIG; /* Address for Rx Digital tracking Enable bits register */
17669 if (enableMask & ((uint8_t)MYK_DC_OFFSET_RX1 | (uint8_t)MYK_DC_OFFSET_RX2)) /* Enable / Disable Rx1 and/or Rx2 */
17670 {
17671 dataToWrite |= ((enableMask & ((uint8_t)MYK_DC_OFFSET_RX1 |(uint8_t) MYK_DC_OFFSET_RX2)) << 1 );
17672 }
17673 CMB_SPIWriteField(device->spiSettings, REG_ADDRESS, dataToWrite, 0x06,0); /* Write RX enable bits to the register */
17674
17675 dataToWrite = 0x0; /* Reset dataToWrite */
17676 REG_ADDRESS = MYKONOS_DIGITAL_DC_OFFSET_CH3_TRACKING; /* Address for ORx and Sniffer Digital trackingEnable bits register */
17677 if (enableMask & ((uint8_t)MYK_DC_OFFSET_SNF | (uint8_t)MYK_DC_OFFSET_ORX)) /* Check for channel ORx and/or Sniffer */
17678 {
17679 dataToWrite |= ((enableMask & ((uint8_t)MYK_DC_OFFSET_SNF | (uint8_t)MYK_DC_OFFSET_ORX))>>2);
17680 }
17681 CMB_SPIWriteField(device->spiSettings, REG_ADDRESS, dataToWrite, 0x03,0); /* Write Loopback, ORx and Sniffer enable bits to the register */
17682
17683 return retVal;
17684 }
17685
17686 /**
17687 * \brief reads Enable/ Disable channels Digital DC Offset and returns a mask of it.
17688 * The mask returned will be a combination of the following channel values ( ::mykonosRxDcOffsettEn_t ).
17689 *
17690 * Channel | Value | Channel description
17691 * -------------------------|---------|--------------------------
17692 * MYK_DC_OFFSET_ALL_OFF | 0x00 | All channels are disabled
17693 * MYK_DC_OFFSET_RX1 | 0x01 | Rx1 is enabled
17694 * MYK_DC_OFFSET_RX2 | 0x02 | Rx2 is enabled
17695 * MYK_DC_OFFSET_SNF | 0x04 | Sniffer is enabled
17696 * MYK_DC_OFFSET_ORX | 0x08 | ORx is enabled
17697 * MYK_DC_OFFSET_AVAILABLE | 0x0F | All channels are enabled
17698 *
17699 * <B>Dependencies</B>
17700 * - device->spiSettings->chipSelectIndex
17701 *
17702 * \param device Pointer to the Mykonos device data structure containing settings
17703 * \param enableMask pointer to the variable to store Enable mask of channels
17704 *
17705 * \retval MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK enableMask is NULL
17706 * \retval MYKONOS_ERR_OK Function completed successfully
17707 */
MYKONOS_getDigDcOffsetEn(mykonosDevice_t * device,uint8_t * enableMask)17708 mykonosErr_t MYKONOS_getDigDcOffsetEn(mykonosDevice_t *device,uint8_t *enableMask)
17709 {
17710 mykonosErr_t retVal = MYKONOS_ERR_OK;
17711 uint16_t REG_ADDRESS = 0;
17712 uint8_t readbackData = 0;
17713 uint8_t enableMaskData = 0;
17714
17715 #if (MYKONOS_VERBOSE == 1)
17716 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDigDcOffsetEn()\n");
17717 #endif
17718
17719 if (enableMask == NULL)
17720 {
17721 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK,
17722 getMykonosErrorMessage(MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK));
17723 return MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK;
17724 }
17725
17726 REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CONFIG; /* register address of Rx1 and Rx2 enable bits*/
17727 CMB_SPIReadField(device->spiSettings, REG_ADDRESS, &readbackData, 0x06,0);
17728 enableMaskData |= (readbackData>>1); /* adjust bits to match channel :refer enum mykonosRfDcOffsettEn_t. */
17729
17730 readbackData = 0x00;
17731 REG_ADDRESS = MYKONOS_DIGITAL_DC_OFFSET_CH3_TRACKING; /* register address of Orx and sniffer enable bits*/
17732 CMB_SPIReadField(device->spiSettings, REG_ADDRESS, &readbackData, 0x03,0);
17733 enableMaskData |= (uint8_t)(readbackData<<2); /* adjust bits to match channel :refer enum mykonosRfDcOffsettEn_t. */
17734
17735 *enableMask = enableMaskData;
17736
17737 return retVal;
17738 }
17739
17740 /**
17741 * \brief This function will configure the path delay settings for all the features:
17742 * DPD, VSWR and CLGC.
17743 *
17744 * A DPD device is required.
17745 *
17746 * <B>Dependencies</B>
17747 * - device->spiSettings->chipSelectIndex
17748 * - device->profilesValid
17749 *
17750 * \param device Pointer to the Mykonos device data structure containing settings
17751 * \param pathDelay pointer to structure of type ::mykonosPathdelay_t to be programmed
17752 *
17753 * \retval MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM pathDelay is null
17754 * \retval MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE path delay valid range is from 0 to 4095 at 1/16 sample resolution of ORx sample rate
17755 * \retval MYKONOS_ERR_OK Function completed successfully
17756 */
MYKONOS_setPathDelay(mykonosDevice_t * device,mykonosPathdelay_t * pathDelay)17757 mykonosErr_t MYKONOS_setPathDelay(mykonosDevice_t *device, mykonosPathdelay_t *pathDelay)
17758 {
17759 mykonosErr_t retVal = MYKONOS_ERR_OK;
17760 uint8_t armFieldValue[16] = {0};
17761 uint8_t extData[3] = {(uint8_t)MYKONOS_ARM_OBJECTID_TRACKING_CAL_CONTROL, (uint8_t)SET_PATH_DELAY, 0};
17762 uint8_t writeSize = 0;
17763 uint8_t fifoDel[4] = {0};
17764 uint8_t interpIndex[4] = {0};
17765 uint32_t *delPointer = &pathDelay->forwardPathDelayCh1;
17766 uint8_t i = 0;
17767
17768 const uint32_t RANGE_PATH_DELAY = 4095;
17769 const uint8_t PATH_DELAY_SIZE = 4;
17770
17771 #if (MYKONOS_VERBOSE == 1)
17772 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setPathDelay()\n");
17773 #endif
17774
17775 if (pathDelay == NULL)
17776 {
17777 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM,
17778 getMykonosErrorMessage(MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM));
17779 return MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM;
17780 }
17781
17782 /* Loop to set the ARM memory data */
17783 for (i = 0; i < PATH_DELAY_SIZE ; i++)
17784 {
17785 /* Verify all the data in the structure is in range */
17786 if (*delPointer > RANGE_PATH_DELAY)
17787 {
17788 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE,
17789 getMykonosErrorMessage(MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE));
17790 return MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE;
17791 }
17792
17793 fifoDel[i] = (uint8_t)(*delPointer >> 4);
17794 interpIndex[i] = (uint8_t)(*delPointer - (fifoDel[i] * 16));
17795
17796 delPointer++;
17797 }
17798
17799 if ((device->tx->vswrConfig == NULL) || ((pathDelay->reversePathDelayCh1 == 0) && (pathDelay->reversePathDelayCh2 == 0)))
17800 {
17801 armFieldValue[0] = interpIndex[0];
17802 armFieldValue[1] = 0;
17803 armFieldValue[2] = fifoDel[0];
17804 armFieldValue[3] = 0;
17805 armFieldValue[4] = interpIndex[2];
17806 armFieldValue[5] = 0;
17807 armFieldValue[6] = fifoDel[2];
17808 armFieldValue[7] = 0;
17809 extData[2] = 0;
17810 writeSize = 8;
17811 }
17812 else
17813 {
17814 armFieldValue[0] = interpIndex[0];
17815 armFieldValue[1] = 0;
17816 armFieldValue[2] = fifoDel[0];
17817 armFieldValue[3] = 0;
17818 armFieldValue[4] = interpIndex[2];
17819 armFieldValue[5] = 0;
17820 armFieldValue[6] = fifoDel[2];
17821 armFieldValue[7] = 0;
17822 armFieldValue[8] = interpIndex[1];
17823 armFieldValue[9] = 0;
17824 armFieldValue[10] = fifoDel[1];
17825 armFieldValue[11] = 0;
17826 armFieldValue[12] = interpIndex[3];
17827 armFieldValue[13] = 0;
17828 armFieldValue[14] = fifoDel[3];
17829 armFieldValue[15] = 0;
17830 extData[2] = 1;
17831 writeSize = 16;
17832 }
17833
17834 retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armFieldValue[0], writeSize);
17835 if (retVal != MYKONOS_ERR_OK)
17836 {
17837 return retVal;
17838 }
17839
17840 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData));
17841
17842 return retVal;
17843 }
17844
17845 /**
17846 * \brief This function will read the current path delay settings for the selected calibration.
17847 *
17848 * A DPD-enabled transceiver is required
17849 *
17850 * <B>Dependencies</B>
17851 * - device->spiSettings->chipSelectIndex
17852 * - device->profilesValid
17853 *
17854 * \param device Pointer to the Mykonos device data structure containing settings
17855 * \param select path delay status selection from ::mykonosPathDelaySel_t
17856 * \param pathDelay pointer to structure of type ::mykonosPathdelay_t to store the read back path delay
17857 *
17858 * \retval MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM pathDelay is null
17859 * \retval MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION invalid selection for getting the path delay, valid selections are given by mykonosPathDelaySel_t
17860 * \retval MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG Arm error while reading path delay for the selected calibration status
17861 * \retval MYKONOS_ERR_OK Function completed successfully
17862 */
MYKONOS_getPathDelay(mykonosDevice_t * device,mykonosPathDelaySel_t select,mykonosPathdelay_t * pathDelay)17863 mykonosErr_t MYKONOS_getPathDelay(mykonosDevice_t *device, mykonosPathDelaySel_t select, mykonosPathdelay_t *pathDelay)
17864 {
17865 uint8_t extData[3] = {(uint8_t)MYKONOS_ARM_OBJECTID_CAL_STATUS, (uint8_t)MYKONOS_ARM_OBJECTID_VSWRCONFIG, 0};
17866 uint8_t armData[80] = {0};
17867 uint32_t timeoutMs = 0;
17868 uint8_t cmdStatusByte = 0;
17869 uint32_t *delPointer = &pathDelay->forwardPathDelayCh1;
17870 uint8_t channel = 0;
17871 uint8_t addr[4] = {0};
17872 mykonosErr_t retVal = MYKONOS_ERR_OK;
17873
17874 #if (MYKONOS_VERBOSE == 1)
17875 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getPathDelay()\n");
17876 #endif
17877
17878 if (pathDelay == NULL)
17879 {
17880 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM,
17881 getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM));
17882 return MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM;
17883 }
17884
17885 switch (select)
17886 {
17887 case MYK_DPD_PATH_DELAY:
17888 extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG;
17889 addr[0] = 24;
17890 addr[1] = 26;
17891 addr[2] = 0;
17892 addr[3] = 0;
17893 break;
17894 case MYK_CLGC_PATH_DELAY:
17895 extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG;
17896 addr[0] = 60;
17897 addr[1] = 62;
17898 addr[2] = 0;
17899 addr[3] = 0;
17900 break;
17901 case MYK_VSWR_PATH_DELAY:
17902 extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG;
17903 addr[0] = 72;
17904 addr[1] = 74;
17905 addr[2] = 76;
17906 addr[3] = 78;
17907 break;
17908 default:
17909 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION,
17910 getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION));
17911 return MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION;
17912 }
17913
17914 /* reading 2 channels, channel being the channel selector */
17915 for (channel = 0; channel < 2; channel++)
17916 {
17917 if (channel)
17918 {
17919 delPointer++;
17920 }
17921
17922 extData[2] = channel;
17923
17924 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
17925 if (retVal != MYKONOS_ERR_OK)
17926 {
17927 return retVal;
17928 }
17929
17930 timeoutMs = 1000;
17931 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
17932 if (retVal != MYKONOS_ERR_OK)
17933 {
17934 /* throw more specific error message instead of returning error code from waitArmCmdStatus */
17935 if (cmdStatusByte > 0)
17936 {
17937 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG,
17938 getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG));
17939 return MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG;
17940 }
17941
17942 return retVal;
17943 }
17944
17945 if (cmdStatusByte > 0)
17946 {
17947 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG,
17948 getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG));
17949 return MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG;
17950 }
17951
17952 /* read status from ARM memory */
17953 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1);
17954 if (retVal != MYKONOS_ERR_OK)
17955 {
17956 return retVal;
17957 }
17958
17959 *delPointer = ((uint32_t)(armData[addr[1]]) * 16) + (uint32_t)(armData[addr[0]]);
17960 delPointer++;
17961 if ((addr[2] != 0) && (addr[3] != 0))
17962 {
17963 /* reverse path delay only applies to VSWR */
17964 *delPointer = ((uint32_t)(armData[addr[3]]) * 16) + (uint32_t)(armData[addr[2]]);
17965 }
17966 else
17967 {
17968 /* the rest of path delays will not have a reverse delay value */
17969 *delPointer = 0;
17970 }
17971 }
17972
17973 return retVal;
17974 }
17975
17976 /**
17977 * \brief This function reads the current error counters for all the DPD error codes from ::mykonosDpdErrors_t.
17978 *
17979 * A DPD-enabled transceiver is required
17980 *
17981 * <B>Dependencies</B>
17982 * - device->spiSettings->chipSelectIndex
17983 * - device->profilesValid
17984 *
17985 * \param device Pointer to the Mykonos device data structure containing settings
17986 * \param txChannel Tx channel selection from ::mykonosTxChannels_t
17987 * \param dpdErrCnt pointer to structure of type ::mykonosDpdErrorCounters_t to store the read back error counters
17988 *
17989 * \retval MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM dpdErrCnt is null
17990 * \retval MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH invalid selection for getting the error counters tx channel, only valid values are Tx1 and Tx2
17991 * \retval MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG Arm error while reading the error counters for the DPD status
17992 * \retval MYKONOS_ERR_OK Function completed successfully
17993 */
MYKONOS_getDpdErrorCounters(mykonosDevice_t * device,mykonosTxChannels_t txChannel,mykonosDpdErrorCounters_t * dpdErrCnt)17994 mykonosErr_t MYKONOS_getDpdErrorCounters(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdErrorCounters_t *dpdErrCnt)
17995 {
17996 uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_DPDCONFIG, 0};
17997 uint8_t armData[200] = {0};
17998 uint32_t timeoutMs = 0;
17999 uint8_t cmdStatusByte = 0;
18000 uint8_t loop = 0;
18001 uint8_t index = 0;
18002 uint8_t channelSelect = 0;
18003 mykonosErr_t retVal = MYKONOS_ERR_OK;
18004
18005 #if (MYKONOS_VERBOSE == 1)
18006 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdErrorCounters()\n");
18007 #endif
18008
18009 if (dpdErrCnt == NULL)
18010 {
18011 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM,
18012 getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM));
18013 return MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM;
18014 }
18015
18016 switch (txChannel)
18017 {
18018 case TX1:
18019 channelSelect = 0;
18020 break;
18021 case TX2:
18022 channelSelect = 1;
18023 break;
18024 default:
18025 {
18026 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH,
18027 getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH));
18028 return MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH;
18029 }
18030 }
18031
18032 extData[2] = channelSelect;
18033
18034 retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData));
18035 if (retVal != MYKONOS_ERR_OK)
18036 {
18037 return retVal;
18038 }
18039
18040 timeoutMs = 1000;
18041 retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte);
18042 if (retVal != MYKONOS_ERR_OK)
18043 {
18044 if (cmdStatusByte > 0)
18045 {
18046 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG,
18047 getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG));
18048 return MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG;
18049 }
18050
18051 return retVal;
18052 }
18053
18054 if (cmdStatusByte > 0)
18055 {
18056 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG,
18057 getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG));
18058 return MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG;
18059 }
18060
18061 /* read status from ARM memory */
18062 retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1);
18063 if (retVal != MYKONOS_ERR_OK)
18064 {
18065 return retVal;
18066 }
18067
18068 dpdErrCnt->dpdErrorCount = ((uint32_t)(armData[67]) << 24) | ((uint32_t)(armData[66]) << 16) | ((uint32_t)(armData[65]) << 8) | (uint32_t)(armData[64]);
18069 index = 68;
18070 for (loop = 1; loop < (uint8_t)MYK_DPD_ERROR_END; loop++)
18071 {
18072 dpdErrCnt->errorCounter[loop] = ((uint32_t)(armData[index + 3]) << 24) | ((uint32_t)(armData[index + 2]) << 16) | ((uint32_t)(armData[index + 1]) << 8) | (uint32_t)(armData[index]);
18073 index +=4;
18074 }
18075
18076 return MYKONOS_ERR_OK;
18077 }
18078
18079 /**
18080 * \brief DPD feature to set the bypassing actuator when Tx signal power is below a programmable threshold given in
18081 * ::mykonosDpdBypassConfig_t lowPowerActuatorBypassLevel.
18082 *
18083 * <B>Dependencies</B>
18084 * - device->spiSettings->chipSelectIndex
18085 * - device->profilesValid
18086 *
18087 * \param device Pointer to the Mykonos device data structure containing settings
18088 * \param actConfig Pointer to actuator structure of type ::mykonosDpdBypassConfig_t which contains the settings to be programmed
18089 *
18090 * \retval MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT passed structure is null
18091 * \retval MYKONOS_ERR_SETDPDACT_INV_ACTMODE invalid mode in actConfig->lowPowerActuatorBypassMode for valid modes ::mykonosDpdResetMode_t
18092 * \retval MYKONOS_ERR_SETDPDACT_INV_LEVEL actConfig->lowPowerActuatorBypassLevel outside the range, valid range is 0 to 6000 (0 to 60dB)
18093 * \retval MYKONOS_ERR_OK Function completed successfully
18094 */
MYKONOS_setDpdBypassConfig(mykonosDevice_t * device,mykonosDpdBypassConfig_t * actConfig)18095 mykonosErr_t MYKONOS_setDpdBypassConfig(mykonosDevice_t *device, mykonosDpdBypassConfig_t *actConfig)
18096 {
18097 mykonosErr_t retVal = MYKONOS_ERR_OK;
18098 uint8_t armFieldValue[4] = {0};
18099 uint8_t byteOffset = 62;
18100
18101 const uint16_t LEVEL_RANGE_CHECK = 6000;
18102
18103 #if (MYKONOS_VERBOSE == 1)
18104 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDpdBypassConfig()\n");
18105 #endif
18106
18107 if (actConfig == NULL)
18108 {
18109 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT,
18110 getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT));
18111 return MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT;
18112 }
18113
18114 if (actConfig->bypassActuatorMode >= MYK_DPD_RESET_END)
18115 {
18116 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_ACTMODE,
18117 getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_ACTMODE));
18118 return MYKONOS_ERR_SETDPDACT_INV_ACTMODE;
18119 }
18120
18121 if (actConfig->bypassActuatorLevel > LEVEL_RANGE_CHECK)
18122 {
18123 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_LEVEL,
18124 getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_LEVEL));
18125 return MYKONOS_ERR_SETDPDACT_INV_LEVEL;
18126 }
18127
18128 armFieldValue[0] = (actConfig->bypassActuatorEn > 0) ? 1 : 0;
18129 armFieldValue[1] = (uint8_t)(actConfig->bypassActuatorMode);
18130 armFieldValue[2] = (uint8_t)(actConfig->bypassActuatorLevel & 0xFF);
18131 armFieldValue[3] = (uint8_t)((actConfig->bypassActuatorLevel >> 8) & 0xFF);
18132
18133 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue));
18134 if (retVal != MYKONOS_ERR_OK)
18135 {
18136 return retVal;
18137 }
18138
18139 return MYKONOS_ERR_OK;
18140 }
18141
18142 /**
18143 * \brief Get configuration for bypassing DPD actuator
18144 *
18145 * <B>Dependencies</B>
18146 * - device->spiSettings->chipSelectIndex
18147 * - device->profilesValid
18148 *
18149 * \param device Pointer to the Mykonos device data structure containing settings
18150 * \param actConfig actuator structure of type ::mykonosDpdBypassConfig_t
18151 *
18152 * \retval MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT passed structure is null
18153 * \retval MYKONOS_ERR_OK Function completed successfully
18154 */
MYKONOS_getDpdBypassConfig(mykonosDevice_t * device,mykonosDpdBypassConfig_t * actConfig)18155 mykonosErr_t MYKONOS_getDpdBypassConfig(mykonosDevice_t *device, mykonosDpdBypassConfig_t *actConfig)
18156 {
18157 mykonosErr_t retVal = MYKONOS_ERR_OK;
18158 uint8_t armFieldValue[4] = {0};
18159 uint8_t byteOffset = 62;
18160
18161 #if (MYKONOS_VERBOSE == 1)
18162 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdBypassConfig()\n");
18163 #endif
18164
18165 if (actConfig == NULL)
18166 {
18167 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT,
18168 getMykonosErrorMessage(MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT));
18169 return MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT;
18170 }
18171
18172 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue));
18173 if (retVal != MYKONOS_ERR_OK)
18174 {
18175 return retVal;
18176 }
18177
18178 actConfig->bypassActuatorEn = armFieldValue[0];
18179 actConfig->bypassActuatorMode = (mykonosDpdResetMode_t)armFieldValue[1];
18180 actConfig->bypassActuatorLevel = (uint16_t)(((uint16_t)(armFieldValue[3]) << 8) | (uint16_t)(armFieldValue[2]));
18181
18182 return MYKONOS_ERR_OK;
18183 }
18184
18185 /**
18186 * \brief DPD feature to set the actuator gain difference check.
18187 * If the gain before and after the actuator exceeds the value actCheck->actuatorGainCheckLevel an error will be issued
18188 * and the actuator will reset depending on the actCheck->actuatorGainCheckMode.
18189 *
18190 * <B>Dependencies</B>
18191 * - device->spiSettings->chipSelectIndex
18192 * - device->profilesValid
18193 *
18194 * \param device Pointer to the Mykonos device data structure containing settings
18195 * \param actCheck Pointer to structure of type mykonosDpdActuatorCheck_t which contains the settings to be programmed
18196 *
18197 * \retval MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT passed structure is null
18198 * \retval MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE invalid mode in actCheck->actuatorGainCheckMode for valid modes ::mykonosDpdResetMode_t
18199 * \retval MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL actCheck->actuatorGainCheckLevel outside the range, valid range is from 0 to 3000 (0 to 30dB)
18200 * \retval MYKONOS_ERR_OK Function completed successfully
18201 */
MYKONOS_setDpdActuatorCheck(mykonosDevice_t * device,mykonosDpdActuatorCheck_t * actCheck)18202 mykonosErr_t MYKONOS_setDpdActuatorCheck(mykonosDevice_t *device, mykonosDpdActuatorCheck_t *actCheck)
18203 {
18204 mykonosErr_t retVal = MYKONOS_ERR_OK;
18205 uint8_t armFieldValue[4] = {0};
18206 uint8_t byteOffset = 58;
18207
18208 const uint16_t LEVEL_RANGE_CHECK = 3000;
18209
18210 #if (MYKONOS_VERBOSE == 1)
18211 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDpdActuatorCheck()\n");
18212 #endif
18213
18214 if (actCheck == NULL)
18215 {
18216 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT,
18217 getMykonosErrorMessage(MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT));
18218 return MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT;
18219 }
18220
18221 if (actCheck->actuatorGainCheckMode >= MYK_DPD_RESET_END)
18222 {
18223 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE,
18224 getMykonosErrorMessage(MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE));
18225 return MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE;
18226 }
18227
18228 if (actCheck->actuatorGainCheckLevel > LEVEL_RANGE_CHECK)
18229 {
18230 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL,
18231 getMykonosErrorMessage(MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL));
18232 return MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL;
18233 }
18234
18235 armFieldValue[0] = (actCheck->actuatorGainCheckEn > 0) ? 1 : 0;
18236 armFieldValue[1] = (uint8_t)(actCheck->actuatorGainCheckMode);
18237 armFieldValue[2] = (uint8_t)(actCheck->actuatorGainCheckLevel & 0xFF);
18238 armFieldValue[3] = (uint8_t)((actCheck->actuatorGainCheckLevel >> 8) & 0xFF);
18239
18240 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue));
18241 if (retVal != MYKONOS_ERR_OK)
18242 {
18243 return retVal;
18244 }
18245
18246 return MYKONOS_ERR_OK;
18247 }
18248
18249
18250 /**
18251 * \brief Get configuration for DPD actuator check
18252 *
18253 * <B>Dependencies</B>
18254 * - device->spiSettings->chipSelectIndex
18255 * - device->profilesValid
18256 *
18257 * \param device Pointer to the Mykonos device data structure containing settings
18258 * \param actCheck Pointer to structure of type mykonosDpdActuatorCheck_t which will contain the programmed settings
18259 *
18260 * \retval MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT passed structure is null
18261 * \retval MYKONOS_ERR_OK Function completed successfully
18262 */
MYKONOS_getDpdActuatorCheck(mykonosDevice_t * device,mykonosDpdActuatorCheck_t * actCheck)18263 mykonosErr_t MYKONOS_getDpdActuatorCheck(mykonosDevice_t *device, mykonosDpdActuatorCheck_t *actCheck)
18264 {
18265 mykonosErr_t retVal = MYKONOS_ERR_OK;
18266 uint8_t armFieldValue[4] = {0};
18267 uint8_t byteOffset = 58;
18268
18269 #if (MYKONOS_VERBOSE == 1)
18270 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdActuatorCheck()\n");
18271 #endif
18272
18273 if (actCheck == NULL)
18274 {
18275 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT,
18276 getMykonosErrorMessage(MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT));
18277 return MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT;
18278 }
18279
18280 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue));
18281 if (retVal != MYKONOS_ERR_OK)
18282 {
18283 return retVal;
18284 }
18285
18286 actCheck->actuatorGainCheckEn = armFieldValue[0];
18287 actCheck->actuatorGainCheckMode = (mykonosDpdResetMode_t)armFieldValue[1];
18288 actCheck->actuatorGainCheckLevel = (uint16_t)(((uint16_t)(armFieldValue[3]) << 8) | (uint16_t)(armFieldValue[2]));
18289
18290 return MYKONOS_ERR_OK;
18291 }
18292
18293
18294 /**
18295 * \brief CLGC feature to set the TX attenuation tuning range to a relative range around a nominal value
18296 *
18297 * <B>Dependencies</B>
18298 * - device->spiSettings->chipSelectIndex
18299 * - device->profilesValid
18300 *
18301 * \param device Pointer to the Mykonos device data structure containing settings
18302 * \param attRangeCfg Pointer to structure of type mykonosClgcAttenTuningConfig_t which contains the settings to be programmed
18303 *
18304 * \retval MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV Tx and ObsRx profiles must be valid to use the CLGC feature
18305 * \retval MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT Passed structure is null
18306 * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE Invalid mode in attRangeCfg member, for valid modes ::mykonosClgcAttenTuningMode_t
18307 * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET Invalid AttenTuningPreset in attRangeCfg member, valid range is from 0 to 839 (0 to 41.95dB)
18308 * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE Invalid AttenTuningRange in attRangeCfg member, valid range is from 0 to 420 (0 to 21dB)
18309 * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS Invalid Tx1 AttenTuningRange and AttenTuningPreset combination
18310 * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS Invalid Tx2 AttenTuningRange and AttenTuningPreset combination
18311 * \retval MYKONOS_ERR_OK Function completed successfully
18312 */
MYKONOS_setClgcAttenTuningConfig(mykonosDevice_t * device,mykonosClgcAttenTuningConfig_t * attRangeCfg)18313 mykonosErr_t MYKONOS_setClgcAttenTuningConfig(mykonosDevice_t *device, mykonosClgcAttenTuningConfig_t *attRangeCfg)
18314 {
18315 mykonosErr_t retVal = MYKONOS_ERR_OK;
18316 uint8_t armFieldValue[10] = {0};
18317 uint8_t byteOffset = 0x2C;
18318
18319 const uint16_t PRESET_CHECK = 840;
18320 const uint16_t RANGE_CHECK = 420;
18321
18322 #if (MYKONOS_VERBOSE == 1)
18323 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setClgcAttenTuningConfig()\n");
18324 #endif
18325
18326 /* CLGC requires Tx and ORx enabled, throw error if both are not enabled */
18327 if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID))
18328 {
18329 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV,
18330 getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV));
18331 return MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV;
18332 }
18333
18334 if (attRangeCfg == NULL)
18335 {
18336 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT,
18337 getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT));
18338 return MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT;
18339 }
18340
18341 /* Range checks */
18342 if ((attRangeCfg->tx1AttenTuningLimitMode >= MYK_CLGC_ATTEN_END) || (attRangeCfg->tx2AttenTuningLimitMode >= MYK_CLGC_ATTEN_END))
18343 {
18344 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE,
18345 getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE));
18346 return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE;
18347 }
18348
18349 if ((attRangeCfg->tx1AttenTuningPreset >= PRESET_CHECK) || (attRangeCfg->tx2AttenTuningPreset >= PRESET_CHECK))
18350 {
18351 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET,
18352 getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET));
18353 return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET;
18354 }
18355
18356 if ((attRangeCfg->tx1AttenTuningRange > RANGE_CHECK) || (attRangeCfg->tx2AttenTuningRange > RANGE_CHECK))
18357 {
18358 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE,
18359 getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE));
18360 return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE;
18361 }
18362
18363 if (((attRangeCfg->tx1AttenTuningPreset - attRangeCfg->tx1AttenTuningRange) < 0) ||
18364 ((attRangeCfg->tx1AttenTuningPreset + attRangeCfg->tx1AttenTuningRange) > PRESET_CHECK))
18365 {
18366 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS,
18367 getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS));
18368 return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS;
18369 }
18370
18371 if (((attRangeCfg->tx2AttenTuningPreset - attRangeCfg->tx2AttenTuningRange) < 0) ||
18372 ((attRangeCfg->tx2AttenTuningPreset + attRangeCfg->tx2AttenTuningRange) > PRESET_CHECK))
18373 {
18374 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS,
18375 getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS));
18376 return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS;
18377 }
18378
18379 armFieldValue[0] = (uint8_t)(attRangeCfg->tx1AttenTuningLimitMode & 0xFF);
18380 armFieldValue[1] = (uint8_t)(attRangeCfg->tx2AttenTuningLimitMode & 0xFF);
18381 armFieldValue[2] = (uint8_t)(attRangeCfg->tx1AttenTuningPreset & 0xFF);
18382 armFieldValue[3] = (uint8_t)((attRangeCfg->tx1AttenTuningPreset >> 8) & 0xFF);
18383 armFieldValue[4] = (uint8_t)(attRangeCfg->tx2AttenTuningPreset & 0xFF);
18384 armFieldValue[5] = (uint8_t)((attRangeCfg->tx2AttenTuningPreset >> 8) & 0xFF);
18385 armFieldValue[6] = (uint8_t)(attRangeCfg->tx1AttenTuningRange & 0xFF);
18386 armFieldValue[7] = (uint8_t)((attRangeCfg->tx1AttenTuningRange >> 8) & 0xFF);
18387 armFieldValue[8] = (uint8_t)(attRangeCfg->tx2AttenTuningRange & 0xFF);
18388 armFieldValue[9] = (uint8_t)((attRangeCfg->tx2AttenTuningRange >> 8) & 0xFF);
18389
18390 retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue));
18391 if (retVal != MYKONOS_ERR_OK)
18392 {
18393 return retVal;
18394 }
18395
18396 return MYKONOS_ERR_OK;
18397 }
18398
18399
18400 /**
18401 * \brief Get configuration for CLGC Tx attenuation tuning range.
18402 *
18403 * <B>Dependencies</B>
18404 * - device->spiSettings->chipSelectIndex
18405 * - device->profilesValid
18406 *
18407 * \param device Pointer to the Mykonos device data structure containing settings
18408 * \param attRangeCfg Pointer to structure of type mykonosClgcAttenTuningConfig_t which will contain the programmed settings
18409 *
18410 * \retval MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT passed structure is null
18411 * \retval MYKONOS_ERR_OK Function completed successfully
18412 */
MYKONOS_getClgcAttenTuningConfig(mykonosDevice_t * device,mykonosClgcAttenTuningConfig_t * attRangeCfg)18413 mykonosErr_t MYKONOS_getClgcAttenTuningConfig(mykonosDevice_t *device, mykonosClgcAttenTuningConfig_t *attRangeCfg)
18414 {
18415 mykonosErr_t retVal = MYKONOS_ERR_OK;
18416 uint8_t armFieldValue[10] = {0};
18417 uint8_t byteOffset = 0x2C;
18418
18419 #if (MYKONOS_VERBOSE == 1)
18420 CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getClgcAttenTuningConfig()\n");
18421 #endif
18422
18423 if (attRangeCfg == NULL)
18424 {
18425 CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT,
18426 getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT));
18427 return MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT;
18428 }
18429
18430 retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue));
18431 if (retVal != MYKONOS_ERR_OK)
18432 {
18433 return retVal;
18434 }
18435
18436 attRangeCfg->tx1AttenTuningLimitMode = (mykonosClgcAttenTuningMode_t)armFieldValue[0];
18437 attRangeCfg->tx2AttenTuningLimitMode = (mykonosClgcAttenTuningMode_t)armFieldValue[1];
18438 attRangeCfg->tx1AttenTuningPreset = (uint16_t)(((uint16_t)(armFieldValue[3]) << 8) | (uint16_t)(armFieldValue[2]));
18439 attRangeCfg->tx2AttenTuningPreset = (uint16_t)(((uint16_t)(armFieldValue[5]) << 8) | (uint16_t)(armFieldValue[4]));
18440 attRangeCfg->tx1AttenTuningRange = (uint16_t)(((uint16_t)(armFieldValue[7]) << 8) | (uint16_t)(armFieldValue[6]));
18441 attRangeCfg->tx2AttenTuningRange = (uint16_t)(((uint16_t)(armFieldValue[9]) << 8) | (uint16_t)(armFieldValue[8]));
18442
18443 return MYKONOS_ERR_OK;
18444 }
18445