amiro-lld / drivers / DW1000 / v2 / decadriver / deca_device.c @ 99ca7610
History | View | Annotate | Download (142.18 KB)
1 | 22401187 | Thomas Schöpping | /*! ------------------------------------------------------------------------------------------------------------------
|
---|---|---|---|
2 | * @file deca_device.c
|
||
3 | * @brief Decawave device configuration and control functions
|
||
4 | *
|
||
5 | * @attention
|
||
6 | *
|
||
7 | * Copyright 2013 (c) Decawave Ltd, Dublin, Ireland.
|
||
8 | *
|
||
9 | * All rights reserved.
|
||
10 | *
|
||
11 | */
|
||
12 | |||
13 | #include <assert.h> |
||
14 | #include <stdlib.h> |
||
15 | |||
16 | #include "deca_types.h" |
||
17 | #include "deca_param_types.h" |
||
18 | #include "deca_regs.h" |
||
19 | #include "deca_device_api.h" |
||
20 | |||
21 | // Defines for enable_clocks function
|
||
22 | #define FORCE_SYS_XTI 0 |
||
23 | #define ENABLE_ALL_SEQ 1 |
||
24 | #define FORCE_SYS_PLL 2 |
||
25 | #define READ_ACC_ON 7 |
||
26 | #define READ_ACC_OFF 8 |
||
27 | #define FORCE_OTP_ON 11 |
||
28 | #define FORCE_OTP_OFF 12 |
||
29 | #define FORCE_TX_PLL 13 |
||
30 | #define FORCE_LDE 14 |
||
31 | |||
32 | // Defines for ACK request bitmask in DATA and MAC COMMAND frame control (first byte) - Used to detect AAT bit wrongly set.
|
||
33 | #define FCTRL_ACK_REQ_MASK 0x20 |
||
34 | // Frame control maximum length in bytes.
|
||
35 | #define FCTRL_LEN_MAX 2 |
||
36 | |||
37 | // #define DWT_API_ERROR_CHECK // define so API checks config input parameters
|
||
38 | |||
39 | // -------------------------------------------------------------------------------------------------------------------
|
||
40 | //
|
||
41 | // Internal functions for controlling and configuring the device
|
||
42 | //
|
||
43 | // -------------------------------------------------------------------------------------------------------------------
|
||
44 | |||
45 | // Enable and Configure specified clocks
|
||
46 | void _dwt_enableclocks(int clocks) ; |
||
47 | // Configure the ucode (FP algorithm) parameters
|
||
48 | void _dwt_configlde(int prf); |
||
49 | // Load ucode from OTP/ROM
|
||
50 | void _dwt_loaducodefromrom(void); |
||
51 | // Read non-volatile memory
|
||
52 | uint32 _dwt_otpread(uint16 address); |
||
53 | // Program the non-volatile memory
|
||
54 | uint32 _dwt_otpprogword32(uint32 data, uint16 address); |
||
55 | // Upload the device configuration into always on memory
|
||
56 | void _dwt_aonarrayupload(void); |
||
57 | // -------------------------------------------------------------------------------------------------------------------
|
||
58 | |||
59 | /*!
|
||
60 | * Static data for DW1000 DecaWave Transceiver control
|
||
61 | */
|
||
62 | |||
63 | // -------------------------------------------------------------------------------------------------------------------
|
||
64 | // Structure to hold device data
|
||
65 | typedef struct |
||
66 | { |
||
67 | uint32 partID ; // IC Part ID - read during initialisation
|
||
68 | uint32 lotID ; // IC Lot ID - read during initialisation
|
||
69 | uint8 vBatP ; // IC V bat read during production and stored in OTP (Vmeas @ 3V3)
|
||
70 | uint8 tempP ; // IC V temp read during production and stored in OTP (Tmeas @ 23C)
|
||
71 | uint8 longFrames ; // Flag in non-standard long frame mode
|
||
72 | uint8 otprev ; // OTP revision number (read during initialisation)
|
||
73 | uint32 txFCTRL ; // Keep TX_FCTRL register config
|
||
74 | uint32 sysCFGreg ; // Local copy of system config register
|
||
75 | uint8 dblbuffon; // Double RX buffer mode flag
|
||
76 | uint8 wait4resp ; // wait4response was set with last TX start command
|
||
77 | uint16 sleep_mode; // Used for automatic reloading of LDO tune and microcode at wake-up
|
||
78 | uint16 otp_mask ; // Local copy of the OTP mask used in dwt_initialise call
|
||
79 | dwt_cb_data_t cbData; // Callback data structure
|
||
80 | dwt_cb_t cbTxDone; // Callback for TX confirmation event
|
||
81 | dwt_cb_t cbRxOk; // Callback for RX good frame event
|
||
82 | dwt_cb_t cbRxTo; // Callback for RX timeout events
|
||
83 | dwt_cb_t cbRxErr; // Callback for RX error events
|
||
84 | } dwt_local_data_t ; |
||
85 | |||
86 | static dwt_local_data_t dw1000local[DWT_NUM_DW_DEV] ; // Static local device data, can be an array to support multiple DW1000 testing applications/platforms |
||
87 | static dwt_local_data_t *pdw1000local = dw1000local ; // Static local data structure pointer |
||
88 | |||
89 | |||
90 | /*! ------------------------------------------------------------------------------------------------------------------
|
||
91 | * @fn dwt_apiversion()
|
||
92 | *
|
||
93 | * @brief This function returns the version of the API as defined by DW1000_DRIVER_VERSION
|
||
94 | *
|
||
95 | * input parameters
|
||
96 | *
|
||
97 | * output parameters
|
||
98 | *
|
||
99 | * returns version (DW1000_DRIVER_VERSION)
|
||
100 | */
|
||
101 | int32 dwt_apiversion(void)
|
||
102 | { |
||
103 | return DW1000_DRIVER_VERSION ;
|
||
104 | } |
||
105 | |||
106 | /*! ------------------------------------------------------------------------------------------------------------------
|
||
107 | * @fn dwt_setlocaldataptr()
|
||
108 | *
|
||
109 | * @brief This function sets the local data structure pointer to point to the element in the local array as given by the index.
|
||
110 | *
|
||
111 | * input parameters
|
||
112 | * @param index - selects the array element to point to. Must be within the array bounds, i.e. < DWT_NUM_DW_DEV
|
||
113 | *
|
||
114 | * output parameters
|
||
115 | *
|
||
116 | * returns DWT_SUCCESS for success, or DWT_ERROR for error
|
||
117 | */
|
||
118 | int dwt_setlocaldataptr(unsigned int index) |
||
119 | { |
||
120 | // Check the index is within the array bounds
|
||
121 | if (DWT_NUM_DW_DEV <= index) // return error if index outside the array bounds |
||
122 | { |
||
123 | return DWT_ERROR ;
|
||
124 | } |
||
125 | |||
126 | pdw1000local = &dw1000local[index]; |
||
127 | |||
128 | return DWT_SUCCESS ;
|
||
129 | } |
||
130 | |||
131 | /*! ------------------------------------------------------------------------------------------------------------------
|
||
132 | * @fn dwt_initialise()
|
||
133 | *
|
||
134 | * @brief This function initiates communications with the DW1000 transceiver
|
||
135 | * and reads its DEV_ID register (address 0x00) to verify the IC is one supported
|
||
136 | * by this software (e.g. DW1000 32-bit device ID value is 0xDECA0130). Then it
|
||
137 | * does any initial once only device configurations needed for its use and initialises
|
||
138 | * as necessary any static data items belonging to this low-level driver.
|
||
139 | *
|
||
140 | * This function does not need to be called after DW1000 device is woken up from DEEPSLEEP,
|
||
141 | * the device will preserve register values e.g. LDO, UCODE, XTAL. However if needed this
|
||
142 | * function can be called to initialise internal structure dw1000local[] if it has not been preserved
|
||
143 | * (e.g. if micro was in sleep and its RAM data (containing dw1000local structure was not preserved during sleep)
|
||
144 | *
|
||
145 | * NOTES:
|
||
146 | * 1. When DW1000 is powered on this function needs to be run before dwt_configuresleep,
|
||
147 | * also the SPI frequency has to be < 3MHz
|
||
148 | * 2. It reads and applies LDO tune and crystal trim values from OTP memory
|
||
149 | * 3. If accurate RX timestamping is needed microcode/LDE must be loaded
|
||
150 | *
|
||
151 | * input parameters
|
||
152 | * @param config - specifies what configuration to load
|
||
153 | * DWT_LOADNONE 0x00 - do not load any values from OTP memory
|
||
154 | * DWT_LOADUCODE 0x01 - load the LDE microcode from ROM - enable accurate RX timestamp
|
||
155 | * DWT_DW_WAKE_UP 0x02 - just initialise dw1000local[] values (e.g. DW1000 has woken up)
|
||
156 | * DWT_DW_WUP_NO_UCODE 0x04 - if microcode/LDE algorithm has not already been loaded (on power up) e.g. when LDE is not used
|
||
157 | * DWT_READ_OTP_PID 0x10 - read part ID from OTP
|
||
158 | * DWT_READ_OTP_LID 0x20 - read lot ID from OTP
|
||
159 | * DWT_READ_OTP_BAT 0x40 - read ref voltage from OTP
|
||
160 | * DWT_READ_OTP_TMP 0x80 - read ref temperature from OTP
|
||
161 | * output parameters
|
||
162 | *
|
||
163 | * returns DWT_SUCCESS for success, or DWT_ERROR for error
|
||
164 | */
|
||
165 | // OTP addresses definitions
|
||
166 | #define LDOTUNE_ADDRESS (0x04) |
||
167 | #define PARTID_ADDRESS (0x06) |
||
168 | #define LOTID_ADDRESS (0x07) |
||
169 | #define VBAT_ADDRESS (0x08) |
||
170 | #define VTEMP_ADDRESS (0x09) |
||
171 | #define XTRIM_ADDRESS (0x1E) |
||
172 | |||
173 | int dwt_initialise(int config) |
||
174 | { |
||
175 | uint16 otp_xtaltrim_and_rev = 0;
|
||
176 | uint32 ldo_tune = 0;
|
||
177 | |||
178 | pdw1000local->dblbuffon = 0; // - set to 0 - meaning double buffer mode is off by default |
||
179 | pdw1000local->wait4resp = 0; // - set to 0 - meaning wait for response not active |
||
180 | pdw1000local->sleep_mode = 0; // - set to 0 - meaning sleep mode has not been configured |
||
181 | |||
182 | pdw1000local->cbTxDone = NULL;
|
||
183 | pdw1000local->cbRxOk = NULL;
|
||
184 | pdw1000local->cbRxTo = NULL;
|
||
185 | pdw1000local->cbRxErr = NULL;
|
||
186 | |||
187 | #if DWT_API_ERROR_CHECK
|
||
188 | pdw1000local->otp_mask = config ; // Save the READ_OTP config mask
|
||
189 | #endif
|
||
190 | |||
191 | // Read and validate device ID, return -1 if not recognised
|
||
192 | if (DWT_DEVICE_ID != dwt_readdevid()) // MP IC ONLY (i.e. DW1000) FOR THIS CODE |
||
193 | { |
||
194 | return DWT_ERROR ;
|
||
195 | } |
||
196 | |||
197 | if(!(DWT_DW_WAKE_UP & config)) // Don't reset the device if DWT_DW_WAKE_UP bit is set, e.g. when calling this API after wake up |
||
198 | { |
||
199 | dwt_softreset(); // Make sure the device is completely reset before starting initialisation
|
||
200 | } |
||
201 | |||
202 | if(!((DWT_DW_WAKE_UP & config) && ((DWT_READ_OTP_TMP | DWT_READ_OTP_BAT | DWT_READ_OTP_LID | DWT_READ_OTP_PID | DWT_DW_WUP_RD_OTPREV)& config)))
|
||
203 | { |
||
204 | _dwt_enableclocks(FORCE_SYS_XTI); // NOTE: set system clock to XTI - this is necessary to make sure the values read by _dwt_otpread are reliable
|
||
205 | } // when not reading from OTP, clocks don't need to change.
|
||
206 | |||
207 | // Configure the CPLL lock detect
|
||
208 | dwt_write8bitoffsetreg(EXT_SYNC_ID, EC_CTRL_OFFSET, EC_CTRL_PLLLCK); |
||
209 | |||
210 | // When DW1000 IC is initialised from power up, then the LDO value should be kicked from OTP, otherwise if this API is called after
|
||
211 | // DW1000 IC has been woken up (DWT_DW_WAKE_UP bit is set) this can be skipped as LDO would have already been automatically
|
||
212 | // kicked/loaded on wake up
|
||
213 | if(!(DWT_DW_WAKE_UP & config))
|
||
214 | { |
||
215 | // Load LDO tune from OTP and kick it if there is a value actually programmed.
|
||
216 | ldo_tune = _dwt_otpread(LDOTUNE_ADDRESS); |
||
217 | if((ldo_tune & 0xFF) != 0) |
||
218 | { |
||
219 | // Kick LDO tune
|
||
220 | dwt_write8bitoffsetreg(OTP_IF_ID, OTP_SF, OTP_SF_LDO_KICK); // Set load LDO kick bit
|
||
221 | pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDO; // LDO tune must be kicked at wake-up
|
||
222 | } |
||
223 | } |
||
224 | else
|
||
225 | { //if LDOTUNE reg contains value different from default it means it was kicked from OTP and thus set AON_WCFG_ONW_LLDO.
|
||
226 | if(dwt_read32bitoffsetreg(RF_CONF_ID, LDOTUNE) != LDOTUNE_DEFAULT)
|
||
227 | pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDO; |
||
228 | } |
||
229 | |||
230 | if((!(DWT_DW_WAKE_UP & config)) || ((DWT_DW_WAKE_UP & config) && (DWT_DW_WUP_RD_OTPREV & config)))
|
||
231 | { |
||
232 | // Read OTP revision number
|
||
233 | otp_xtaltrim_and_rev = _dwt_otpread(XTRIM_ADDRESS) & 0xffff; // Read 32 bit value, XTAL trim val is in low octet-0 (5 bits) |
||
234 | pdw1000local->otprev = (otp_xtaltrim_and_rev >> 8) & 0xff; // OTP revision is the next byte |
||
235 | } |
||
236 | else
|
||
237 | pdw1000local->otprev = 0; // If OTP valuse are not used, if this API is called after DW1000 IC has been woken up |
||
238 | // (DWT_DW_WAKE_UP bit is set), set otprev to 0
|
||
239 |