Statistics
| Branch: | Tag: | Revision:

amiro-lld / drivers / DW1000 / v1 / deca_instance_common.c @ 9be47646

History | View | Annotate | Download (71.11 KB)

1
/*! ----------------------------------------------------------------------------
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
#include <module.h>
16
#include <string.h>
17
#include <math.h>
18
#include <deca_instance.h>
19

    
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

    
70

    
71
/*! 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

    
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
        (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
};
205

    
206
//these are default TREK Tag/Anchor antenna delays
207
const uint16_t rfDelaysTREK[2] = {
208
        (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
};
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
typedef struct __attribute__((packed))
226
{
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
  dtime = (long double)((microsecu / (double) DWT_TIME_UNITS) / 1e6);
253

    
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
  int64_t tofi ;
273

    
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
  tof = convertdevicetimetosec((int32_t)tofi) ;          //this is divided by 4 to get single time of flight
282
  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
  instance_data[0].mode =  (INST_MODE)inst_mode;                   // set the role
347
}
348

    
349
int instancegetrole(void){
350
  return (int)instance_data[0].mode;
351
}
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
uint32_t instancenewrangetim(void){
368
  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
int instance_init(DW1000Driver* drv){
403
  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
  result = dwt_initialise(DWT_LOADUCODE, drv);
418

    
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
void instance_config(instanceConfig_t *config, sfConfig_t *sfConfig, DW1000Driver* drv){
482
  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
    setHighSpeed_SPI(FALSE, drv);
567
    dwt_loadopsettabfromotp(0);
568
    //increase SPI to max
569
    setHighSpeed_SPI(TRUE, drv);
570
  }
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
  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

    
744
  instance_data[instance].stopTimer = 0;
745

    
746
  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

    
751
  memcpy((uint8_t *)&dw_event.msgu.frame[0], (uint8_t *)&instance_data[instance].msg_f, instance_data[instance].psduLength);
752

    
753
  instance_putevent(dw_event, DWT_SIG_TX_DONE);
754

    
755
  instance_data[instance].txMsgCount++;
756

    
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
      dwt_setrxtimeout((uint16_t)(instance_data[instance].fwtoTime_sy * instance_data[instance].responseTO)); //reconfigure the timeout
785
      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
  dwt_setrxaftertxdelay((uint32_t)instance_data[instance].ancRespRxDelay);  //units are 1.0256us - wait for wait4respTIM before RX on (delay RX)
1007

    
1008
  instance_data[instance].tagSleepCorrection = 0;
1009
  instance_data[instance].msg_f.messageData[RES_TAG_SLP0] = 0 ;
1010
  instance_data[instance].msg_f.messageData[RES_TAG_SLP1] = 0 ;
1011

    
1012
  instance_data[instance].msg_f.messageData[FCODE] = RTLS_DEMO_MSG_ANCH_RESP2; //message function code (specifies if message is a poll, response or other...)
1013

    
1014
  //write the TX data
1015
  dwt_writetxfctrl(frameLength, 0, 1);
1016
  dwt_writetxdata(frameLength, (uint8_t *)  &instance_data[instance].msg_f, 0) ;        // write the frame data
1017

    
1018
}
1019

    
1020
/**
1021
 * @brief this function prepares and writes the anchor to tag response frame into the TX buffer
1022
 * it is called after anchor receives a Poll from a tag
1023
 */
1024
void ancprepareresponse(uint16_t sourceAddress, uint8_t srcAddr_index, uint8_t fcode_index, uint8_t *frame, uint32_t uTimeStamp){
1025
  uint16_t frameLength = 0;
1026
  uint8_t tof_idx = (sourceAddress) & 0x7 ;
1027
  int instance = 0;
1028

    
1029
  instance_data[instance].psduLength = frameLength = ANCH_RESPONSE_MSG_LEN + FRAME_CRTL_AND_ADDRESS_S + FRAME_CRC;
1030
  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)
1031
  instance_data[instance].msg_f.sourceAddr[0] = instance_data[instance].eui64[0];
1032
  instance_data[instance].msg_f.sourceAddr[1] = instance_data[instance].eui64[1];
1033
  // Write calculated TOF into response message (get the previous ToF+range number from that tag)
1034
  memcpy(&(instance_data[instance].msg_f.messageData[TOFR]), &instance_data[instance].tof[tof_idx], 4);
1035
  instance_data[instance].msg_f.messageData[TOFRN] = instance_data[instance].rangeNumA[tof_idx]; //get the previous range number
1036

    
1037
  instance_data[instance].rangeNumA[tof_idx] = 0; //clear after copy above...
1038
  instance_data[instance].rangeNum = frame[POLL_RNUM+fcode_index] ;
1039
  instance_data[instance].msg_f.seqNum = instance_data[instance].frameSN++;
1040

    
1041
  //we have our range - update the own mask entry...
1042
  if(instance_data[instance].tof[tof_idx] != INVALID_TOF) { //check the last ToF entry is valid and copy into the current array
1043
    instance_data[instance].rxResponseMask = (uint8_t)(0x1 << instance_data[instance].shortAdd_idx);
1044
    instance_data[instance].tofArray[instance_data[instance].shortAdd_idx] = instance_data[instance].tof[tof_idx];
1045
  }
1046
  else        {  //reset response mask
1047
    instance_data[instance].tofArray[instance_data[instance].shortAdd_idx] = INVALID_TOF ;
1048
    instance_data[instance].rxResponseMask = 0;        //reset the mask of received responses when rx poll
1049
  }
