amiro-lld / drivers / DW1000 / v1 / deca_instance_common.c @ 9466e34d
History | View | Annotate | Download (71.11 KB)
1 | 69a601a5 | Cung Sang | /*! ----------------------------------------------------------------------------
|
---|---|---|---|
2 | * @file instance_common.c
|
||
3 | * @brief DecaWave application level common instance functions
|
||
4 | *
|
||
5 | * @attention
|
||
6 | *
|
||
7 | * Copyright 2015 (c) DecaWave Ltd, Dublin, Ireland.
|
||
8 | *
|
||
9 | * All rights reserved.
|
||
10 | *
|
||
11 | * @author DecaWave
|
||
12 | */
|
||
13 | |||
14 | #include <alld_DW1000.h> |
||
15 | 9466e34d | Thomas Schöpping | #include <module.h> |
16 | 69a601a5 | Cung Sang | #include <string.h> |
17 | #include <math.h> |
||
18 | 9466e34d | Thomas Schöpping | #include <deca_instance.h> |
19 | 33f54213 | Cung Sang | |
20 | |||
21 | /*! @brief Software defined configuration settings for RTLS applications */
|
||
22 | /*! Configuration for DecaRangeRTLS TREK Modes (4 default use cases selected by the switch S1 [2,3] on EVB1000, indexed 0 to 3 )*/
|
||
23 | instanceConfig_t chConfig[4] ={
|
||
24 | //mode 1 - S1: 2 off, 3 off
|
||
25 | { |
||
26 | .channelNumber = 2, // channel |
||
27 | .preambleCode = 4, // preambleCode |
||
28 | .pulseRepFreq = DWT_PRF_16M, // prf
|
||
29 | .dataRate = DWT_BR_110K, // datarate
|
||
30 | .preambleLen = DWT_PLEN_1024, // preambleLength
|
||
31 | .pacSize = DWT_PAC32, // pacSize
|
||
32 | .nsSFD = 1, // non-standard SFD |
||
33 | .sfdTO = (1025 + 64 - 32) // SFD timeout |
||
34 | }, |
||
35 | //mode 2 - S1: 2 on, 3 off
|
||
36 | { |
||
37 | .channelNumber = 2, // channel |
||
38 | .preambleCode = 4, // preambleCode |
||
39 | .pulseRepFreq = DWT_PRF_16M, // prf
|
||
40 | .dataRate = DWT_BR_6M8, // datarate
|
||
41 | .preambleLen = DWT_PLEN_128, // preambleLength
|
||
42 | .pacSize = DWT_PAC8, // pacSize
|
||
43 | .nsSFD = 0, // non-standard SFD |
||
44 | .sfdTO = (129 + 8 - 8) // SFD timeout |
||
45 | }, |
||
46 | //mode 3 - S1: 2 off, 3 on
|
||
47 | { |
||
48 | .channelNumber = 5, // channel |
||
49 | .preambleCode = 3, // preambleCode |
||
50 | .pulseRepFreq = DWT_PRF_16M, // prf
|
||
51 | .dataRate = DWT_BR_110K, // datarate
|
||
52 | .preambleLen = DWT_PLEN_1024, // preambleLength
|
||
53 | .pacSize = DWT_PAC32, // pacSize
|
||
54 | .nsSFD = 1, // non-standard SFD |
||
55 | .sfdTO = (1025 + 64 - 32) // SFD timeout |
||
56 | }, |
||
57 | //mode 4 - S1: 2 on, 3 on
|
||
58 | { |
||
59 | .channelNumber = 5, // channel |
||
60 | .preambleCode = 3, // preambleCode |
||
61 | .pulseRepFreq = DWT_PRF_16M, // prf
|
||
62 | .dataRate = DWT_BR_6M8, // datarate
|
||
63 | .preambleLen = DWT_PLEN_128, // preambleLength
|
||
64 | .pacSize = DWT_PAC8, // pacSize
|
||
65 | .nsSFD = 0, // non-standard SFD |
||
66 | .sfdTO = (129 + 8 - 8) // SFD timeout |
||
67 | } |
||
68 | }; |
||
69 | 69a601a5 | Cung Sang | |
70 | |||
71 | 33f54213 | Cung Sang | /*! Slot and Superframe Configuration for DecaRangeRTLS TREK Modes (4 default use cases selected by the switch S1 [2,3] on EVB1000, indexed 0 to 3 )*/
|
72 | sfConfig_t sfConfig[4] ={
|
||
73 | //mode 1 - S1: 2 off, 3 off
|
||
74 | { |
||
75 | .slotPeriod = (28), //slot duration in milliseconds (NOTE: the ranging exchange must be able to complete in this time |
||
76 | //e.g. tag sends a poll, 4 anchors send responses and tag sends the final + processing time
|
||
77 | .numSlots = (10), //number of slots in the superframe (8 tag slots and 2 used for anchor to anchor ranging), |
||
78 | .sfPeriod = (10*28), //in ms => 280ms frame means 3.57 Hz location rate |
||
79 | .pollSleepDly = (10*28), //tag period in ms (sleep time + ranging time) |
||
80 | .replyDly = (25000) //poll to final delay in microseconds (needs to be adjusted according to lengths of ranging frames) |
||
81 | }, |
||
82 | #if (DISCOVERY == 1) |
||
83 | //mode 2 - S1: 2 on, 3 off
|
||
84 | { |
||
85 | .slotPeriod = (10), //slot duration in milliseconds (NOTE: the ranging exchange must be able to complete in this time |
||
86 | //e.g. tag sends a poll, 4 anchors send responses and tag sends the final + processing time
|
||
87 | .numSlots = (100), //number of slots in the superframe (98 tag slots and 2 used for anchor to anchor ranging), |
||
88 | .sfPeriod = (10*100), //in ms => 1000 ms frame means 1 Hz location rate |
||
89 | .pollSleepDly = (10*100), //tag period in ms (sleep time + ranging time) |
||
90 | .replyDly = (2500) //poll to final delay in microseconds (needs to be adjusted according to lengths of ranging frames) |
||
91 | |||
92 | }, |
||
93 | #else
|
||
94 | //mode 2 - S1: 2 on, 3 off
|
||
95 | { |
||
96 | .slotPeriod = (10), //slot duration in milliseconds (NOTE: the ranging exchange must be able to complete in this time |
||
97 | //e.g. tag sends a poll, 4 anchors send responses and tag sends the final + processing time
|
||
98 | .numSlots = (10), //number of slots in the superframe (8 tag slots and 2 used for anchor to anchor ranging), |
||
99 | .sfPeriod = (10*10), //in ms => 100 ms frame means 10 Hz location rate |
||
100 | .pollSleepDly = (10*10), //tag period in ms (sleep time + ranging time) |
||
101 | .replyDly = (2500) //poll to final delay in microseconds (needs to be adjusted according to lengths of ranging frames) |
||
102 | }, |
||
103 | #endif
|
||
104 | //mode 3 - S1: 2 off, 3 on
|
||
105 | { |
||
106 | .slotPeriod = (28), //slot duration in milliseconds (NOTE: the ranging exchange must be able to complete in this time |
||
107 | //e.g. tag sends a poll, 4 anchors send responses and tag sends the final + processing time
|
||
108 | .numSlots = (10), //number of slots in the superframe (8 tag slots and 2 used for anchor to anchor ranging), |
||
109 | .sfPeriod = (10*28), //in ms => 280ms frame means 3.57 Hz location rate |
||
110 | .pollSleepDly = (10*28), //tag period in ms (sleep time + ranging time) |
||
111 | .replyDly = (20000) //poll to final delay in microseconds (needs to be adjusted according to lengths of ranging frames) |
||
112 | |||
113 | }, |
||
114 | //mode 4 - S1: 2 on, 3 on
|
||
115 | { |
||
116 | .slotPeriod = (10), //slot duration in milliseconds (NOTE: the ranging exchange must be able to complete in this time |
||
117 | //e.g. tag sends a poll, 4 anchors send responses and tag sends the final + processing time
|
||
118 | .numSlots = (10), //number of slots in the superframe (8 tag slots and 2 used for anchor to anchor ranging), |
||
119 | .sfPeriod = (10*10), //in ms => 100 ms frame means 10 Hz location rate |
||
120 | .pollSleepDly = (10*10), //tag period in ms (sleep time + ranging time) |
||
121 | .replyDly = (2500) //poll to final delay in microseconds (needs to be adjusted according to lengths of ranging frames) |
||
122 | } |
||
123 | }; |
||
124 | 69a601a5 | Cung Sang | |
125 | |||
126 | // -------------------------------------------------------------------------------------------------------------------
|
||
127 | |||
128 | //The table below specifies the default TX spectrum configuration parameters... this has been tuned for DW EVK hardware units
|
||
129 | //the table is set for smart power - see below in the instance_config function how this is used when not using smart power
|
||
130 | const tx_struct txSpectrumConfig[8] = |
||
131 | { |
||
132 | //Channel 0 ----- this is just a place holder so the next array element is channel 1
|
||
133 | { |
||
134 | 0x0, //0 |
||
135 | { |
||
136 | 0x0, //0 |
||
137 | 0x0 //0 |
||
138 | } |
||
139 | }, |
||
140 | //Channel 1
|
||
141 | { |
||
142 | 0xc9, //PG_DELAY |
||
143 | { |
||
144 | 0x15355575, //16M prf power |
||
145 | 0x07274767 //64M prf power |
||
146 | } |
||
147 | |||
148 | }, |
||
149 | //Channel 2
|
||
150 | { |
||
151 | 0xc2, //PG_DELAY |
||
152 | { |
||
153 | 0x15355575, //16M prf power |
||
154 | 0x07274767 //64M prf power |
||
155 | } |
||
156 | }, |
||
157 | //Channel 3
|
||
158 | { |
||
159 | 0xc5, //PG_DELAY |
||
160 | { |
||
161 | 0x0f2f4f6f, //16M prf power |
||
162 | 0x2b4b6b8b //64M prf power |
||
163 | } |
||
164 | }, |
||
165 | //Channel 4
|
||
166 | { |
||
167 | 0x95, //PG_DELAY |
||
168 | { |
||
169 | 0x1f1f3f5f, //16M prf power |
||
170 | 0x3a5a7a9a //64M prf power |
||
171 | } |
||
172 | }, |
||
173 | //Channel 5
|
||
174 | { |
||
175 | 0xc0, //PG_DELAY |
||
176 | { |
||
177 | 0x0E082848, //16M prf power |
||
178 | 0x25456585 //64M prf power |
||
179 | } |
||
180 | }, |
||
181 | //Channel 6 ----- this is just a place holder so the next array element is channel 7
|
||
182 | { |
||
183 | 0x0, //0 |
||
184 | { |
||
185 | 0x0, //0 |
||
186 | 0x0 //0 |
||
187 | } |
||
188 | }, |
||
189 | //Channel 7
|
||
190 | { |
||
191 | 0x93, //PG_DELAY |
||
192 | { |
||
193 | 0x32527292, //16M prf power |
||
194 | 0x5171B1d1 //64M prf power |
||
195 | } |
||
196 | } |
||
197 | }; |
||
198 | |||
199 | //these are default antenna delays for EVB1000, these can be used if there is no calibration data in the DW1000,
|
||
200 | //or instead of the calibration data
|
||
201 | const uint16_t rfDelays[2] = { |
||
202 | 26dead12 | Cung Sang | (uint16_t) (((double)DWT_PRF_16M_RFDLY/ 2.0) * 1e-9 / DWT_TIME_UNITS),//PRF 16 |
203 | (uint16_t) (((double)DWT_PRF_64M_RFDLY/ 2.0) * 1e-9 / DWT_TIME_UNITS) |
||
204 | 69a601a5 | Cung Sang | }; |
205 | |||
206 | //these are default TREK Tag/Anchor antenna delays
|
||
207 | const uint16_t rfDelaysTREK[2] = { |
||
208 | 26dead12 | Cung Sang | (uint16_t) (((double)514.83f/ 2.0) * 1e-9 / DWT_TIME_UNITS),//channel 2 |
209 | (uint16_t) (((double)514.65f/ 2.0) * 1e-9 / DWT_TIME_UNITS) //channel 5 |
||
210 | 69a601a5 | Cung Sang | }; |
211 | |||
212 | |||
213 | // -------------------------------------------------------------------------------------------------------------------
|
||
214 | // Data Definitions
|
||
215 | // -------------------------------------------------------------------------------------------------------------------
|
||
216 | |||
217 | instance_data_t instance_data[NUM_INST] ; |
||
218 | |||
219 | static double inst_tdist[MAX_TAG_LIST_SIZE] ; |
||
220 | static double inst_idist[MAX_ANCHOR_LIST_SIZE] ; |
||
221 | static double inst_idistraw[MAX_ANCHOR_LIST_SIZE] ; |
||
222 | |||
223 | instance_data_t instance_data[NUM_INST] ; |
||
224 | |||
225 | 26dead12 | Cung Sang | typedef struct __attribute__((packed)) |
226 | 69a601a5 | Cung Sang | { |
227 | uint32_t deviceID ; |
||
228 | uint8_t chan; // added chan here - used in the reading of acc
|
||
229 | uint16_t rfrxDly; // rf delay (delay though the RF blocks before the signal comes out of the antenna i.e. "antenna delay")
|
||
230 | uint16_t rftxDly; // rf delay (delay though the RF blocks before the signal comes out of the antenna i.e. "antenna delay")
|
||
231 | uint32_t antennaDly; // antenna delay read from OTP 64 PRF value is in high 16 bits and 16M PRF in low 16 bits
|
||
232 | uint32_t antennaCals[4]; // antenna delays for the TREKs (Anchor high 16-bits, Tag low 16-bits) |
||
233 | uint32_t txPowCfg[12]; // stores the Tx power configuration read from OTP (6 channels consecutively with PRF16 then 64, e.g. Ch 1 PRF16 is index 0 and 64 index 1) |
||
234 | uint32_t states[3] ; //MP workaround debug states register |
||
235 | uint8_t statescount ; |
||
236 | int prfIndex ;
|
||
237 | uint32_t ldoTune ; //low 32 bits of LDO tune value
|
||
238 | } platform_local_data_t ; |
||
239 | |||
240 | static platform_local_data_t platformLocalData ; // Static local device data |
||
241 | |||
242 | // -------------------------------------------------------------------------------------------------------------------
|
||
243 | // Functions
|
||
244 | // -------------------------------------------------------------------------------------------------------------------
|
||
245 | |||
246 | // -------------------------------------------------------------------------------------------------------------------
|
||
247 | // convert microseconds to device time
|
||
248 | uint64_t convertmicrosectodevicetimeu (double microsecu){
|
||
249 | uint64_t dt; |
||
250 | long double dtime; |
||
251 | |||
252 | 26dead12 | Cung Sang | dtime = (long double)((microsecu / (double) DWT_TIME_UNITS) / 1e6); |
253 | 69a601a5 | Cung Sang | |
254 | dt = (uint64_t) (dtime) ; |
||
255 | |||
256 | return dt;
|
||
257 | } |
||
258 | |||
259 | double convertdevicetimetosec(int32_t dt){
|
||
260 | double f = 0; |
||
261 | |||
262 | f = dt * DWT_TIME_UNITS ; // seconds #define TIME_UNITS (1.0/499.2e6/128.0) = 15.65e-12
|
||
263 | |||
264 | return f ;
|
||
265 | } |
||
266 | |||
267 | #pragma GCC optimize ("O3") |
||
268 | int reportTOF(int idx, uint32_t tofx){ |
||
269 | double distance ;
|
||
270 | double distance_to_correct;
|
||
271 | double tof ;
|
||
272 | 26dead12 | Cung Sang | int64_t tofi ; |
273 | 69a601a5 | Cung Sang | |
274 | // check for negative results and accept them making them proper negative integers
|
||
275 | tofi = (int32_t) tofx ; // make it signed
|
||
276 | if (tofi > 0x7FFFFFFF){ // close up TOF may be negative |
||
277 | tofi -= 0x80000000 ; // |
||
278 | } |
||
279 | |||
280 | // convert to seconds (as floating point)
|
||
281 | 26dead12 | Cung Sang | tof = convertdevicetimetosec((int32_t)tofi) ; //this is divided by 4 to get single time of flight
|
282 | 69a601a5 | Cung Sang | inst_idistraw[idx] = distance = tof * SPEED_OF_LIGHT; |
283 | |||
284 | #if (CORRECT_RANGE_BIAS == 1) |
||
285 | //for the 6.81Mb data rate we assume gating gain of 6dB is used,
|
||
286 | //thus a different range bias needs to be applied
|
||
287 | //if(inst->configData.dataRate == DWT_BR_6M8)
|
||
288 | if(instance_data[0].configData.smartPowerEn){ |
||
289 | //1.31 for channel 2 and 1.51 for channel 5
|
||
290 | if(instance_data[0].configData.chan == 5){ |
||
291 | distance_to_correct = distance/1.51; |
||
292 | } |
||
293 | else{ //channel 2 |
||
294 | distance_to_correct = distance/1.31; |
||
295 | } |
||
296 | } |
||
297 | else{
|
||
298 | distance_to_correct = distance; |
||
299 | } |
||
300 | |||
301 | distance = distance - dwt_getrangebias(instance_data[0].configData.chan, (float) distance_to_correct, instance_data[0].configData.prf); |
||
302 | #endif
|
||
303 | |||
304 | if ((distance < 0) || (distance > 20000.000)) // discard any results less than <0 cm or >20 km |
||
305 | return 0; |
||
306 | |||
307 | inst_idist[idx] = distance; |
||
308 | |||
309 | instance_data[0].longTermRangeCount++ ; // for computing a long term average |
||
310 | |||
311 | return 1; |
||
312 | }// end of reportTOF
|
||
313 | |||
314 | void setTagDist(int tidx, int aidx){ |
||
315 | inst_tdist[tidx] = inst_idist[aidx]; |
||
316 | } |
||
317 | |||
318 | double getTagDist(int idx){ |
||
319 | return inst_tdist[idx];
|
||
320 | } |
||
321 | |||
322 | void clearDistTable(int idx){ |
||
323 | inst_idistraw[idx] = 0;
|
||
324 | inst_idist[idx] = 0;
|
||
325 | } |
||
326 | |||
327 | void instancecleardisttableall(void){ |
||
328 | int i;
|
||
329 | |||
330 | for(i=0; i<MAX_ANCHOR_LIST_SIZE; i++) { |
||
331 | inst_idistraw[i] = 0xffff;
|
||
332 | inst_idist[i] = 0xffff;
|
||
333 | } |
||
334 | } |
||
335 | |||
336 | // -------------------------------------------------------------------------------------------------------------------
|
||
337 | #if NUM_INST != 1 |
||
338 | #error These functions assume one instance only
|
||
339 | #else
|
||
340 | |||
341 | |||
342 | // -------------------------------------------------------------------------------------------------------------------
|
||
343 | // Set this instance role as the Tag, Anchor or Listener
|
||
344 | void instancesetrole(int inst_mode){ |
||
345 | // assume instance 0, for this
|
||
346 | 26dead12 | Cung Sang | instance_data[0].mode = (INST_MODE)inst_mode; // set the role |
347 | 69a601a5 | Cung Sang | } |
348 | |||
349 | int instancegetrole(void){ |
||
350 | 26dead12 | Cung Sang | return (int)instance_data[0].mode; |
351 | 69a601a5 | Cung Sang | } |
352 | |||
353 | int instancenewrange(void){ |
||
354 | int x = instance_data[0].newRange; |
||
355 | instance_data[0].newRange = TOF_REPORT_NUL;
|
||
356 | return x;
|
||
357 | } |
||
358 | |||
359 | int instancenewrangeancadd(void){ |
||
360 | return instance_data[0].newRangeAncAddress; |
||
361 | } |
||
362 | |||
363 | int instancenewrangetagadd(void){ |
||
364 | return instance_data[0].newRangeTagAddress; |
||
365 | } |
||
366 | |||
367 | 26dead12 | Cung Sang | uint32_t instancenewrangetim(void){
|
368 | 69a601a5 | Cung Sang | return instance_data[0].newRangeTime; |
369 | } |
||
370 | |||
371 | // -------------------------------------------------------------------------------------------------------------------
|
||
372 | // function to clear counts/averages/range values
|
||
373 | //
|
||
374 | void instanceclearcounts(void){ |
||
375 | int instance = 0 ; |
||
376 | int i= 0 ; |
||
377 | |||
378 | instance_data[instance].rxTimeouts = 0 ;
|
||
379 | |||
380 | dwt_configeventcounters(1); //enable and clear - NOTE: the counters are not preserved when in DEEP SLEEP |
||
381 | |||
382 | instance_data[instance].frameSN = 0;
|
||
383 | |||
384 | instance_data[instance].longTermRangeCount = 0;
|
||
385 | |||
386 | |||
387 | for(i=0; i<MAX_ANCHOR_LIST_SIZE; i++){ |
||
388 | instance_data[instance].tofArray[i] = INVALID_TOF; |
||
389 | } |
||
390 | |||
391 | for(i=0; i<MAX_TAG_LIST_SIZE; i++){ |
||
392 | instance_data[instance].tof[i] = INVALID_TOF; |
||
393 | } |
||
394 | |||
395 | } // end instanceclearcounts()
|
||
396 | |||
397 | |||
398 | // -------------------------------------------------------------------------------------------------------------------
|
||
399 | // function to initialise instance structures
|
||
400 | //
|
||
401 | // Returns 0 on success and -1 on error
|
||
402 | 33f54213 | Cung Sang | int instance_init(DW1000Driver* drv){
|
403 | 69a601a5 | Cung Sang | int instance = 0 ; |
404 | int i;
|
||
405 | int result;
|
||
406 | |||
407 | instance_data[instance].mode = ANCHOR; // assume listener,
|
||
408 | instance_data[instance].testAppState = TA_INIT ; |
||
409 | instance_data[instance].instToSleep = FALSE; |
||
410 | |||
411 | |||
412 | // Reset the IC (might be needed if not getting here from POWER ON)
|
||
413 | // ARM code: Remove soft reset here as using hard reset in the inittestapplication() in the main.c file
|
||
414 | //dwt_softreset();
|
||
415 | |||
416 | //this initialises DW1000 and uses specified configurations from OTP/ROM
|
||
417 | 26dead12 | Cung Sang | result = dwt_initialise(DWT_LOADUCODE, drv); |
418 | 69a601a5 | Cung Sang | |
419 | //this is platform dependent - only program if DW EVK/EVB
|
||
420 | dwt_setleds(3) ; //configure the GPIOs which control the leds on EVBs |
||
421 | |||
422 | if (DWT_SUCCESS != result){
|
||
423 | return (-1) ; // device initialise has failed |
||
424 | } |
||
425 | |||
426 | |||
427 | instanceclearcounts() ; |
||
428 | |||
429 | instance_data[instance].panID = 0xdeca ;
|
||
430 | |||
431 | instance_data[instance].wait4ack = 0;
|
||
432 | instance_data[instance].stopTimer = 0;
|
||
433 | instance_data[instance].instanceTimerEn = 0;
|
||
434 | |||
435 | instance_clearevents(); |
||
436 | |||
437 | //dwt_geteui(instance_data[instance].eui64);
|
||
438 | memset(instance_data[instance].eui64, 0, ADDR_BYTE_SIZE_L);
|
||
439 | |||
440 | instance_data[instance].tagSleepCorrection = 0;
|
||
441 | |||
442 | // dwt_setautorxreenable(0); //disable auto RX re-enable
|
||
443 | dwt_setdblrxbuffmode(0); //disable double RX buffer |
||
444 | |||
445 | // if using auto CRC check (DWT_INT_RFCG and DWT_INT_RFCE) are used instead of DWT_INT_RDFR flag
|
||
446 | // other errors which need to be checked (as they disable receiver) are
|
||
447 | //dwt_setinterrupt(DWT_INT_TFRS | DWT_INT_RFCG | (DWT_INT_SFDT | DWT_INT_RFTO /*| DWT_INT_RXPTO*/), 1);
|
||
448 | dwt_setinterrupt(DWT_INT_TFRS | DWT_INT_RFCG | (DWT_INT_ARFE | DWT_INT_RFSL | DWT_INT_SFDT | DWT_INT_RPHE | DWT_INT_RFCE | DWT_INT_RFTO | DWT_INT_RXPTO), 1);
|
||
449 | |||
450 | dwt_setcallbacks(instance_txcallback, instance_rxcallback, instance_rxtimeoutcallback,instance_rxerrorcallback ); |
||
451 | |||
452 | instance_data[instance].monitor = 0;
|
||
453 | |||
454 | instance_data[instance].lateTX = 0;
|
||
455 | instance_data[instance].lateRX = 0;
|
||
456 | |||
457 | instance_data[instance].responseTO = -1; //initialise |
||
458 | for(i=0; i<256; i++) { |
||
459 | instance_data[instance].rxResps[i] = -10;
|
||
460 | } |
||
461 | |||
462 | instance_data[instance].delayedReplyTime = 0;
|
||
463 | |||
464 | return 0 ; |
||
465 | } |
||
466 | |||
467 | // -------------------------------------------------------------------------------------------------------------------
|
||
468 | //
|
||
469 | // Return the Device ID register value, enables higher level validation of physical device presence
|
||
470 | //
|
||
471 | |||
472 | uint32_t instancereaddeviceid(void){
|
||
473 | return dwt_readdevid() ;
|
||
474 | } |
||
475 | |||
476 | |||
477 | // -------------------------------------------------------------------------------------------------------------------
|
||
478 | //
|
||
479 | // function to allow application configuration be passed into instance and affect underlying device operation
|
||
480 | //
|
||
481 | 4172c48d | Cung Sang | void instance_config(instanceConfig_t *config, sfConfig_t *sfConfig, DW1000Driver* drv){
|
482 | 69a601a5 | Cung Sang | int instance = 0 ; |
483 | uint32_t power = 0;
|
||
484 | uint8_t otprev ; |
||
485 | |||
486 | instance_data[instance].configData.chan = config->channelNumber ; |
||
487 | instance_data[instance].configData.rxCode = config->preambleCode ; |
||
488 | instance_data[instance].configData.txCode = config->preambleCode ; |
||
489 | instance_data[instance].configData.prf = config->pulseRepFreq ; |
||
490 | instance_data[instance].configData.dataRate = config->dataRate ; |
||
491 | instance_data[instance].configData.txPreambLength = config->preambleLen ; |
||
492 | instance_data[instance].configData.rxPAC = config->pacSize ; |
||
493 | instance_data[instance].configData.nsSFD = config->nsSFD ; |
||
494 | instance_data[instance].configData.phrMode = DWT_PHRMODE_STD ; |
||
495 | instance_data[instance].configData.sfdTO = config->sfdTO; |
||
496 | |||
497 | //the DW1000 will automatically use gating gain for frames < 1ms duration (i.e. 6.81Mbps data rate)
|
||
498 | //smartPowerEn should be set based on the frame length, but we can also use dtaa rate.
|
||
499 | if(instance_data[instance].configData.dataRate == DWT_BR_6M8) {
|
||
500 | instance_data[instance].configData.smartPowerEn = 1;
|
||
501 | } |
||
502 | else{
|
||
503 | instance_data[instance].configData.smartPowerEn = 0;
|
||
504 | } |
||
505 | |||
506 | //configure the channel parameters
|
||
507 | dwt_configure(&instance_data[instance].configData) ; |
||
508 | |||
509 | instance_data[instance].configTX.PGdly = txSpectrumConfig[config->channelNumber].PGdelay ; //Default
|
||
510 | |||
511 | //firstly check if there are calibrated TX power value in the DW1000 OTP
|
||
512 | power = dwt_getotptxpower(config->pulseRepFreq, instance_data[instance].configData.chan); |
||
513 | |||
514 | if((power == 0x0) || (power == 0xFFFFFFFF)) { //if there are no calibrated values... need to use defaults |
||
515 | power = txSpectrumConfig[config->channelNumber].txPwr[config->pulseRepFreq- DWT_PRF_16M]; |
||
516 | } |
||
517 | |||
518 | //Configure TX power
|
||
519 | instance_data[instance].configTX.power = power; |
||
520 | |||
521 | //configure the tx spectrum parameters (power and PG delay)
|
||
522 | dwt_configuretxrf(&instance_data[instance].configTX); |
||
523 | |||
524 | otprev = dwt_otprevision() ; // this revision tells us how OTP is programmed.
|
||
525 | |||
526 | if ((2 == otprev) || (3 == otprev)) { // board is calibrated with TREK1000 with antenna delays set for each use case) |
||
527 | uint8_t mode = (instance_data[instance].mode == ANCHOR ? 1 : 0); |
||
528 | uint8_t chanindex = 0;
|
||
529 | |||
530 | instance_data[instance].txAntennaDelay |
||
531 | = dwt_getTREKOTPantennadelay(mode, |
||
532 | instance_data[instance].configData.chan, |
||
533 | instance_data[instance].configData.dataRate) ; |
||
534 | |||
535 | // if nothing was actually programmed then set a reasonable value anyway
|
||
536 | if ((instance_data[instance].txAntennaDelay == 0) |
||
537 | || (instance_data[instance].txAntennaDelay == 0xffff)){
|
||
538 | if(instance_data[instance].configData.chan == 5){ |
||
539 | chanindex = 1;
|
||
540 | } |
||
541 | |||
542 | instance_data[instance].txAntennaDelay = rfDelaysTREK[chanindex]; |
||
543 | } |
||
544 | |||
545 | } |
||
546 | else { // assume it is older EVK1000 programming. |
||
547 | //get the antenna delay that was read from the OTP calibration area
|
||
548 | instance_data[instance].txAntennaDelay = dwt_readantennadelay(config->pulseRepFreq) >> 1;
|
||
549 | |||
550 | // if nothing was actually programmed then set a reasonable value anyway
|
||
551 | if ((instance_data[instance].txAntennaDelay == 0) |
||
552 | || (instance_data[instance].txAntennaDelay == 0xffff)){
|
||
553 | instance_data[instance].txAntennaDelay = rfDelays[config->pulseRepFreq - DWT_PRF_16M]; |
||
554 | } |
||
555 | } |
||
556 | |||
557 | // -------------------------------------------------------------------------------------------------------------------
|
||
558 | // set the antenna delay, we assume that the RX is the same as TX.
|
||
559 | dwt_setrxantennadelay(instance_data[instance].txAntennaDelay); |
||
560 | dwt_settxantennadelay(instance_data[instance].txAntennaDelay); |
||
561 | |||
562 | instance_data[instance].rxAntennaDelay = instance_data[instance].txAntennaDelay; |
||
563 | |||
564 | if(config->preambleLen == DWT_PLEN_64) { //if preamble length is 64 |
||
565 | //reduce SPI to < 3MHz
|
||
566 | 4172c48d | Cung Sang | setHighSpeed_SPI(FALSE, drv); |
567 | 69a601a5 | Cung Sang | dwt_loadopsettabfromotp(0);
|
568 | //increase SPI to max
|
||
569 | 4172c48d | Cung Sang | setHighSpeed_SPI(TRUE, drv); |
570 | 69a601a5 | Cung Sang | } |
571 | |||
572 | instancesettagsleepdelay(sfConfig->pollSleepDly); //set the Tag sleep time
|
||
573 | instance_data[instance].sframePeriod = sfConfig->sfPeriod; |
||
574 | instance_data[instance].slotPeriod = sfConfig->slotPeriod; |
||
575 | instance_data[instance].tagSleepRnd = sfConfig->slotPeriod; |
||
576 | instance_data[instance].numSlots = sfConfig->numSlots; |
||
577 | |||
578 | //last two slots are used for anchor to anchor ranging
|
||
579 | instance_data[instance].a0SlotTime = (instance_data[instance].numSlots-2) * instance_data[instance].slotPeriod;
|
||
580 | |||
581 | //set the default response delays
|
||
582 | instancesetreplydelay(sfConfig->replyDly); |
||
583 | |||
584 | } |
||
585 | |||
586 | // -------------------------------------------------------------------------------------------------------------------
|
||
587 | // function to set the tag sleep time (in ms)
|
||
588 | //
|
||
589 | void instancesettagsleepdelay(int sleepdelay) { //sleep in ms |
||
590 | int instance = 0 ; |
||
591 | instance_data[instance].tagSleepTime_ms = sleepdelay; //subtract the micro system delays (time it takes to switch states etc.)
|
||
592 | } |
||
593 | |||
594 | |||
595 | int instancegetrnum(void) { //get ranging number |
||
596 | return instance_data[0].rangeNum; |
||
597 | } |
||
598 | |||
599 | int instancegetrnuma(int idx){ //get ranging number |
||
600 | return instance_data[0].rangeNumA[idx]; |
||
601 | } |
||
602 | |||
603 | int instancegetrnumanc(int idx){ //get ranging number |
||
604 | return instance_data[0].rangeNumAAnc[idx]; |
||
605 | } |
||
606 | |||
607 | int instancegetlcount(void) { //get count of ranges used for calculation of lt avg |
||
608 | int x = instance_data[0].longTermRangeCount; |
||
609 | |||
610 | return (x);
|
||
611 | } |
||
612 | |||
613 | double instancegetidist(int idx) { //get instantaneous range |
||
614 | double x ;
|
||
615 | |||
616 | idx &= (MAX_ANCHOR_LIST_SIZE - 1);
|
||
617 | |||
618 | x = inst_idist[idx]; |
||
619 | |||
620 | return (x);
|
||
621 | } |
||
622 | |||
623 | double instancegetidistraw(int idx) { //get instantaneous range (uncorrected) |
||
624 | double x ;
|
||
625 | |||
626 | idx &= (MAX_ANCHOR_LIST_SIZE - 1);
|
||
627 | |||
628 | x = inst_idistraw[idx]; |
||
629 | |||
630 | return (x);
|
||
631 | } |
||
632 | |||
633 | int instancegetidist_mm(int idx) { //get instantaneous range |
||
634 | int x ;
|
||
635 | |||
636 | idx &= (MAX_ANCHOR_LIST_SIZE - 1);
|
||
637 | |||
638 | x = (int)(inst_idist[idx]*1000); |
||
639 | |||
640 | return (x);
|
||
641 | } |
||
642 | |||
643 | int instancegetidistraw_mm(int idx) { //get instantaneous range (uncorrected) |
||
644 | int x ;
|
||
645 | |||
646 | idx &= (MAX_ANCHOR_LIST_SIZE - 1);
|
||
647 | |||
648 | x = (int)(inst_idistraw[idx]*1000); |
||
649 | |||
650 | return (x);
|
||
651 | } |
||
652 | |||
653 | void instance_backtoanchor(instance_data_t *inst){
|
||
654 | //stay in RX and behave as anchor
|
||
655 | inst->testAppState = TA_RXE_WAIT ; |
||
656 | inst->mode = ANCHOR ; |
||
657 | dwt_setrxtimeout(0);
|
||
658 | dwt_setpreambledetecttimeout(0);
|
||
659 | dwt_setrxaftertxdelay(0);
|
||
660 | } |
||
661 | |||
662 | |||
663 | #pragma GCC optimize ("O3") |
||
664 | void inst_processrxtimeout(instance_data_t *inst){
|
||
665 | |||
666 | //inst->responseTimeouts ++ ;
|
||
667 | inst->rxTimeouts ++ ; |
||
668 | inst->done = INST_NOT_DONE_YET; |
||
669 | |||
670 | if(inst->mode == ANCHOR) { //we did not receive the final - wait for next poll |
||
671 | //only enable receiver when not using double buffering
|
||
672 | inst->testAppState = TA_RXE_WAIT ; // wait for next frame
|
||
673 | dwt_setrxtimeout(0);
|
||
674 | } |
||
675 | |||
676 | else if(inst->mode == TAG) { |
||
677 | //if tag times out - no response (check if we are to send a final)
|
||
678 | //send the final only if it has received response from anchor 0
|
||
679 | if((inst->previousState == TA_TXPOLL_WAIT_SEND) && ((inst->rxResponseMask & 0x1) == 0)) { |
||
680 | inst->instToSleep = TRUE ; //set sleep to TRUE so that tag will go to DEEP SLEEP before next ranging attempt
|
||
681 | inst->testAppState = TA_TXE_WAIT ; |
||
682 | inst->nextState = TA_TXPOLL_WAIT_SEND ; |
||
683 | } |
||
684 | else if (inst->previousState == TA_TXFINAL_WAIT_SEND) { //got here from main (error sending final - handle as timeout) |
||
685 | dwt_forcetrxoff(); //this will clear all events
|
||
686 | inst->instToSleep = TRUE ; |
||
687 | // initiate the re-transmission of the poll that was not responded to
|
||
688 | inst->testAppState = TA_TXE_WAIT ; |
||
689 | inst->nextState = TA_TXPOLL_WAIT_SEND ; |
||
690 | } |
||
691 | else { //send the final |
||
692 | // initiate the re-transmission of the poll that was not responded to
|
||
693 | inst->testAppState = TA_TXE_WAIT ; |
||
694 | inst->nextState = TA_TXFINAL_WAIT_SEND ; |
||
695 | } |
||
696 | |||
697 | } |
||
698 | else { //ANCHOR_RNG |
||
699 | //no Response form the other anchor
|
||
700 | if(
|
||
701 | ((inst->previousState == TA_TXPOLL_WAIT_SEND) |
||
702 | && ((A1_ANCHOR_ADDR == inst->instanceAddress16) && ((inst->rxResponseMaskAnc & 0x4) == 0))) |
||
703 | || |
||
704 | ((inst->previousState == TA_TXPOLL_WAIT_SEND) |
||
705 | && ((GATEWAY_ANCHOR_ADDR == inst->instanceAddress16) && ((inst->rxResponseMaskAnc & 0x2) == 0))) |
||
706 | ) { |
||
707 | instance_backtoanchor(inst); |
||
708 | } |
||
709 | else if (inst->previousState == TA_TXFINAL_WAIT_SEND) { //got here from main (error ending final - handle as timeout) |
||
710 | instance_backtoanchor(inst); |
||
711 | } |
||
712 | else { //send the final |
||
713 | // initiate the re-transmission of the poll that was not responded to
|
||
714 | inst->testAppState = TA_TXE_WAIT ; |
||
715 | inst->nextState = TA_TXFINAL_WAIT_SEND ; |
||
716 | } |
||
717 | } |
||
718 | |||
719 | //timeout - disable the radio (if using SW timeout the rx will not be off)
|
||
720 | //dwt_forcetrxoff() ;
|
||
721 | } |
||
722 | |||
723 | //
|
||
724 | // NB: This function is called from the (TX) interrupt handler
|
||
725 | //
|
||
726 | #pragma GCC optimize ("O3") |
||
727 | void instance_txcallback(const dwt_cb_data_t *txd){ |
||
728 | |||
729 | (void) txd;
|
||
730 | int instance = 0; |
||
731 | uint8_t txTimeStamp[5] = {0, 0, 0, 0, 0}; |
||
732 | // uint8 txevent = txd->event;
|
||
733 | event_data_t dw_event; |
||
734 | |||
735 | dw_event.uTimeStamp = portGetTickCnt(); |
||
736 | |||
737 | 26dead12 | Cung Sang | dwt_readtxtimestamp(txTimeStamp) ; |
738 | dw_event.timeStamp32l = (uint32_t)txTimeStamp[0] + ((uint32_t)txTimeStamp[1] << 8) + ((uint32_t)txTimeStamp[2] << 16) + ((uint32_t)txTimeStamp[3] << 24); |
||
739 | dw_event.timeStamp = txTimeStamp[4];
|
||
740 | dw_event.timeStamp <<= 32;
|
||
741 | dw_event.timeStamp += dw_event.timeStamp32l; |
||
742 | dw_event.timeStamp32h = ((uint32_t)txTimeStamp[4] << 24) + (dw_event.timeStamp32l >> 8); |
||
743 | 69a601a5 | Cung Sang | |
744 | 26dead12 | Cung Sang | instance_data[instance].stopTimer = 0;
|
745 | 69a601a5 | Cung Sang | |
746 | 26dead12 | Cung Sang | dw_event.rxLength = instance_data[instance].psduLength; |
747 | dw_event.type = 0;
|
||
748 | dw_event.type_pend = 0;
|
||
749 | dw_event.type_save = DWT_SIG_TX_DONE; |
||
750 | 69a601a5 | Cung Sang | |
751 | 26dead12 | Cung Sang | memcpy((uint8_t *)&dw_event.msgu.frame[0], (uint8_t *)&instance_data[instance].msg_f, instance_data[instance].psduLength);
|
752 | 69a601a5 | Cung Sang | |
753 | 26dead12 | Cung Sang | instance_putevent(dw_event, DWT_SIG_TX_DONE); |
754 | 69a601a5 | Cung Sang | |
755 | 26dead12 | Cung Sang | instance_data[instance].txMsgCount++; |
756 | 69a601a5 | Cung Sang | |
757 | instance_data[instance].monitor = 0;
|
||
758 | } |
||
759 | |||
760 | /**
|
||
761 | * @brief function to re-enable the receiver and also adjust the timeout before sending the final message
|
||
762 | * if it is time so send the final message, the callback will notify the application, else the receiver is
|
||
763 | * automatically re-enabled
|
||
764 | *
|
||
765 | * this function is only used for tag when ranging to other anchors
|
||
766 | */
|
||
767 | uint8_t tagrxreenable(uint16_t sourceAddress){ |
||
768 | uint8_t type_pend = DWT_SIG_DW_IDLE; |
||
769 | uint8_t anc = sourceAddress & 0x3;
|
||
770 | int instance = 0; |
||
771 | |||
772 | switch(anc){
|
||
773 | //if we got Response from anchor 3 - this is the last expected response - send the final
|
||
774 | case 3: |
||
775 | type_pend = DWT_SIG_DW_IDLE; |
||
776 | break;
|
||
777 | |||
778 | //if we got Response from anchor 0, 1, or 2 - go back to wait for next anchor's response
|
||
779 | case 0: |
||
780 | case 1: |
||
781 | case 2: |
||
782 | default:
|
||
783 | if(instance_data[instance].responseTO > 0) { //can get here as result of error frame so need to check |
||
784 | 26dead12 | Cung Sang | dwt_setrxtimeout((uint16_t)(instance_data[instance].fwtoTime_sy * instance_data[instance].responseTO)); //reconfigure the timeout
|
785 | 69a601a5 | Cung Sang | dwt_rxenable(DWT_START_RX_IMMEDIATE) ; |
786 | type_pend = DWT_SIG_RX_PENDING ; |
||
787 | } |
||
788 | else //last response was not received (got error/frame was corrupt) |
||
789 | { |
||
790 | type_pend = DWT_SIG_DW_IDLE; //report timeout - send the final
|
||
791 | } |
||
792 | break;
|
||
793 | } |
||
794 | |||
795 | return type_pend;
|
||
796 | } |
||
797 | |||
798 | /**
|
||
799 | * @brief function to re-enable the receiver and also adjust the timeout before sending the final message
|
||
800 | * if it is time so send the final message, the callback will notify the application, else the receiver is
|
||
801 | * automatically re-enabled
|
||
802 | *
|
||
803 | * this function is only used for anchors (having a role of ANCHOR_RNG) when ranging to other anchors
|
||
804 | */
|
||
805 | uint8_t ancsendfinalorrxreenable(uint16_t sourceAddress){ |
||
806 | uint8_t type_pend = DWT_SIG_DW_IDLE; |
||
807 | uint8_t anc = sourceAddress & 0x3;
|
||
808 | int instance = 0; |
||
809 | |||
810 | if(instance_data[instance].instanceAddress16 == GATEWAY_ANCHOR_ADDR) {
|
||
811 | switch(anc) {
|
||
812 | //if we got Response from anchor 1 - go back to wait for next anchor's response
|
||
813 | case 1: |
||
814 | dwt_setrxtimeout((uint16_t)instance_data[instance].fwtoTime_sy); //reconfigure the timeout
|
||
815 | dwt_rxenable(DWT_START_RX_IMMEDIATE) ; |
||
816 | type_pend = DWT_SIG_RX_PENDING ; |
||
817 | break;
|
||
818 | |||
819 | //if we got Response from anchor 2 - this is the last expected response - send the final
|
||
820 | case 2: |
||
821 | default:
|
||
822 | type_pend = DWT_SIG_DW_IDLE; |
||
823 | break;
|
||
824 | } |
||
825 | } |
||
826 | |||
827 | if(instance_data[instance].instanceAddress16 == A1_ANCHOR_ADDR){
|
||
828 | switch(anc)
|
||
829 | { |
||
830 | //if we got Response from anchor 2 - this is the last expected response - send the final
|
||
831 | case 2: |
||
832 | default:
|
||
833 | type_pend = DWT_SIG_DW_IDLE; |
||
834 | break;
|
||
835 | } |
||
836 | } |
||
837 | return type_pend;
|
||
838 | } |
||
839 | |||
840 | /**
|
||
841 | * @brief this function either enables the receiver (delayed)
|
||
842 | *
|
||
843 | **/
|
||
844 | void ancenablerx(void){ |
||
845 | int instance = 0; |
||
846 | //subtract preamble length
|
||
847 | dwt_setdelayedtrxtime(instance_data[instance].delayedReplyTime - instance_data[instance].fixedReplyDelayAncP) ; |
||
848 | if(dwt_rxenable(DWT_START_RX_DELAYED)) { //delayed rx |
||
849 | //if the delayed RX failed - time has passed - do immediate enable
|
||
850 | //led_on(LED_PC9);
|
||
851 | dwt_setrxtimeout((uint16_t)instance_data[instance].fwtoTimeAnc_sy*2); //reconfigure the timeout before enable |
||
852 | //longer timeout as we cannot do delayed receive... so receiver needs to stay on for longer
|
||
853 | dwt_rxenable(DWT_START_RX_IMMEDIATE); |
||
854 | dwt_setrxtimeout((uint16_t)instance_data[instance].fwtoTimeAnc_sy); //restore the timeout for next RX enable
|
||
855 | instance_data[instance].lateRX++; |
||
856 | //led_off(LED_PC9);
|
||
857 | } |
||
858 | |||
859 | } |
||
860 | |||
861 | /**
|
||
862 | * @brief this function either re-enables the receiver (delayed or immediate) or transmits the response frame
|
||
863 | *
|
||
864 | * @param the sourceAddress is the address of the sender of the current received frame
|
||
865 | * @param ancToAncTWR == 1 means that the anchor is ranging to another anchor, if == 0 then ranging to a tag
|
||
866 | *
|
||
867 | */
|
||
868 | #pragma GCC optimize ("O0") |
||
869 | uint8_t anctxorrxreenable(uint16_t sourceAddress, int ancToAncTWR){
|
||
870 | uint8_t type_pend = DWT_SIG_DW_IDLE; |
||
871 | int sendResp = 0; |
||
872 | int instance = 0; |
||
873 | |||
874 | if(instance_data[instance].responseTO == 0) { //go back to RX without TO - ranging has finished. (wait for Final but no TO) |
||
875 | dwt_setrxtimeout(0); //reconfigure the timeout |
||
876 | dwt_setpreambledetecttimeout(0);
|
||
877 | } |
||
878 | |||
879 | if((ancToAncTWR & 1) == 1) { |
||
880 | if(instance_data[instance].responseTO == 1) { //if one response left to receive (send a response now) |
||
881 | sendResp = 1;
|
||
882 | } |
||
883 | //if A0 or A3 go back to RX as they do not send any responses when Anchor to Anchor ranging
|
||
884 | if((instance_data[instance].gatewayAnchor)
|
||
885 | || (instance_data[instance].shortAdd_idx == 3)) { //if this is anchor ID 3 do not reply to anchor poll |
||
886 | dwt_setrxtimeout(0);
|
||
887 | dwt_rxenable(DWT_START_RX_IMMEDIATE); |
||
888 | return DWT_SIG_RX_PENDING ;
|
||
889 | } |
||
890 | } |
||
891 | |||
892 | //configure delayed reply time (this is incremented for each received frame) it is timed from Poll rx time
|
||
893 | instance_data[instance].delayedReplyTime += (instance_data[instance].fixedReplyDelayAnc >> 8);
|
||
894 | |||
895 | //this checks if to send a frame
|
||
896 | if((((ancToAncTWR & 1) == 0) && ((instance_data[instance].responseTO + instance_data[instance].shortAdd_idx) == NUM_EXPECTED_RESPONSES)) //it's our turn to tx |
||
897 | || (sendResp == 1)) {
|
||
898 | //led_on(LED_PC9);
|
||
899 | //response is expected
|
||
900 | instance_data[instance].wait4ack = DWT_RESPONSE_EXPECTED; //re has/will be re-enabled
|
||
901 | |||
902 | dwt_setdelayedtrxtime(instance_data[instance].delayedReplyTime) ; |
||
903 | if(dwt_starttx(DWT_START_TX_DELAYED | DWT_RESPONSE_EXPECTED)) {
|
||
904 | //if TX has failed - we need to re-enable RX for the next response or final reception...
|
||
905 | dwt_setrxaftertxdelay(0);
|
||
906 | instance_data[instance].wait4ack = 0; //clear the flag as the TX has failed the TRX is off |
||
907 | instance_data[instance].lateTX++; |
||
908 | instance_data[instance].delayedReplyTime += 2*(instance_data[instance].fixedReplyDelayAnc >> 8); //to take into account W4R |
||
909 | ancenablerx(); |
||
910 | type_pend = DWT_SIG_RX_PENDING ; |
||
911 | } |
||
912 | else {
|
||
913 | instance_data[instance].delayedReplyTime += (instance_data[instance].fixedReplyDelayAnc >> 8); //to take into account W4R |
||
914 | type_pend = DWT_SIG_TX_PENDING ; // exit this interrupt and notify the application/instance that TX is in progress.
|
||
915 | instance_data[instance].timeofTx = portGetTickCnt(); |
||
916 | instance_data[instance].monitor = 1;
|
||
917 | } |
||
918 | //led_off(LED_PC9);
|
||
919 | } |
||
920 | else { //stay in receive |
||
921 | if(sourceAddress == 0) { //we got here after RX error, as we don't need to TX, we just enable RX |
||
922 | dwt_setrxtimeout(0);
|
||
923 | dwt_rxenable(DWT_START_RX_IMMEDIATE); |
||
924 | } |
||
925 | else{
|
||
926 | //led_on(LED_PC9);
|
||
927 | ancenablerx(); |
||
928 | //led_off(LED_PC9);
|
||
929 | } |
||
930 | |||
931 | type_pend = DWT_SIG_RX_PENDING ; |
||
932 | } |
||
933 | //if time to send a response
|
||
934 | |||
935 | return type_pend;
|
||
936 | } |
||
937 | |||
938 | /**
|
||
939 | * @brief this function handles frame error event, it will either signal TO or re-enable the receiver
|
||
940 | */
|
||
941 | void handle_error_unknownframe(event_data_t dw_event){
|
||
942 | int instance = 0; |
||
943 | //re-enable the receiver (after error frames as we are not using auto re-enable
|
||
944 | //for ranging application rx error frame is same as TO - as we are not going to get the expected frame
|
||
945 | if(instance_data[instance].mode == ANCHOR){
|
||
946 | //if we are participating in the ranging (i.e. Poll was received)
|
||
947 | //and we get an rx error (in one of the responses)
|
||
948 | //need to consider this as a timeout as we could be sending our response next and
|
||
949 | //the applications needs to know to change the state
|
||
950 | //
|
||
951 | if(instance_data[instance].responseTO > 0){ |
||
952 | instance_data[instance].responseTO--; |
||
953 | |||
954 | //send a response or re-enable rx
|
||
955 | dw_event.type_pend = anctxorrxreenable(0, 0); |
||
956 | dw_event.type = 0;
|
||
957 | dw_event.type_save = 0x40 | DWT_SIG_RX_TIMEOUT;
|
||
958 | dw_event.rxLength = 0;
|
||
959 | |||
960 | instance_putevent(dw_event, DWT_SIG_RX_TIMEOUT); |
||
961 | } |
||
962 | else{
|
||
963 | dwt_setrxtimeout(0); //reconfigure the timeout |
||
964 | dwt_rxenable(DWT_START_RX_IMMEDIATE) ; |
||
965 | } |
||
966 | } |
||
967 | else if(instance_data[instance].mode == LISTENER){ |
||
968 | dwt_rxenable(DWT_START_RX_IMMEDIATE) ; |
||
969 | } |
||
970 | else{
|
||
971 | instance_data[instance].responseTO--; //got something (need to reduce timeout (for remaining responses))
|
||
972 | |||
973 | dw_event.type_pend = tagrxreenable(0); //check if receiver will be re-enabled or it's time to send the final |
||
974 | dw_event.type = 0;
|
||
975 | dw_event.type_save = 0x40 | DWT_SIG_RX_TIMEOUT;
|
||
976 | dw_event.rxLength = 0;
|
||
977 | |||
978 | instance_putevent(dw_event, DWT_SIG_RX_TIMEOUT); |
||
979 | } |
||
980 | } |
||
981 | |||
982 | |||
983 | /**
|
||
984 | * @brief this function prepares and writes the anchor to anchor response frame into the TX buffer
|
||
985 | * it is called after anchor receives a Poll from an anchor
|
||
986 | */
|
||
987 | void ancprepareresponse2(uint16_t sourceAddress, uint8_t srcAddr_index, uint8_t fcode_index, uint8_t *frame){
|
||
988 | uint16_t frameLength = 0;
|
||
989 | uint8_t tof_idx = (sourceAddress) & 0x3 ;
|
||
990 | int instance = 0; |
||
991 | |||
992 | instance_data[instance].psduLength = frameLength = ANCH_RESPONSE_MSG_LEN + FRAME_CRTL_AND_ADDRESS_S + FRAME_CRC; |
||
993 | //set the destination address (copy source as this is a reply)
|
||
994 | memcpy(&instance_data[instance].msg_f.destAddr[0], &frame[srcAddr_index], ADDR_BYTE_SIZE_S); //remember who to send the reply to (set destination address) |
||
995 | instance_data[instance].msg_f.sourceAddr[0] = instance_data[instance].eui64[0]; |
||
996 | instance_data[instance].msg_f.sourceAddr[1] = instance_data[instance].eui64[1]; |
||
997 | // Write calculated TOF into response message (get the previous ToF+range number from that anchor)
|
||
998 | memcpy(&(instance_data[instance].msg_f.messageData[TOFR]), &instance_data[instance].tofAnc[tof_idx], 4);
|
||
999 | instance_data[instance].msg_f.messageData[TOFRN] = instance_data[instance].rangeNumAAnc[tof_idx]; //get the previous range number
|
||
1000 | |||
1001 | instance_data[instance].rangeNumAAnc[tof_idx] = 0; //clear the entry |
||
1002 | instance_data[instance].rangeNumAnc = frame[POLL_RNUM + fcode_index] ; |
||
1003 | instance_data[instance].msg_f.seqNum = instance_data[instance].frameSN++; |
||
1004 | |||
1005 | //set the delayed rx on time (the final message will be sent after this delay)
|
||
1006 | 26dead12 | Cung Sang | dwt_setrxaftertxdelay((uint32_t)instance_data[instance].ancRespRxDelay); //units are 1.0256us - wait for wait4respTIM before RX on (delay RX)
|
1007 |