1050
  //set the delayed rx on time (the final message will be sent after this delay)
1051
  dwt_setrxaftertxdelay((uint32_t)instance_data[instance].ancRespRxDelay);  //units are 1.0256us - wait for wait4respTIM before RX on (delay RX)
1052

    
1053
  //if this is gateway anchor - calculate the slot period correction
1054
  if(instance_data[instance].gatewayAnchor)  {
1055
    int error = 0;
1056
    int currentSlotTime = 0;
1057
    int expectedSlotTime = 0;
1058
    //find the time in the current superframe
1059
    currentSlotTime = uTimeStamp % instance_data[instance].sframePeriod;
1060

    
1061
    //this is the slot time the poll should be received in (Mask 0x07 for the 8 MAX tags we support in TREK)
1062
    expectedSlotTime = (sourceAddress&0xFF) * instance_data[instance].slotPeriod; //
1063

    
1064
    //error = expectedSlotTime - currentSlotTime
1065
    error = expectedSlotTime - currentSlotTime;
1066

    
1067
    if(error < (-(instance_data[instance].sframePeriod>>1))) { //if error is more negative than 0.5 period, add whole period to give up to 1.5 period sleep
1068
      instance_data[instance].tagSleepCorrection = (instance_data[instance].sframePeriod + error);
1069
    }
1070
    else { //the minimum Sleep time will be 0.5 period
1071
      instance_data[instance].tagSleepCorrection = error;
1072
    }
1073
    instance_data[instance].msg_f.messageData[RES_TAG_SLP0] = instance_data[instance].tagSleepCorrection & 0xFF ;
1074
    instance_data[instance].msg_f.messageData[RES_TAG_SLP1] = (instance_data[instance].tagSleepCorrection >> 8) & 0xFF;
1075
  }
1076
  else {
1077
    instance_data[instance].tagSleepCorrection = 0;
1078
    instance_data[instance].msg_f.messageData[RES_TAG_SLP0] = 0 ;
1079
    instance_data[instance].msg_f.messageData[RES_TAG_SLP1] = 0 ;
1080
  }
1081
  instance_data[instance].msg_f.messageData[FCODE] = RTLS_DEMO_MSG_ANCH_RESP; //message function code (specifies if message is a poll, response or other...)
1082

    
1083
  //write the TX data
1084
  dwt_writetxfctrl(frameLength, 0, 1);
1085
  dwt_writetxdata(frameLength, (uint8_t *)  &instance_data[instance].msg_f, 0) ;        // write the frame data
1086
}
1087

    
1088
/**
1089
 * @brief this is the receive event callback handler, the received event is processed and the instance either
1090
 * responds by sending a response frame or re-enables the receiver to await the next frame
1091
 * once the immediate action is taken care of the event is queued up for application to process
1092
 */
1093
#pragma GCC optimize ("O3")
1094
void instance_rxcallback(const dwt_cb_data_t *rxd){
1095
  int instance = 0;
1096
  uint8_t rxTimeStamp[5]  = {0, 0, 0, 0, 0};
1097

    
1098
  uint8_t rxd_event = 0;
1099
  uint8_t fcode_index  = 0;
1100
  uint8_t srcAddr_index = 0;
1101
  event_data_t dw_event;
1102

    
1103
  //microcontroller time at which we received the frame
1104
  dw_event.uTimeStamp = portGetTickCnt();
1105

    
1106
  //if we got a frame with a good CRC - RX OK
1107
  //  if(rxd->event == DWT_SIG_RX_OKAY) { // Timeout and error are handle separately in the driver itself
1108
  dw_event.rxLength = rxd->datalength;
1109

    
1110
  //need to process the frame control bytes to figure out what type of frame we have received
1111
  if(((rxd->fctrl[0] == 0x41) || (rxd->fctrl[0] == 0x61))
1112
      &&
1113
      ((rxd->fctrl[1] & 0xCC) == 0x88)) {  //short address
1114
    fcode_index = FRAME_CRTL_AND_ADDRESS_S; //function code is in first byte after source address
1115
    srcAddr_index = FRAME_CTRLP + ADDR_BYTE_SIZE_S;
1116
    rxd_event = DWT_SIG_RX_OKAY;
1117
  }
1118
  else {
1119
    rxd_event = SIG_RX_UNKNOWN; //not supported - all TREK1000 frames are short addressed
1120
  }
1121

    
1122
  //read RX timestamp
1123
  dwt_readrxtimestamp(rxTimeStamp) ;
1124
  dwt_readrxdata((uint8_t *)&dw_event.msgu.frame[0], rxd->datalength, 0);  // Read Data Frame
1125
  dw_event.timeStamp32l =  (uint32_t)rxTimeStamp[0] + ((uint32_t)rxTimeStamp[1] << 8) + ((uint32_t)rxTimeStamp[2] << 16) + ((uint32_t)rxTimeStamp[3] << 24);
1126
  dw_event.timeStamp = rxTimeStamp[4];
1127
  dw_event.timeStamp <<= 32;
1128
  dw_event.timeStamp += dw_event.timeStamp32l;
1129
  dw_event.timeStamp32h = ((uint32_t)rxTimeStamp[4] << 24) + (dw_event.timeStamp32l >> 8);
1130

    
1131
  dw_event.type = 0; //type will be added as part of adding to event queue
1132
  dw_event.type_save = rxd_event;
1133
  dw_event.type_pend = DWT_SIG_DW_IDLE;
1134

    
1135
  //if Listener then just report the received frame to the instance (application)
1136
  if(rxd_event == DWT_SIG_RX_OKAY) { //Process good/known frame types
1137
    uint16_t sourceAddress = (uint16_t)(((uint16_t)dw_event.msgu.frame[srcAddr_index+1]) << 8) + (uint16_t)(dw_event.msgu.frame[srcAddr_index]);
1138

    
1139
    if(instance_data[instance].mode != LISTENER)      {
1140
      if(instance_data[instance].mode == TAG) //if tag got a good frame - this is probably a response, but could also be some other non-ranging frame
1141
        //(although due to frame filtering this is limited as non-addressed frames are filtered out)
1142
      {
1143
        instance_data[instance].responseTO--; //got 1 more response or other RX frame - need to reduce timeout (for next response)
1144
      }
1145

    
1146
      //check if this is a TWR message (and also which one)
1147
      switch(dw_event.msgu.frame[fcode_index]){
1148
      //poll message from an anchor
1149
      case RTLS_DEMO_MSG_ANCH_POLL:{
1150
        //the anchor to anchor ranging poll frames are ignored by A0 and A3
1151
        if(instance_data[instance].gatewayAnchor || (instance_data[instance].instanceAddress16 > A2_ANCHOR_ADDR)){
1152
          //ignore poll from anchor 1 if gateway or anchor 3
1153
          //anchors 2 and 3 will never send polls
1154
          dw_event.type_pend = DWT_SIG_DW_IDLE ;
1155
          break;
1156
        }
1157

    
1158
        if(instance_data[instance].mode == TAG)  {  //tag should ignore any other Polls from anchors
1159
          instance_data[instance].responseTO++; //as will be decremented in the function and was also decremented above
1160
          handle_error_unknownframe(dw_event);
1161
          instance_data[instance].stopTimer = 1;
1162
          instance_data[instance].rxMsgCount++;
1163
          return;
1164
        }
1165

    
1166
        //update the response index and number of responses received tables
1167
        instance_data[instance].rxRespsIdx = (uint8_t) ((dw_event.msgu.frame[POLL_RNUM+fcode_index] & 0xf)
1168
            + (((sourceAddress&0x3) + 8) << 4));
1169
        instance_data[instance].rxResps[instance_data[instance].rxRespsIdx] = 0;
1170
        //debug LED on
1171
        //                                                led_on(LED_PC9);
1172

    
1173
        //prepare the response and write it to the tx buffer
1174
        ancprepareresponse2(sourceAddress, srcAddr_index, fcode_index, &dw_event.msgu.frame[0]);
1175

    
1176
        //A2 does not need timeout if ranging to A1
1177
        if(sourceAddress != A1_ANCHOR_ADDR){
1178
          dwt_setrxtimeout((uint16_t)instance_data[instance].fwtoTimeAnc_sy); //reconfigure the timeout for response
1179
        }
1180

    
1181
        //set the bast reply time (the actual will be Poll rx time + instance_data[0].fixedReplyDelayAnc)
1182
        instance_data[instance].delayedReplyTime = dw_event.timeStamp32h ;
1183
        instance_data[instance].responseTO = (instance_data[instance].instanceAddress16 - sourceAddress) & 0x3; //set number of expected responses
1184

    
1185
        dw_event.type_pend = anctxorrxreenable(instance_data[instance].instanceAddress16, 2+1);
1186

    
1187
        instance_data[instance].tofAnc[sourceAddress & 0x3] = INVALID_TOF; //clear ToF ..
1188
        //debug LED off
1189
        //                                                led_off(LED_PC9);
1190
        break;
1191
      }
1192

    
1193
      case RTLS_DEMO_MSG_TAG_POLL:{
1194
        if(instance_data[instance].mode == TAG) {  //tag should ignore any other Polls from tags
1195
          instance_data[instance].responseTO++; //as will be decremented in the function and was also decremented above
1196
          handle_error_unknownframe(dw_event);
1197
          instance_data[instance].stopTimer = 1;
1198
          instance_data[instance].rxMsgCount++;
1199
          return;
1200
        }
1201
        instance_data[instance].rxRespsIdx = (uint8_t) ((dw_event.msgu.frame[POLL_RNUM+fcode_index] & 0xf)
1202
            + ((sourceAddress&0x7) << 4));
1203
        instance_data[instance].rxResps[instance_data[instance].rxRespsIdx] = 0;
1204

    
1205
        //prepare the response and write it to the tx buffer
1206
        ancprepareresponse(sourceAddress, srcAddr_index, fcode_index, &dw_event.msgu.frame[0], dw_event.uTimeStamp);
1207

    
1208
        dwt_setrxtimeout((uint16_t)instance_data[instance].fwtoTimeAnc_sy); //reconfigure the timeout for response
1209

    
1210
        instance_data[0].delayedReplyTime = dw_event.timeStamp32h /*+ (instance_data[0].fixedReplyDelayAnc >> 8)*/ ;
1211
        instance_data[instance].responseTO = NUM_EXPECTED_RESPONSES; //set number of expected responses to 3 (from other anchors)
1212

    
1213
        dw_event.type_pend = anctxorrxreenable(instance_data[instance].instanceAddress16, 2+0);
1214

    
1215
        instance_data[instance].tof[sourceAddress & 0x7] = INVALID_TOF; //clear ToF ..
1216
      }
1217
      break;
1218

    
1219
      //we got a response from a "responder" (anchor)
1220
      case RTLS_DEMO_MSG_ANCH_RESP:
1221
      case RTLS_DEMO_MSG_ANCH_RESP2:{
1222

    
1223
        //we are a tag
1224
        if(instance_data[instance].mode == TAG){
1225
          uint8_t index ;
1226
          instance_data[instance].rxResps[instance_data[instance].rangeNum]++;
1227
          dw_event.type_pend = tagrxreenable(sourceAddress); //responseTO decremented above...
1228
          index = RRXT0 + 5*(sourceAddress & 0x3);
1229

    
1230
          instance_data[instance].rxResponseMask |= (0x1 << (sourceAddress & 0x3)); //add anchor ID to the mask
1231
          // Write Response RX time field of Final message
1232
          memcpy(&(instance_data[instance].msg_f.messageData[index]), rxTimeStamp, 5);
1233

    
1234
        }
1235
        else if (instance_data[instance].mode == ANCHOR_RNG) {  //A0 and A1 only when ranging to other anchors
1236
          uint8_t index ;
1237
          instance_data[instance].rxResps[instance_data[instance].rangeNumAnc]++;
1238
          dw_event.type_pend = ancsendfinalorrxreenable(sourceAddress);
1239
          index = RRXT0 + 5*(sourceAddress & 0x3);
1240

    
1241
          instance_data[instance].rxResponseMaskAnc |= (0x1 << (sourceAddress & 0x3)); //add anchor ID to the mask
1242
          // Write Response RX time field of Final message
1243
          memcpy(&(instance_data[instance].msg_f.messageData[index]), rxTimeStamp, 5);
1244
        }
1245
        else { //normal anchor mode
1246
          //got a response... (check if we got a Poll with the same range number as in this response)
1247
          if(RTLS_DEMO_MSG_ANCH_RESP == dw_event.msgu.frame[fcode_index]){
1248
            if((instance_data[instance].rxResps[instance_data[instance].rxRespsIdx] >= 0) //we got the poll else ignore this response
1249
                && (instance_data[instance].responseTO > 0)        ) {  //if responseTO == 0 we have already received all of the responses - meaning should not be here => error
1250
              instance_data[instance].rxResps[instance_data[instance].rxRespsIdx]++; //increment the number of responses received
1251
              instance_data[instance].responseTO--;
1252

    
1253
              //send a response or re-enable rx
1254
              dw_event.type_pend = anctxorrxreenable(sourceAddress, 4+0);
1255
            }
1256
            else {  //like a timeout (error) ...
1257

    
1258
              //send a response or re-enable rx
1259
              dwt_setrxtimeout(0); //reconfigure the timeout
1260
              dwt_rxenable(DWT_START_RX_IMMEDIATE) ;
1261
              dw_event.type_pend = DWT_SIG_RX_PENDING ;
1262
            }
1263
          }
1264
          else {  //in anchor mode and got RTLS_DEMO_MSG_ANCH_RESP2
1265
            if((instance_data[instance].gatewayAnchor) &&
1266
                (instance_data[instance].rxResps[instance_data[instance].rangeNumAnc]) == 2){ //got two responses A1 and A2 this is third (A2's to A1)
1267
              instance_data[instance].rxResps[instance_data[instance].rangeNumAnc]++;
1268
              instance_data[instance].rxResponseMaskAnc |= 0x8 ;
1269

    
1270
              dw_event.type_pend = anctxorrxreenable(sourceAddress, 4+1); //re-enable the RX
1271
            }
1272
            //A2 got A1's response to A0 - send A2 response (but only if we got the Poll from A0)
1273
            else if((instance_data[instance].instanceAddress16 == A2_ANCHOR_ADDR) &&
1274
                (instance_data[instance].rxResps[instance_data[instance].rxRespsIdx] >= 0) ){
1275
              instance_data[instance].rxResps[instance_data[instance].rxRespsIdx]++;
1276
              instance_data[instance].responseTO--;
1277

    
1278
              dwt_setrxtimeout(0);
1279
              dwt_setrxaftertxdelay(0); //clear rx on delay as Final will come sooner than if we were waiting for next Response
1280
              dw_event.type_pend = anctxorrxreenable(sourceAddress, 1);
1281
            }
1282
            else {  // if other anchor A1, A2, A3 .. ignore these responses when in ANCHOR mode
1283
              dwt_setrxtimeout(0); //reconfigure the timeout
1284
              dwt_rxenable(DWT_START_RX_IMMEDIATE) ;
1285
              dw_event.type_pend = DWT_SIG_RX_PENDING ;
1286
            }
1287
          }
1288
        }
1289

    
1290
      }
1291
      break;
1292

    
1293
      case RTLS_DEMO_MSG_TAG_FINAL:
1294
      case RTLS_DEMO_MSG_ANCH_FINAL:
1295
        if(instance_data[instance].mode == TAG) {  //tag should ignore any other Final from anchors
1296
          instance_data[instance].responseTO++; //as will be decremented in the function and was also decremented above
1297
          handle_error_unknownframe(dw_event);
1298
          instance_data[instance].stopTimer = 1;
1299
          instance_data[instance].rxMsgCount++;
1300
          return;
1301
        }
1302
      break;
1303
//        __attribute__ ((fallthrough));
1304

    
1305
        //if anchor fall into case below and process the frame
1306
      default: {  //process rx frame
1307
        dw_event.type_pend = DWT_SIG_DW_IDLE;
1308
      }
1309
      break;
1310

    
1311
      }
1312
    }//end of if not Listener mode
1313
    instance_data[instance].stopTimer = 1;
1314

    
1315
    instance_putevent(dw_event, rxd_event);
1316

    
1317
    instance_data[instance].rxMsgCount++;
1318
  }
1319
  else { //if (rxd_event == SIG_RX_UNKNOWN) //need to re-enable the rx (got unknown frame type)
1320
    handle_error_unknownframe(dw_event);
1321
  }
1322
  //  }
1323
}
1324

    
1325

    
1326
/*! Callback funtion for RX timeout (available from newer driver version) */
1327
#pragma GCC optimize ("O3")
1328
void instance_rxtimeoutcallback(const dwt_cb_data_t *rxd){
1329

    
1330
    (void) rxd;
1331
    event_data_t dw_event;
1332

    
1333
    int instance = 0;
1334

    
1335
    dw_event.type_pend = DWT_SIG_DW_IDLE;
1336

    
1337
    if(instance_data[instance].mode == ANCHOR) {
1338
        //check if anchor has received all of the responses from other anchors (it could have received only 1 or 2)
1339
        //it's timed out (re-enable rx or tx response)
1340
        if(instance_data[instance].responseTO > 0) {
1341
            instance_data[instance].responseTO--;
1342
            //send a response or re-enable rx
1343
            dw_event.type_pend = anctxorrxreenable(instance_data[instance].instanceAddress16, 6+0);
1344
//          Print_On_Uart("Re-enable RX in rxtimeout callback\r\n");
1345
        }
1346
    }
1347
    dw_event.type = 0;
1348
    dw_event.type_save = DWT_SIG_RX_TIMEOUT;
1349
    dw_event.rxLength = 0;
1350
    dw_event.timeStamp = 0;
1351
    dw_event.timeStamp32l = 0;
1352
    dw_event.timeStamp32h = 0;
1353

    
1354
    instance_putevent(dw_event, DWT_SIG_RX_TIMEOUT);
1355
//  printf("RX timeout while in %d\n", instance_data[instance].testAppState);
1356

    
1357
}
1358

    
1359

    
1360
/*! Callback funtion for RX error (available from newer driver version) */
1361
#pragma GCC optimize ("O3")
1362
void instance_rxerrorcallback(const dwt_cb_data_t *rxd) {
1363

    
1364
    (void) rxd;
1365
    event_data_t dw_event;
1366

    
1367
    dw_event.uTimeStamp = portGetTickCnt();
1368

    
1369
    handle_error_unknownframe(dw_event);
1370
}
1371

    
1372

    
1373

    
1374
#pragma GCC optimize ("O3")
1375
int instance_peekevent(void){
1376
  int instance = 0;
1377
  return instance_data[instance].dwevent[instance_data[instance].dweventPeek].type; //return the type of event that is in front of the queue
1378
}
1379

    
1380
#pragma GCC optimize ("O3")
1381
void instance_saveevent(event_data_t newevent, uint8_t etype){
1382
  int instance = 0;
1383

    
1384
  instance_data[instance].saved_dwevent = newevent;
1385
  instance_data[instance].saved_dwevent.type = etype;
1386
}
1387

    
1388
#pragma GCC optimize ("O3")
1389
event_data_t instance_getsavedevent(void){
1390
  int instance = 0;
1391

    
1392
  return instance_data[instance].saved_dwevent;
1393
}
1394

    
1395
#pragma GCC optimize ("O3")
1396
void instance_putevent(event_data_t newevent, uint8_t etype){
1397
  int instance = 0;
1398
  //newevent.eventtime = portGetTickCnt();
1399
  newevent.gotit = 0 ; //newevent.eventtimeclr = 0;
1400

    
1401
  //copy event
1402
  instance_data[instance].dwevent[instance_data[instance].dweventIdxIn] = newevent;
1403

    
1404
  //set type - this makes it a new event (making sure the event data is copied before event is set as new)
1405
  //to make sure that the get event function does not get an incomplete event
1406
  instance_data[instance].dwevent[instance_data[instance].dweventIdxIn].type = etype;
1407

    
1408
  instance_data[instance].dweventIdxIn++;
1409

    
1410
  if(MAX_EVENT_NUMBER == instance_data[instance].dweventIdxIn)
1411
  {
1412
    instance_data[instance].dweventIdxIn = 0;
1413
  }
1414
  //eventIncount++;
1415

    
1416
  //printf("put %d - in %d out %d @ %d\n", newevent.type, instance_data[instance].dweventCntIn, instance_data[instance].dweventCntOut, ptime);
1417
}
1418

    
1419
event_data_t dw_event_g;
1420

    
1421
#pragma GCC optimize ("O3")
1422
event_data_t* instance_getevent(int x){
1423
  int instance = 0;
1424
  int indexOut = instance_data[instance].dweventIdxOut;
1425

    
1426
  //dw_event_g = instance_data[instance].dwevent[instance_data[instance].dweventCntOut]; //this holds any TX/RX events
1427

    
1428
  //memcpy(&dw_event_g, &instance_data[instance].dwevent[instance_data[instance].dweventCntOut], sizeof(event_data_t));
1429

    
1430
  if(instance_data[instance].dwevent[indexOut].type == 0) {  //exit with "no event"
1431
    dw_event_g.type = 0;
1432
    dw_event_g.type_save = 0;
1433
    return &dw_event_g;
1434
  }
1435

    
1436
  //copy the event
1437
  dw_event_g.type_save = instance_data[instance].dwevent[indexOut].type_save ;
1438
  dw_event_g.type_pend = instance_data[instance].dwevent[indexOut].type_pend ;
1439
  dw_event_g.rxLength = instance_data[instance].dwevent[indexOut].rxLength ;
1440
  dw_event_g.timeStamp = instance_data[instance].dwevent[indexOut].timeStamp ;
1441
  dw_event_g.timeStamp32l = instance_data[instance].dwevent[indexOut].timeStamp32l ;
1442
  dw_event_g.timeStamp32h = instance_data[instance].dwevent[indexOut].timeStamp32h ;
1443
  dw_event_g.uTimeStamp = instance_data[instance].dwevent[indexOut].uTimeStamp ;
1444
  //dw_event_g.eventtime = instance_data[instance].dwevent[indexOut].eventtime ;
1445
  //dw_event_g.eventtimeclr = instance_data[instance].dwevent[indexOut].eventtimeclr ;
1446
  //dw_event_g.gotit = instance_data[instance].dwevent[indexOut].gotit ;
1447

    
1448
  memcpy(&dw_event_g.msgu, &instance_data[instance].dwevent[indexOut].msgu, sizeof(instance_data[instance].dwevent[indexOut].msgu));
1449

    
1450
  dw_event_g.type = instance_data[instance].dwevent[indexOut].type ;
1451

    
1452

    
1453
  instance_data[instance].dwevent[indexOut].gotit = (uint8_t)x;
1454

    
1455
  //instance_data[instance].dwevent[indexOut].eventtimeclr = portGetTickCnt();
1456

    
1457
  instance_data[instance].dwevent[indexOut].type = 0; //clear the event
1458

    
1459
  instance_data[instance].dweventIdxOut++;
1460
  if(MAX_EVENT_NUMBER == instance_data[instance].dweventIdxOut){   //wrap the counter
1461
    instance_data[instance].dweventIdxOut = 0;
1462
  }
1463
  instance_data[instance].dweventPeek = instance_data[instance].dweventIdxOut; //set the new peek value
1464

    
1465
  //if(dw_event.type) printf("get %d - in %d out %d @ %d\n", dw_event.type, instance_data[instance].dweventCntIn, instance_data[instance].dweventCntOut, ptime);
1466

    
1467
  //eventOutcount++;
1468

    
1469

    
1470
  return &dw_event_g;
1471
}
1472

    
1473
void instance_clearevents(void){
1474
  int i = 0;
1475
  int instance = 0;
1476

    
1477
  for(i=0; i<MAX_EVENT_NUMBER; i++) {
1478
    memset(&instance_data[instance].dwevent[i], 0, sizeof(event_data_t));
1479
  }
1480

    
1481
  instance_data[instance].dweventIdxIn = 0;
1482
  instance_data[instance].dweventIdxOut = 0;
1483
  instance_data[instance].dweventPeek = 0;
1484

    
1485
  //eventOutcount = 0;
1486
  //eventIncount = 0;
1487
}
1488

    
1489
// -------------------------------------------------------------------------------------------------------------------
1490
#pragma GCC optimize ("O3")
1491
int instance_run(void){
1492
  int instance = 0 ;
1493
  int done = INST_NOT_DONE_YET;
1494
  int message = instance_peekevent(); //get any of the received events from ISR
1495

    
1496

    
1497
  while(done == INST_NOT_DONE_YET){
1498
    //int state = instance_data[instance].testAppState;
1499
    done = testapprun(&instance_data[instance], message) ;                                               // run the communications application
1500

    
1501
    //we've processed message
1502
    message = 0;
1503
  }
1504

    
1505
  if(done == INST_DONE_WAIT_FOR_NEXT_EVENT_TO) { //we are in RX and need to timeout (Tag needs to send another poll if no Rx frame)
1506
    if(instance_data[instance].mode == TAG) { //Tag (is either in RX or sleeping)
1507
      int32_t nextPeriod ;
1508

    
1509
      // next period will be a positive number because correction is -0.5 to +1.5 periods, (and tagSleepTime_ms is the period)
1510
      nextPeriod = instance_data[instance].tagSleepRnd + instance_data[instance].tagSleepTime_ms + instance_data[instance].tagSleepCorrection;
1511

    
1512
      instance_data[instance].nextSleepPeriod = (uint32_t) nextPeriod ; //set timeout time, CAST the positive period to UINT for correct wrapping.
1513
      instance_data[instance].tagSleepCorrection2 = instance_data[instance].tagSleepCorrection;
1514
      instance_data[instance].tagSleepCorrection = 0; //clear the correction
1515
      instance_data[instance].instanceTimerEn = 1; //start timer
1516
    }
1517
    instance_data[instance].stopTimer = 0 ; //clear the flag - timer can run if instancetimer_en set (set above)
1518
    instance_data[instance].done = INST_NOT_DONE_YET;
1519
  }
1520

    
1521
  //check if timer has expired
1522
  if((instance_data[instance].instanceTimerEn == 1) && (instance_data[instance].stopTimer == 0))  {
1523
    if(instance_data[instance].mode == TAG)    {
1524
      if((portGetTickCnt() - instance_data[instance].instanceWakeTime) > instance_data[instance].nextSleepPeriod)      {
1525
        event_data_t dw_event;
1526
        instance_data[instance].instanceTimerEn = 0;
1527
        dw_event.rxLength = 0;
1528
        dw_event.type = 0;
1529
        dw_event.type_save = 0x80 | DWT_SIG_RX_TIMEOUT;
1530
        //printf("PC timeout DWT_SIG_RX_TIMEOUT\n");
1531
        instance_putevent(dw_event, DWT_SIG_RX_TIMEOUT);
1532
      }
1533
    }
1534
#if (ANCTOANCTWR == 1) //allow anchor to anchor ranging
1535
    else if(instance_data[instance].mode == ANCHOR)    {
1536
      uint32_t slotTime = portGetTickCnt() % instance_data[instance].sframePeriod;
1537

    
1538
      if(instance_data[instance].gatewayAnchor) {
1539
        //if we are in the last slot - then A0 ranges to A1 and A2
1540
        if( slotTime >= instance_data[instance].a0SlotTime)        {
1541
          port_DisableEXT_IRQ(); //enable ScenSor IRQ before starting
1542
          //anchor0 sends poll to anchor1
1543
          instance_data[instance].mode = ANCHOR_RNG; //change to ranging initiator
1544
          dwt_forcetrxoff(); //disable DW1000
1545
          instance_clearevents(); //clear any events
1546
          //change state to send a Poll
1547
          instance_data[instance].testAppState = TA_TXPOLL_WAIT_SEND ;
1548
          instance_data[instance].msg_f.destAddr[0] = 0x1 ;
1549
          instance_data[instance].msg_f.destAddr[1] = (GATEWAY_ANCHOR_ADDR >> 8);
1550
          instance_data[instance].instanceTimerEn = 0;
1551
          instance_data[instance].rangeNumAnc++;
1552
          port_EnableEXT_IRQ(); //enable ScenSor IRQ before starting
1553
        }
1554
      }
1555
      else if (instance_data[instance].instanceAddress16 == A1_ANCHOR_ADDR) { //A1 ranges to A2 in the 2nd half of last slot
1556
        if(portGetTickCnt() >= instance_data[instance].a1SlotTime) {
1557
          port_DisableEXT_IRQ(); //enable ScenSor IRQ before starting
1558
          //anchor1 sends poll to anchor2
1559
          instance_data[instance].mode = ANCHOR_RNG; //change to ranging initiator
1560
          dwt_forcetrxoff(); //disable DW1000
1561
          instance_clearevents(); //clear any events
1562
          //change state to send a Poll
1563
          instance_data[instance].testAppState = TA_TXPOLL_WAIT_SEND ;
1564
          instance_data[instance].msg_f.destAddr[0] = 0x2 ;
1565
          instance_data[instance].msg_f.destAddr[1] = (GATEWAY_ANCHOR_ADDR >> 8);
1566

    
1567
          instance_data[instance].instanceTimerEn = 0;
1568
          //instance_data[instance].a1SlotTime = 0;
1569
          port_EnableEXT_IRQ(); //enable ScenSor IRQ before starting
1570
        }
1571
      }
1572
    }
1573
#endif
1574
  }
1575

    
1576
#if (ANCTOANCTWR == 1) //allow anchor to anchor ranging
1577
  else if (instance_data[instance].instanceTimerEn == 0){
1578
    if((instance_data[instance].mode == ANCHOR) && (instance_data[instance].gatewayAnchor)){
1579
      uint32_t slotTime = portGetTickCnt() % instance_data[instance].sframePeriod;
1580
      //enable the timer in 1st slot
1581
      if(slotTime < instance_data[instance].slotPeriod){
1582
        instance_data[instance].instanceTimerEn = 1;
1583
      }
1584
    }
1585
  }
1586
#endif
1587
  return 0 ;
1588
}
1589

    
1590

    
1591
void instance_close(void){
1592
  //wake up device from low power mode
1593
  //NOTE - in the ARM  code just drop chip select for 200us
1594
  clear_SPI_chip_select();  //CS low
1595
  Sleep(1);   //200 us to wake up then waits 5ms for DW1000 XTAL to stabilise
1596
  set_SPI_chip_select();  //CS high
1597
  Sleep(5);
1598
  dwt_entersleepaftertx(0); // clear the "enter deep sleep after tx" bit
1599
  dwt_setinterrupt(0xFFFFFFFF, 0); //don't allow any interrupts
1600

    
1601
}
1602

    
1603

    
1604
void instance_notify_DW1000_inIDLE(int idle){
1605
  instance_data[0].dwIDLE = idle;
1606
}
1607

    
1608
void instanceconfigtxpower(uint32_t txpower){
1609
  instance_data[0].txPower = txpower ;
1610

    
1611
  instance_data[0].txPowerChanged = 1;
1612
}
1613

    
1614
void instancesettxpower(void){
1615
  if(instance_data[0].txPowerChanged == 1){
1616
    //Configure TX power
1617
    dwt_write32bitreg(0x1E, instance_data[0].txPower);
1618

    
1619
    instance_data[0].txPowerChanged = 0;
1620
  }
1621
}
1622

    
1623
void instanceconfigantennadelays(uint16_t tx, uint16_t rx){
1624
  instance_data[0].txAntennaDelay = tx ;
1625
  instance_data[0].rxAntennaDelay = rx ;
1626

    
1627
  instance_data[0].antennaDelayChanged = 1;
1628
}
1629

    
1630
void instancesetantennadelays(void){
1631
  if(instance_data[0].antennaDelayChanged == 1){
1632
    dwt_setrxantennadelay(instance_data[0].rxAntennaDelay);
1633
    dwt_settxantennadelay(instance_data[0].txAntennaDelay);
1634

    
1635
    instance_data[0].antennaDelayChanged = 0;
1636
  }
1637
}
1638

    
1639

    
1640
uint16_t instancetxantdly(void){
1641
  return instance_data[0].txAntennaDelay;
1642
}
1643

    
1644
uint16_t instancerxantdly(void){
1645
  return instance_data[0].rxAntennaDelay;
1646
}
1647

    
1648
uint8_t instancevalidranges(void){
1649
  uint8_t x = instance_data[0].rxResponseMaskReport;
1650
  instance_data[0].rxResponseMaskReport = 0; //reset mask as we have printed out the ToFs
1651
  return x;
1652
}
1653
#endif
1654

    
1655

    
1656
/*! The following Functions are added for user application (previously on the API )*/
1657

    
1658
/*! ------------------------------------------------------------------------------------------------------------------
1659
 * @fn dwt_getotptxpower()
1660
 *
1661
 * @brief This API function returns the tx power value read from OTP memory as part of initialisation
1662
 *
1663
 * input parameters
1664
 * @param prf   -   this is the PRF e.g. DWT_PRF_16M or DWT_PRF_64M
1665
 * @param chan  -   this is the channel e.g. 1 to 7
1666
 *
1667
 * output parameters
1668
 *
1669
 * returns tx power value for a given PRF and channel
1670
 */
1671
uint32_t dwt_getotptxpower(uint8_t prf, uint8_t chan){
1672
    return platformLocalData.txPowCfg[(prf - DWT_PRF_16M) + (chan_idx[chan] * 2)];
1673
}
1674

    
1675
/*! ------------------------------------------------------------------------------------------------------------------
1676
 * @fn dwt_getTREKOTPantennadelay()
1677
 *
1678
 * @brief This API function returns the antenna delay read from the OTP memory as part of device initialisation
1679
 * Note: the antenna delay will only be read if dwt_initialise is called with DWT_LOADANTDLY bit set in the config parameter
1680
 * The values of antenna delay are only valid for TREK use case modes.
1681
 *
1682
 * input parameters:
1683
 * @param anchor   - this is the mode (Tag or Anchor) if Tag set to 0, if Anchor set to 1
1684
 * @param chan   - this is the channel (1, 2, 3, 4, 5, 7)
1685
 * @param datarate   - this is the datarate DWT_BR_6M8, DWT_BR_110K or DWT_BR_850K
1686
 *
1687
 */
1688
uint16_t dwt_getTREKOTPantennadelay(uint8_t anchor, uint8_t chan, uint8_t datarate){
1689
    uint32_t dly = 0;
1690

    
1691
    // 32-bit antenna delay value previously read from OTP, high 16 bits is value for Anchor mode, low 16-bits for Tag mode
1692
    switch(chan){
1693
        case 2:
1694
            if(datarate == DWT_BR_6M8)
1695
                dly = platformLocalData.antennaCals[0];
1696
            else if(datarate == DWT_BR_110K)
1697
                dly = platformLocalData.antennaCals[1];
1698
            break;
1699
        case 5:
1700
            if(datarate == DWT_BR_6M8)
1701
                dly = platformLocalData.antennaCals[2];
1702
            else if(datarate == DWT_BR_110K)
1703
                dly = platformLocalData.antennaCals[3];
1704
            break;
1705
        default:
1706
            dly = 0;
1707
            break;
1708
    }
1709

    
1710
    return (dly >> (16*(anchor & 0x1))) & 0xFFFF;
1711
}
1712

    
1713
/*! ------------------------------------------------------------------------------------------------------------------
1714
 * @fn dwt_readantennadelay()
1715
 *
1716
 * @brief This API function returns the antenna delay read from the OTP memory as part of device initialisation
1717
 * Note: the antenna delay will only be read if dwt_initialise is called with DWT_LOADANTDLY bit set in the config parameter
1718
 *
1719
 * input parameters:
1720
 * @param prf   -   this is the PRF e.g. DWT_PRF_16M or DWT_PRF_64M
1721
 *
1722
 */
1723
uint16_t dwt_readantennadelay(uint8_t prf){
1724
    // 32-bit antenna delay value previously read from OTP, high 16 bits is value for 64 MHz PRF, low 16-bits for 16 MHz PRF
1725
    return (platformLocalData.antennaDly >> (16*(prf-DWT_PRF_16M))) & 0xFFFF;
1726
}
1727

    
1728

    
1729
/* ==========================================================
1730

1731
Notes:
1732

1733
Previously code handled multiple instances in a single console application
1734

1735
Now have changed it to do a single instance only. With minimal code changes...(i.e. kept [instance] index but it is always 0.
1736

1737
Windows application should call instance_init() once and then in the "main loop" call instance_run().
1738

1739
*/
1740