Statistics
| Branch: | Tag: | Revision:

amiro-lld / source / alld_dw1000.c @ 3fb3c6e7

History | View | Annotate | Download (150.737 KB)

1 fce9feec Robin Ewers
/*
2
AMiRo-LLD is a compilation of low-level hardware drivers for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2018  Thomas Schöpping et al.
4

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU Lesser General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU Lesser General Public License for more details.
14

15
You should have received a copy of the GNU Lesser General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
/*! ------------------------------------------------------------------------------------------------------------------
20
 * @file    deca_device.c
21
 * @brief   Decawave device configuration and control functions
22
 *
23
 * @attention
24
 *
25
 * Copyright 2013 (c) Decawave Ltd, Dublin, Ireland.
26
 *
27
 * All rights reserved.
28
 *
29
 */
30
31
32
#include <alld_dw1000.h>
33
#if defined(AMIROLLD_CFG_USE_DW1000) || defined(__DOXYGEN__)
34
35
#include <alld_dw1000_regs.h>
36
#include <aos_thread.h>
37
#include <assert.h>
38
#include <string.h>
39
#include <stdlib.h>
40
#include <math.h>
41
42
43
// HW dependent implementation (see bottom of file)
44
static int _alld_dw1000_writespi(uint16_t headerLength,
45
               const        uint8_t *headerBuffer,
46
               uint32_t bodyLength,
47
               const        uint8_t *bodyBuffer);
48
49
static int _alld_dw1000_readspi(uint16_t headerLength,
50
                const uint8_t *headerBuffer,
51
                uint32_t readlength,
52
                uint8_t *readBuffer);
53
54
// Defines for enable_clocks function
55
#define FORCE_SYS_XTI  0
56
#define ENABLE_ALL_SEQ 1
57
#define FORCE_SYS_PLL  2
58
#define READ_ACC_ON    7
59
#define READ_ACC_OFF   8
60
#define FORCE_OTP_ON   11
61
#define FORCE_OTP_OFF  12
62
#define FORCE_TX_PLL   13
63
#define FORCE_LDE      14
64
65
// Defines for ACK request bitmask in DATA and MAC COMMAND frame control (first byte) - Used to detect AAT bit wrongly set.
66
#define FCTRL_ACK_REQ_MASK 0x20
67
// Frame control maximum length in bytes.
68
#define FCTRL_LEN_MAX 2
69
70
71
#define NUM_BR 3
72
#define NUM_PRF 2
73
#define NUM_PACS 4
74
#define NUM_BW 2            //2 bandwidths are supported
75
#define NUM_SFD 2           //supported number of SFDs - standard = 0, non-standard = 1
76
#define NUM_CH 6            //supported channels are 1, 2, 3, 4, 5, 7
77
#define NUM_CH_SUPPORTED 8  //supported channels are '0', 1, 2, 3, 4, 5, '6', 7
78
#define PCODES 25           //supported preamble codes
79
80
81
typedef struct {
82
    uint32_t lo32;
83
    uint16_t target[NUM_PRF];
84
} agc_cfg_struct ;
85
86
extern const agc_cfg_struct agc_config ;
87
88
//SFD threshold settings for 110k, 850k, 6.8Mb standard and non-standard
89
extern const uint16_t sftsh[NUM_BR][NUM_SFD];
90
91
extern const uint16_t dtune1[NUM_PRF];
92
93
#define XMLPARAMS_VERSION   (1.17f)
94
95
extern const uint32_t fs_pll_cfg[NUM_CH];
96
extern const uint8_t fs_pll_tune[NUM_CH];
97
extern const uint8_t rx_config[NUM_BW];
98
extern const uint32_t tx_config[NUM_CH];
99
extern const uint8_t dwnsSFDlen[NUM_BR]; //length of SFD for each of the bitrates
100
extern const uint32_t digital_bb_config[NUM_PRF][NUM_PACS];
101
extern const uint8_t chan_idx[NUM_CH_SUPPORTED];
102
extern const double txpwr_compensation[NUM_CH];
103
104
#define PEAK_MULTPLIER  (0x60) //3 -> (0x3 * 32) & 0x00E0
105
#define N_STD_FACTOR    (13)
106
#define LDE_PARAM1      (PEAK_MULTPLIER | N_STD_FACTOR)
107
108
#define LDE_PARAM3_16 (0x1607)
109
#define LDE_PARAM3_64 (0x0607)
110
111
#define MIXER_GAIN_STEP (0.5)
112
#define DA_ATTN_STEP    (2.5)
113
114
// #define DWT_API_ERROR_CHECK     // define so API checks config input parameters
115
116
//-----------------------------------------
117
// map the channel number to the index in the configuration arrays below
118
// 0th element is chan 1, 1st is chan 2, 2nd is chan 3, 3rd is chan 4, 4th is chan 5, 5th is chan 7
119
const uint8_t chan_idx[NUM_CH_SUPPORTED] = {0, 0, 1, 2, 3, 4, 0, 5};
120
121
//-----------------------------------------
122
const uint32_t tx_config[NUM_CH] =
123
{
124
    RF_TXCTRL_CH1,
125
    RF_TXCTRL_CH2,
126
    RF_TXCTRL_CH3,
127
    RF_TXCTRL_CH4,
128
    RF_TXCTRL_CH5,
129
    RF_TXCTRL_CH7,
130
};
131
132
//Frequency Synthesiser - PLL configuration
133
const uint32_t fs_pll_cfg[NUM_CH] =
134
{
135
    FS_PLLCFG_CH1,
136
    FS_PLLCFG_CH2,
137
    FS_PLLCFG_CH3,
138
    FS_PLLCFG_CH4,
139
    FS_PLLCFG_CH5,
140
    FS_PLLCFG_CH7
141
};
142
143
//Frequency Synthesiser - PLL tuning
144
const uint8_t fs_pll_tune[NUM_CH] =
145
{
146
    FS_PLLTUNE_CH1,
147
    FS_PLLTUNE_CH2,
148
    FS_PLLTUNE_CH3,
149
    FS_PLLTUNE_CH4,
150
    FS_PLLTUNE_CH5,
151
    FS_PLLTUNE_CH7
152
};
153
154
//bandwidth configuration
155
const uint8_t rx_config[NUM_BW] =
156
{
157
    RF_RXCTRLH_NBW,
158
    RF_RXCTRLH_WBW
159
};
160
161
162
const agc_cfg_struct agc_config =
163
{
164
    AGC_TUNE2_VAL,
165
    { AGC_TUNE1_16M , AGC_TUNE1_64M }  //adc target
166
};
167
168
//DW non-standard SFD length for 110k, 850k and 6.81M
169
const uint8_t dwnsSFDlen[NUM_BR] =
170
{
171
    DW_NS_SFD_LEN_110K,
172
    DW_NS_SFD_LEN_850K,
173
    DW_NS_SFD_LEN_6M8
174
};
175
176
// SFD Threshold
177
const uint16_t sftsh[NUM_BR][NUM_SFD] =
178
{
179
    {
180
        DRX_TUNE0b_110K_STD,
181
        DRX_TUNE0b_110K_NSTD
182
    },
183
    {
184
        DRX_TUNE0b_850K_STD,
185
        DRX_TUNE0b_850K_NSTD
186
    },
187
    {
188
        DRX_TUNE0b_6M8_STD,
189
        DRX_TUNE0b_6M8_NSTD
190
    }
191
};
192
193
const uint16_t dtune1[NUM_PRF] =
194
{
195
    DRX_TUNE1a_PRF16,
196
    DRX_TUNE1a_PRF64
197
};
198
199
const uint32_t digital_bb_config[NUM_PRF][NUM_PACS] =
200
{
201
    {
202
        DRX_TUNE2_PRF16_PAC8,
203
        DRX_TUNE2_PRF16_PAC16,
204
        DRX_TUNE2_PRF16_PAC32,
205
        DRX_TUNE2_PRF16_PAC64
206
    },
207
    {
208
        DRX_TUNE2_PRF64_PAC8,
209
        DRX_TUNE2_PRF64_PAC16,
210
        DRX_TUNE2_PRF64_PAC32,
211
        DRX_TUNE2_PRF64_PAC64
212
    }
213
};
214
215
const uint16_t lde_replicaCoeff[PCODES] =
216
{
217
    0, // No preamble code 0
218
    LDE_REPC_PCODE_1,
219
    LDE_REPC_PCODE_2,
220
    LDE_REPC_PCODE_3,
221
    LDE_REPC_PCODE_4,
222
    LDE_REPC_PCODE_5,
223
    LDE_REPC_PCODE_6,
224
    LDE_REPC_PCODE_7,
225
    LDE_REPC_PCODE_8,
226
    LDE_REPC_PCODE_9,
227
    LDE_REPC_PCODE_10,
228
    LDE_REPC_PCODE_11,
229
    LDE_REPC_PCODE_12,
230
    LDE_REPC_PCODE_13,
231
    LDE_REPC_PCODE_14,
232
    LDE_REPC_PCODE_15,
233
    LDE_REPC_PCODE_16,
234
    LDE_REPC_PCODE_17,
235
    LDE_REPC_PCODE_18,
236
    LDE_REPC_PCODE_19,
237
    LDE_REPC_PCODE_20,
238
    LDE_REPC_PCODE_21,
239
    LDE_REPC_PCODE_22,
240
    LDE_REPC_PCODE_23,
241
    LDE_REPC_PCODE_24
242
};
243
244
const double txpwr_compensation[NUM_CH] = {
245
    0.0,
246
    0.035,
247
    0.0,
248
    0.0,
249
    0.065,
250
    0.0
251
};
252
253
254
#define NUM_16M_OFFSET  (37)
255
#define NUM_16M_OFFSETWB  (68)
256
#define NUM_64M_OFFSET  (26)
257
#define NUM_64M_OFFSETWB  (59)
258
259
const uint8_t chan_idxnb[NUM_CH_SUPPORTED] = {0, 0, 1, 2, 0, 3, 0, 0}; //only channels 1,2,3 and 5 are in the narrow band tables
260
const uint8_t chan_idxwb[NUM_CH_SUPPORTED] = {0, 0, 0, 0, 0, 0, 0, 1}; //only channels 4 and 7 are in in the wide band tables
261
262
//---------------------------------------------------------------------------------------------------------------------------
263
// Range Bias Correction TABLES of range values in integer units of 25 CM, for 8-bit unsigned storage, MUST END IN 255 !!!!!!
264
//---------------------------------------------------------------------------------------------------------------------------
265
266
// offsets to nearest centimeter for index 0, all rest are +1 cm per value
267
268
#define CM_OFFSET_16M_NB    (-23)   // for normal band channels at 16 MHz PRF
269
#define CM_OFFSET_16M_WB    (-28)   // for wider  band channels at 16 MHz PRF
270
#define CM_OFFSET_64M_NB    (-17)   // for normal band channels at 64 MHz PRF
271
#define CM_OFFSET_64M_WB    (-30)   // for wider  band channels at 64 MHz PRF
272
273
274
//---------------------------------------------------------------------------------------------------------------------------
275
// range25cm16PRFnb: Range Bias Correction table for narrow band channels at 16 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
276
//---------------------------------------------------------------------------------------------------------------------------
277
278
const uint8_t range25cm16PRFnb[4][NUM_16M_OFFSET] =
279
{
280
    // ch 1 - range25cm16PRFnb
281
    {
282
           1,
283
           3,
284
           4,
285
           5,
286
           7,
287
           9,
288
          11,
289
          12,
290
          13,
291
          15,
292
          18,
293
          20,
294
          23,
295
          25,
296
          28,
297
          30,
298
          33,
299
          36,
300
          40,
301
          43,
302
          47,
303
          50,
304
          54,
305
          58,
306
          63,
307
          66,
308
          71,
309
          76,
310
          82,
311
          89,
312
          98,
313
         109,
314
         127,
315
         155,
316
         222,
317
         255,
318
         255
319
    },
320
321
    // ch 2 - range25cm16PRFnb
322
    {
323
           1,
324
           2,
325
           4,
326
           5,
327
           6,
328
           8,
329
           9,
330
          10,
331
          12,
332
          13,
333
          15,
334
          18,
335
          20,
336
          22,
337
          24,
338
          27,
339
          29,
340
          32,
341
          35,
342
          38,
343
          41,
344
          44,
345
          47,
346
          51,
347
          55,
348
          58,
349
          62,
350
          66,
351
          71,
352
          78,
353
          85,
354
          96,
355
         111,
356
         135,
357
         194,
358
         240,
359
         255
360
    },
361
362
    // ch 3 - range25cm16PRFnb
363
    {
364
           1,
365
           2,
366
           3,
367
           4,
368
           5,
369
           7,
370
           8,
371
           9,
372
          10,
373
          12,
374
          14,
375
          16,
376
          18,
377
          20,
378
          22,
379
          24,
380
          26,
381
          28,
382
          31,
383
          33,
384
          36,
385
          39,
386
          42,
387
          45,
388
          49,
389
          52,
390
          55,
391
          59,
392
          63,
393
          69,
394
          76,
395
          85,
396
          98,
397
         120,
398
         173,
399
         213,
400
         255
401
    },
402
403
    // ch 5 - range25cm16PRFnb
404
    {
405
           1,
406
           1,
407
           2,
408
           3,
409
           4,
410
           5,
411
           6,
412
           6,
413
           7,
414
           8,
415
           9,
416
          11,
417
          12,
418
          14,
419
          15,
420
          16,
421
          18,
422
          20,
423
          21,
424
          23,
425
          25,
426
          27,
427
          29,
428
          31,
429
          34,
430
          36,
431
          38,
432
          41,
433
          44,
434
          48,
435
          53,
436
          59,
437
          68,
438
          83,
439
         120,
440
         148,
441
         255
442
    }
443
}; // end range25cm16PRFnb
444
445
446
//---------------------------------------------------------------------------------------------------------------------------
447
// range25cm16PRFwb: Range Bias Correction table for wide band channels at 16 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
448
//---------------------------------------------------------------------------------------------------------------------------
449
450
const uint8_t range25cm16PRFwb[2][NUM_16M_OFFSETWB] =
451
{
452
    // ch 4 - range25cm16PRFwb
453
    {
454
           7,
455
           7,
456
           8,
457
           9,
458
           9,
459
          10,
460
          11,
461
          11,
462
          12,
463
          13,
464
          14,
465
          15,
466
          16,
467
          17,
468
          18,
469
          19,
470
          20,
471
          21,
472
          22,
473
          23,
474
          24,
475
          26,
476
          27,
477
          28,
478
          30,
479
          31,
480
          32,
481
          34,
482
          36,
483
          38,
484
          40,
485
          42,
486
          44,
487
          46,
488
          48,
489
          50,
490
          52,
491
          55,
492
          57,
493
          59,
494
          61,
495
          63,
496
          66,
497
          68,
498
          71,
499
          74,
500
          78,
501
          81,
502
          85,
503
          89,
504
          94,
505
          99,
506
         104,
507
         110,
508
         116,
509
         123,
510
         130,
511
         139,
512
         150,
513
         164,
514
         182,
515
         207,
516
         238,
517
         255,
518
         255,
519
         255,
520
         255,
521
         255
522
    },
523
524
    // ch 7 - range25cm16PRFwb
525
    {
526
           4,
527
           5,
528
           5,
529
           5,
530
           6,
531
           6,
532
           7,
533
           7,
534
           7,
535
           8,
536
           9,
537
           9,
538
          10,
539
          10,
540
          11,
541
          11,
542
          12,
543
          13,
544
          13,
545
          14,
546
          15,
547
          16,
548
          17,
549
          17,
550
          18,
551
          19,
552
          20,
553
          21,
554
          22,
555
          23,
556
          25,
557
          26,
558
          27,
559
          29,
560
          30,
561
          31,
562
          32,
563
          34,
564
          35,
565
          36,
566
          38,
567
          39,
568
          40,
569
          42,
570
          44,
571
          46,
572
          48,
573
          50,
574
          52,
575
          55,
576
          58,
577
          61,
578
          64,
579
          68,
580
          72,
581
          75,
582
          80,
583
          85,
584
          92,
585
         101,
586
         112,
587
         127,
588
         147,
589
         168,
590
         182,
591
         194,
592
         205,
593
         255
594
    }
595
}; // end range25cm16PRFwb
596
597
//---------------------------------------------------------------------------------------------------------------------------
598
// range25cm64PRFnb: Range Bias Correction table for narrow band channels at 64 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
599
//---------------------------------------------------------------------------------------------------------------------------
600
601
const uint8_t range25cm64PRFnb[4][NUM_64M_OFFSET] =
602
{
603
    // ch 1 - range25cm64PRFnb
604
    {
605
           1,
606
           2,
607
           2,
608
           3,
609
           4,
610
           5,
611
           7,
612
          10,
613
          13,
614
          16,
615
          19,
616
          22,
617
          24,
618
          27,
619
          30,
620
          32,
621
          35,
622
          38,
623
          43,
624
          48,
625
          56,
626
          78,
627
         101,
628
         120,
629
         157,
630
         255
631
    },
632
633
    // ch 2 - range25cm64PRFnb
634
    {
635
           1,
636
           2,
637
           2,
638
           3,
639
           4,
640
           4,
641
           6,
642
           9,
643
          12,
644
          14,
645
          17,
646
          19,
647
          21,
648
          24,
649
          26,
650
          28,
651
          31,
652
          33,
653
          37,
654
          42,
655
          49,
656
          68,
657
          89,
658
         105,
659
         138,
660
         255
661
    },
662
663
    // ch 3 - range25cm64PRFnb
664
    {
665
           1,
666
           1,
667
           2,
668
           3,
669
           3,
670
           4,
671
           5,
672
           8,
673
          10,
674
          13,
675
          15,
676
          17,
677
          19,
678
          21,
679
          23,
680
          25,
681
          27,
682
          30,
683
          33,
684
          37,
685
          44,
686
          60,
687
          79,
688
          93,
689
         122,
690
         255
691
    },
692
693
    // ch 5 - range25cm64PRFnb
694
    {
695
           1,
696
           1,
697
           1,
698
           2,
699
           2,
700
           3,
701
           4,
702
           6,
703
           7,
704
           9,
705
          10,
706
          12,
707
          13,
708
          15,
709
          16,
710
          17,
711
          19,
712
          21,
713
          23,
714
          26,
715
          30,
716
          42,
717
          55,
718
          65,
719
          85,
720
         255
721
    }
722
}; // end range25cm64PRFnb
723
724
//---------------------------------------------------------------------------------------------------------------------------
725
// range25cm64PRFwb: Range Bias Correction table for wide band channels at 64 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
726
//---------------------------------------------------------------------------------------------------------------------------
727
728
const uint8_t range25cm64PRFwb[2][NUM_64M_OFFSETWB] =
729
{
730
    // ch 4 - range25cm64PRFwb
731
    {
732
           7,
733
           8,
734
           8,
735
           9,
736
           9,
737
          10,
738
          11,
739
          12,
740
          13,
741
          13,
742
          14,
743
          15,
744
          16,
745
          16,
746
          17,
747
          18,
748
          19,
749
          19,
750
          20,
751
          21,
752
          22,
753
          24,
754
          25,
755
          27,
756
          28,
757
          29,
758
          30,
759
          32,
760
          33,
761
          34,
762
          35,
763
          37,
764
          39,
765
          41,
766
          43,
767
          45,
768
          48,
769
          50,
770
          53,
771
          56,
772
          60,
773
          64,
774
          68,
775
          74,
776
          81,
777
          89,
778
          98,
779
         109,
780
         122,
781
         136,
782
         146,
783
         154,
784
         162,
785
         178,
786
         220,
787
         249,
788
         255,
789
         255,
790
         255
791
    },
792
793
    // ch 7 - range25cm64PRFwb
794
    {
795
           4,
796
           5,
797
           5,
798
           5,
799
           6,
800
           6,
801
           7,
802
           7,
803
           8,
804
           8,
805
           9,
806
           9,
807
          10,
808
          10,
809
          10,
810
          11,
811
          11,
812
          12,
813
          13,
814
          13,
815
          14,
816
          15,
817
          16,
818
          16,
819
          17,
820
          18,
821
          19,
822
          19,
823
          20,
824
          21,
825
          22,
826
          23,
827
          24,
828
          25,
829
          26,
830
          28,
831
          29,
832
          31,
833
          33,
834
          35,
835
          37,
836
          39,
837
          42,
838
          46,
839
          50,
840
          54,
841
          60,
842
          67,
843
          75,
844
          83,
845
          90,
846
          95,
847
         100,
848
         110,
849
         135,
850
         153,
851
         172,
852
         192,
853
         255
854
    }
855
}; // end range25cm64PRFwb
856
857
858
859
860
861
/*! ------------------------------------------------------------------------------------------------------------------
862
 * Function: dwt_getrangebias()
863
 *
864
 * Description: This function is used to return the range bias correction need for TWR with DW1000 units.
865
 *
866
 * input parameters:        
867
 * @param chan  - specifies the operating channel (e.g. 1, 2, 3, 4, 5, 6 or 7) 
868
 * @param range - the calculated distance before correction
869
 * @param prf        - this is the PRF e.g. DWT_PRF_16M or DWT_PRF_64M
870
 *
871
 * output parameters
872
 *
873
 * returns correction needed in meters
874
 */
875
double dwt_getrangebias(uint8_t chan, float range, uint8_t prf)
876
{
877
    //first get the lookup index that corresponds to given range for a particular channel at 16M PRF
878
    int i = 0 ;
879
    int chanIdx ;
880
    int cmoffseti ;                                 // integer number of CM offset
881
882
    double mOffset ;                                // final offset result in metres
883
884
    // NB: note we may get some small negitive values e.g. up to -50 cm.
885
886
    int rangeint25cm = (int) (range * 4.00) ;       // convert range to integer number of 25cm values.
887
888
    if (rangeint25cm > 255) rangeint25cm = 255 ;    // make sure it matches largest value in table (all tables end in 255 !!!!)
889
890
    if (prf == DWT_PRF_16M)
891
    {
892
        switch(chan)
893
        {
894
            case 4:
895
            case 7:
896
            {
897
                chanIdx = chan_idxwb[chan];
898
                while (rangeint25cm > range25cm16PRFwb[chanIdx][i]) i++ ;       // find index in table corresponding to range
899
                cmoffseti = i + CM_OFFSET_16M_WB ;                              // nearest centimeter correction
900
            }
901
            break;
902
            default:
903
            {
904
                chanIdx = chan_idxnb[chan];
905
                while (rangeint25cm > range25cm16PRFnb[chanIdx][i]) i++ ;       // find index in table corresponding to range
906
                cmoffseti = i + CM_OFFSET_16M_NB ;                              // nearest centimeter correction
907
            }
908
        }//end of switch
909
    }
910
    else // 64M PRF
911
    {
912
        switch(chan)
913
        {
914
            case 4:
915
            case 7:
916
            {
917
                chanIdx = chan_idxwb[chan];
918
                while (rangeint25cm > range25cm64PRFwb[chanIdx][i]) i++ ;       // find index in table corresponding to range
919
                cmoffseti = i + CM_OFFSET_64M_WB ;                              // nearest centimeter correction
920
            }
921
            break;
922
            default:
923
            {
924
                chanIdx = chan_idxnb[chan];
925
                while (rangeint25cm > range25cm64PRFnb[chanIdx][i]) i++ ;       // find index in table corresponding to range
926
                cmoffseti = i + CM_OFFSET_64M_NB ;                              // nearest centimeter correction
927
            }
928
        }//end of switch
929
    } // end else
930
931
932
    mOffset = (float) cmoffseti ;                                       // offset result in centimmetres
933
934
    mOffset *= 0.01 ;                                                   // convert to metres
935
936
    return (mOffset) ;
937
}
938
939
940
941
// -------------------------------------------------------------------------------------------------------------------
942
//
943
// Internal functions for controlling and configuring the device
944
//
945
// -------------------------------------------------------------------------------------------------------------------
946
947
// Enable and Configure specified clocks
948
void _dwt_enableclocks(int clocks) ;
949
// Configure the ucode (FP algorithm) parameters
950
void _dwt_configlde(int prf);
951
// Load ucode from OTP/ROM
952
void _dwt_loaducodefromrom(void);
953
// Read non-volatile memory
954
uint32_t _dwt_otpread(uint32_t address);
955
// Program the non-volatile memory
956
uint32_t _dwt_otpprogword32(uint32_t data, uint16_t address);
957
// Upload the device configuration into always on memory
958
void _dwt_aonarrayupload(void);
959
// -------------------------------------------------------------------------------------------------------------------
960
961
/*!
962
 * Static data for DW1000 DecaWave Transceiver control
963
 */
964
965
static dwt_local_data_t dw1000local[DWT_NUM_DW_DEV] ; // Static local device data, can be an array to support multiple DW1000 testing applications/platforms
966
static dwt_local_data_t *pdw1000local = dw1000local ; // Static local data structure pointer
967
968
969
/*! ------------------------------------------------------------------------------------------------------------------
970
 * @fn dwt_setdevicedataptr()
971
 *
972
 * @brief This function sets the local data structure pointer to point to the structure in the local array as given by the index.
973
 *
974
 * input parameters
975
 * @param index    - selects the array object to point to. Must be within the array bounds, i.e. < DWT_NUM_DW_DEV
976
 *
977
 * output parameters
978
 *
979
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
980
 */
981
int dwt_setdevicedataptr(unsigned int index)
982
{
983
    // Check the index is within the array bounds
984
    if (DWT_NUM_DW_DEV > index) // return error if index outside the array bounds
985
    {
986
        return DWT_ERROR ;
987
    }
988
989
    pdw1000local = &dw1000local[index];
990
991
    return DWT_SUCCESS ;
992
}
993
994
/*! ------------------------------------------------------------------------------------------------------------------
995
 * @fn dwt_initialise()
996
 *
997
 * @brief This function initiates communications with the DW1000 transceiver
998
 * and reads its DEV_ID register (address 0x00) to verify the IC is one supported
999
 * by this software (e.g. DW1000 32-bit device ID value is 0xDECA0130).  Then it
1000
 * does any initial once only device configurations needed for use and initialises
1001
 * as necessary any static data items belonging to this low-level driver.
1002
 *
1003
 * NOTES:
1004
 * 1.this function needs to be run before dwt_configuresleep, also the SPI frequency has to be < 3MHz
1005
 * 2.it also reads and applies LDO tune and crystal trim values from OTP memory
1006
 *
1007
 * input parameters
1008
 * @param config    -   specifies what configuration to load
1009
 *                  DWT_LOADUCODE     0x1 - load the LDE microcode from ROM - enabled accurate RX timestamp
1010
 *                  DWT_LOADNONE      0x0 - do not load any values from OTP memory
1011
 *
1012
 * output parameters
1013
 *
1014
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
1015
 */
1016
// OTP addresses definitions
1017
#define LDOTUNE_ADDRESS (0x04)
1018
#define PARTID_ADDRESS (0x06)
1019
#define LOTID_ADDRESS  (0x07)
1020
#define VBAT_ADDRESS   (0x08)
1021
#define VTEMP_ADDRESS  (0x09)
1022
#define XTRIM_ADDRESS  (0x1E)
1023
1024
int dwt_initialise(const uint16_t config, DW1000Driver* drv)
1025
{
1026
    uint16_t otp_addr = 0;
1027
    uint32_t ldo_tune = 0;
1028
1029
    pdw1000local->dblbuffon = 0; // Double buffer mode off by default
1030
    pdw1000local->wait4resp = 0;
1031
    pdw1000local->sleep_mode = 0;
1032
1033
    pdw1000local->cbTxDone = NULL;
1034
    pdw1000local->cbRxOk = NULL;
1035
    pdw1000local->cbRxTo = NULL;
1036
    pdw1000local->cbRxErr = NULL;
1037
1038
    pdw1000local->driver = drv;
1039
1040
    // Read and validate device ID return -1 if not recognised
1041
    if (DWT_DEVICE_ID != dwt_readdevid()) // MP IC ONLY (i.e. DW1000) FOR THIS CODE
1042
    {
1043
        return DWT_ERROR ;
1044
    }
1045
1046
    // Make sure the device is completely reset before starting initialisation
1047
    dwt_softreset();
1048
1049
    _dwt_enableclocks(FORCE_SYS_XTI); // NOTE: set system clock to XTI - this is necessary to make sure the values read by _dwt_otpread are reliable
1050
1051
    // Configure the CPLL lock detect
1052
    dwt_write8bitoffsetreg(EXT_SYNC_ID, EC_CTRL_OFFSET, EC_CTRL_PLLLCK);
1053
1054
    // Read OTP revision number
1055
    otp_addr = _dwt_otpread(XTRIM_ADDRESS) & 0xffff;        // Read 32 bit value, XTAL trim val is in low octet-0 (5 bits)
1056
    pdw1000local->otprev = (otp_addr >> 8) & 0xff;            // OTP revision is next byte
1057
1058
    // Load LDO tune from OTP and kick it if there is a value actually programmed.
1059
    ldo_tune = _dwt_otpread(LDOTUNE_ADDRESS);
1060
    if((ldo_tune & 0xFF) != 0)
1061
    {
1062
        // Kick LDO tune
1063
        dwt_write8bitoffsetreg(OTP_IF_ID, OTP_SF, OTP_SF_LDO_KICK); // Set load LDE kick bit
1064
        pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDO; // LDO tune must be kicked at wake-up
1065
    }
1066
1067
    // Load Part and Lot ID from OTP
1068
    pdw1000local->partID = _dwt_otpread(PARTID_ADDRESS);
1069
    pdw1000local->lotID = _dwt_otpread(LOTID_ADDRESS);
1070
1071
    // XTAL trim value is set in OTP for DW1000 module and EVK/TREK boards but that might not be the case in a custom design
1072
    pdw1000local->init_xtrim = otp_addr & 0x1F;
1073
    if (!pdw1000local->init_xtrim) // A value of 0 means that the crystal has not been trimmed
1074
    {
1075
        pdw1000local->init_xtrim = FS_XTALT_MIDRANGE ; // Set to mid-range if no calibration value inside
1076
    }
1077
    // Configure XTAL trim
1078
    dwt_setxtaltrim(pdw1000local->init_xtrim);
1079
1080
    // Load leading edge detect code
1081
    if(config & DWT_LOADUCODE)
1082
    {
1083
        _dwt_loaducodefromrom();
1084
        pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDE; // microcode must be loaded at wake-up
1085
    }
1086
    else // Should disable the LDERUN enable bit in 0x36, 0x4
1087
    {
1088
        uint16_t rega = dwt_read16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1) ;
1089
        rega &= 0xFDFF ; // Clear LDERUN bit
1090
        dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1, rega) ;
1091
    }
1092
1093
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
1094
1095
    // The 3 bits in AON CFG1 register must be cleared to ensure proper operation of the DW1000 in DEEPSLEEP mode.
1096
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, 0x00);
1097
1098
    // Read system register / store local copy
1099
    pdw1000local->sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
1100
1101
    return DWT_SUCCESS ;
1102
1103
} // end dwt_initialise()
1104
1105
/*! ------------------------------------------------------------------------------------------------------------------
1106
 * @fn dwt_otprevision()
1107
 *
1108
 * @brief This is used to return the read OTP revision
1109
 *
1110
 * NOTE: dwt_initialise() must be called prior to this function so that it can return a relevant value.
1111
 *
1112
 * input parameters
1113
 *
1114
 * output parameters
1115
 *
1116
 * returns the read OTP revision value
1117
 */
1118
uint8_t dwt_otprevision(void)
1119
{
1120
    return pdw1000local->otprev ;
1121
}
1122
1123
/*! ------------------------------------------------------------------------------------------------------------------
1124
 * @fn dwt_setfinegraintxseq()
1125
 *
1126
 * @brief This function enables/disables the fine grain TX sequencing (enabled by default).
1127
 *
1128
 * input parameters
1129
 * @param enable - 1 to enable fine grain TX sequencing, 0 to disable it.
1130
 *
1131
 * output parameters none
1132
 *
1133
 * no return value
1134
 */
1135
void dwt_setfinegraintxseq(int enable)
1136
{
1137
    if (enable)
1138
    {
1139
        dwt_write16bitoffsetreg(PMSC_ID, PMSC_TXFINESEQ_OFFSET, PMSC_TXFINESEQ_ENABLE);
1140
    }
1141
    else
1142
    {
1143
        dwt_write16bitoffsetreg(PMSC_ID, PMSC_TXFINESEQ_OFFSET, PMSC_TXFINESEQ_DISABLE);
1144
    }
1145
}
1146
1147
/*! ------------------------------------------------------------------------------------------------------------------
1148
 * @fn dwt_setlnapamode()
1149
 *
1150
 * @brief This is used to enable GPIO for external LNA or PA functionality - HW dependent, consult the DW1000 User Manual.
1151
 *        This can also be used for debug as enabling TX and RX GPIOs is quite handy to monitor DW1000's activity.
1152
 *
1153
 * NOTE: Enabling PA functionality requires that fine grain TX sequencing is deactivated. This can be done using
1154
 *       dwt_setfinegraintxseq().
1155
 *
1156
 * input parameters
1157
 * @param lna - 1 to enable LNA functionality, 0 to disable it
1158
 * @param pa - 1 to enable PA functionality, 0 to disable it
1159
 *
1160
 * output parameters
1161
 *
1162
 * no return value
1163
 */
1164
void dwt_setlnapamode(int lna, int pa)
1165
{
1166
    uint32_t gpio_mode = dwt_read32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET);
1167
    gpio_mode &= ~(GPIO_MSGP4_MASK | GPIO_MSGP5_MASK | GPIO_MSGP6_MASK);
1168
    if (lna)
1169
    {
1170
        gpio_mode |= GPIO_PIN6_EXTRXE;
1171
    }
1172
    if (pa)
1173
    {
1174
        gpio_mode |= (GPIO_PIN5_EXTTXE | GPIO_PIN4_EXTPA);
1175
    }
1176
    dwt_write32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET, gpio_mode);
1177
}
1178
1179
/*! ------------------------------------------------------------------------------------------------------------------
1180
 * @fn dwt_setgpiodirection()
1181
 *
1182
 * @brief This is used to set GPIO direction as an input (1) or output (0)
1183
 *
1184
 * input parameters
1185
 * @param gpioNum    -   this is the GPIO to configure - see GxM0... GxM8 in the deca_regs.h file
1186
 * @param direction  -   this sets the GPIO direction - see GxP0... GxP8 in the deca_regs.h file
1187
 *
1188
 * output parameters
1189
 *
1190
 * no return value
1191
 */
1192
void dwt_setgpiodirection(uint32_t gpioNum, uint32_t direction)
1193
{
1194
    uint8_t buf[GPIO_DIR_LEN];
1195
    uint32_t command = direction | gpioNum;
1196
1197
    buf[0] = command & 0xff;
1198
    buf[1] = (command >> 8) & 0xff;
1199
    buf[2] = (command >> 16) & 0xff;
1200
1201
    dwt_writetodevice(GPIO_CTRL_ID, GPIO_DIR_OFFSET, GPIO_DIR_LEN, buf);
1202
}
1203
1204
/*! ------------------------------------------------------------------------------------------------------------------
1205
 * @fn dwt_setgpiovalue()
1206
 *
1207
 * @brief This is used to set GPIO value as (1) or (0) only applies if the GPIO is configured as output
1208
 *
1209
 * input parameters
1210
 * @param gpioNum    -   this is the GPIO to configure - see GxM0... GxM8 in the deca_regs.h file
1211
 * @param value  -   this sets the GPIO value - see GDP0... GDP8 in the deca_regs.h file
1212
 *
1213
 * output parameters
1214
 *
1215
 * no return value
1216
 */
1217
void dwt_setgpiovalue(uint32_t gpioNum, uint32_t value)
1218
{
1219
    uint8_t buf[GPIO_DOUT_LEN];
1220
    uint32_t command = value | gpioNum;
1221
1222
    buf[0] = command & 0xff;
1223
    buf[1] = (command >> 8) & 0xff;
1224
    buf[2] = (command >> 16) & 0xff;
1225
1226
    dwt_writetodevice(GPIO_CTRL_ID, GPIO_DOUT_OFFSET, GPIO_DOUT_LEN, buf);
1227
}
1228
1229
/*! ------------------------------------------------------------------------------------------------------------------
1230
 * @fn dwt_getpartid()
1231
 *
1232
 * @brief This is used to return the read part ID of the device
1233
 *
1234
 * NOTE: dwt_initialise() must be called prior to this function so that it can return a relevant value.
1235
 *
1236
 * input parameters
1237
 *
1238
 * output parameters
1239
 *
1240
 * returns the 32 bit part ID value as programmed in the factory
1241
 */
1242
uint32_t dwt_getpartid(void)
1243
{
1244
    return pdw1000local->partID;
1245
}
1246
1247
/*! ------------------------------------------------------------------------------------------------------------------
1248
 * @fn dwt_getlotid()
1249
 *
1250
 * @brief This is used to return the read lot ID of the device
1251
 *
1252
 * NOTE: dwt_initialise() must be called prior to this function so that it can return a relevant value.
1253
 *
1254
 * input parameters
1255
 *
1256
 * output parameters
1257
 *
1258
 * returns the 32 bit lot ID value as programmed in the factory
1259
 */
1260
uint32_t dwt_getlotid(void)
1261
{
1262
    return pdw1000local->lotID;
1263
}
1264
1265
/*! ------------------------------------------------------------------------------------------------------------------
1266
 * @fn dwt_readdevid()
1267
 *
1268
 * @brief This is used to return the read device type and revision information of the DW1000 device (MP part is 0xDECA0130)
1269
 *
1270
 * input parameters
1271
 *
1272
 * output parameters
1273
 *
1274
 * returns the read value which for DW1000 is 0xDECA0130
1275
 */
1276
uint32_t dwt_readdevid(void)
1277
{
1278
    return dwt_read32bitoffsetreg(DEV_ID_ID,0);
1279
}
1280
1281
/*! ------------------------------------------------------------------------------------------------------------------
1282
 * @fn dwt_configuretxrf()
1283
 *
1284
 * @brief This function provides the API for the configuration of the TX spectrum
1285
 * including the power and pulse generator delay. The input is a pointer to the data structure
1286
 * of type dwt_txconfig_t that holds all the configurable items.
1287
 *
1288
 * input parameters
1289
 * @param config    -   pointer to the txrf configuration structure, which contains the tx rf config data
1290
 *
1291
 * output parameters
1292
 *
1293
 * no return value
1294
 */
1295
void dwt_configuretxrf(dwt_txconfig_t* config)
1296
{
1297
1298
    // Configure RF TX PG_DELAY
1299
    dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGDELAY_OFFSET, config->PGdly);
1300
1301
    // Configure TX power
1302
    dwt_write32bitreg(TX_POWER_ID, config->power);
1303
1304
}
1305
1306
/*! ------------------------------------------------------------------------------------------------------------------
1307
 * @fn dwt_configure()
1308
 *
1309
 * @brief This function provides the main API for the configuration of the
1310
 * DW1000 and this low-level driver.  The input is a pointer to the data structure
1311
 * of type dwt_config_t that holds all the configurable items.
1312
 * The dwt_config_t structure shows which ones are supported
1313
 *
1314
 * input parameters
1315
 * @param config    -   pointer to the configuration structure, which contains the device configuration data.
1316
 *
1317
 * output parameters
1318
 *
1319
 * no return value
1320
 */
1321
void dwt_configure(dwt_config_t *config)
1322
{
1323
    uint8_t nsSfd_result  = 0;
1324
    uint8_t useDWnsSFD = 0;
1325
    uint8_t chan = config->chan ;
1326
    uint32_t regval ;
1327
    uint16_t reg16 = lde_replicaCoeff[config->rxCode];
1328
    uint8_t prfIndex = config->prf - DWT_PRF_16M;
1329
    uint8_t bw = ((chan == 4) || (chan == 7)) ? 1 : 0 ; // Select wide or narrow band
1330
1331
#ifdef DWT_API_ERROR_CHECK
1332
    assert(config->dataRate <= DWT_BR_6M8);
1333
    assert(config->rxPAC <= DWT_PAC64);
1334
    assert((chan >= 1) && (chan <= 7) && (chan != 6));
1335
    assert(((config->prf == DWT_PRF_64M) && (config->txCode >= 9) && (config->txCode <= 24))
1336
           || ((config->prf == DWT_PRF_16M) && (config->txCode >= 1) && (config->txCode <= 8)));
1337
    assert(((config->prf == DWT_PRF_64M) && (config->rxCode >= 9) && (config->rxCode <= 24))
1338
           || ((config->prf == DWT_PRF_16M) && (config->rxCode >= 1) && (config->rxCode <= 8)));
1339
    assert((config->txPreambLength == DWT_PLEN_64) || (config->txPreambLength == DWT_PLEN_128) || (config->txPreambLength == DWT_PLEN_256)
1340
           || (config->txPreambLength == DWT_PLEN_512) || (config->txPreambLength == DWT_PLEN_1024) || (config->txPreambLength == DWT_PLEN_1536)
1341
           || (config->txPreambLength == DWT_PLEN_2048) || (config->txPreambLength == DWT_PLEN_4096));
1342
    assert((config->phrMode == DWT_PHRMODE_STD) || (config->phrMode == DWT_PHRMODE_EXT));
1343
#endif
1344
1345
    // For 110 kbps we need a special setup
1346
    if(DWT_BR_110K == config->dataRate)
1347
    {
1348
        pdw1000local->sysCFGreg |= SYS_CFG_RXM110K ;
1349
        reg16 >>= 3; // lde_replicaCoeff must be divided by 8
1350
    }
1351
    else
1352
    {
1353
        pdw1000local->sysCFGreg &= (~SYS_CFG_RXM110K) ;
1354
    }
1355
1356
    pdw1000local->longFrames = config->phrMode ;
1357
1358
    pdw1000local->sysCFGreg &= ~SYS_CFG_PHR_MODE_11;
1359
    pdw1000local->sysCFGreg |= (SYS_CFG_PHR_MODE_11 & (config->phrMode << SYS_CFG_PHR_MODE_SHFT));
1360
1361
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
1362
    // Set the lde_replicaCoeff
1363
    dwt_write16bitoffsetreg(LDE_IF_ID, LDE_REPC_OFFSET, reg16) ;
1364
1365
    _dwt_configlde(prfIndex);
1366
1367
    // Configure PLL2/RF PLL block CFG/TUNE (for a given channel)
1368
    dwt_write32bitoffsetreg(FS_CTRL_ID, FS_PLLCFG_OFFSET, fs_pll_cfg[chan_idx[chan]]);
1369
    dwt_write8bitoffsetreg(FS_CTRL_ID, FS_PLLTUNE_OFFSET, fs_pll_tune[chan_idx[chan]]);
1370
1371
    // Configure RF RX blocks (for specified channel/bandwidth)
1372
    dwt_write8bitoffsetreg(RF_CONF_ID, RF_RXCTRLH_OFFSET, rx_config[bw]);
1373
1374
    // Configure RF TX blocks (for specified channel and PRF)
1375
    // Configure RF TX control
1376
    dwt_write32bitoffsetreg(RF_CONF_ID, RF_TXCTRL_OFFSET, tx_config[chan_idx[chan]]);
1377
1378
    // Configure the baseband parameters (for specified PRF, bit rate, PAC, and SFD settings)
1379
    // DTUNE0
1380
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE0b_OFFSET, sftsh[config->dataRate][config->nsSFD]);
1381
1382
    // DTUNE1
1383
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1a_OFFSET, dtune1[prfIndex]);
1384
1385
    if(config->dataRate == DWT_BR_110K)
1386
    {
1387
        dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_110K);
1388
    }
1389
    else
1390
    {
1391
        if(config->txPreambLength == DWT_PLEN_64)
1392
        {
1393
            dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_6M8_PRE64);
1394
            dwt_write8bitoffsetreg(DRX_CONF_ID, DRX_TUNE4H_OFFSET, DRX_TUNE4H_PRE64);
1395
        }
1396
        else
1397
        {
1398
            dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_850K_6M8);
1399
            dwt_write8bitoffsetreg(DRX_CONF_ID, DRX_TUNE4H_OFFSET, DRX_TUNE4H_PRE128PLUS);
1400
        }
1401
    }
1402
1403
    // DTUNE2
1404
    dwt_write32bitoffsetreg(DRX_CONF_ID, DRX_TUNE2_OFFSET, digital_bb_config[prfIndex][config->rxPAC]);
1405
1406
    // DTUNE3 (SFD timeout)
1407
    // Don't allow 0 - SFD timeout will always be enabled
1408
    if(config->sfdTO == 0)
1409
    {
1410
        config->sfdTO = DWT_SFDTOC_DEF;
1411
    }
1412
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_SFDTOC_OFFSET, config->sfdTO);
1413
1414
    // Configure AGC parameters
1415
    dwt_write32bitoffsetreg( AGC_CFG_STS_ID, 0xC, agc_config.lo32);
1416
    dwt_write16bitoffsetreg( AGC_CFG_STS_ID, 0x4, agc_config.target[prfIndex]);
1417
1418
    // Set (non-standard) user SFD for improved performance,
1419
    if(config->nsSFD)
1420
    {
1421
        // Write non standard (DW) SFD length
1422
        dwt_write8bitoffsetreg(USR_SFD_ID, 0x00, dwnsSFDlen[config->dataRate]);
1423
        nsSfd_result = 3 ;
1424
        useDWnsSFD = 1 ;
1425
    }
1426
    regval =  (CHAN_CTRL_TX_CHAN_MASK & (chan << CHAN_CTRL_TX_CHAN_SHIFT)) | // Transmit Channel
1427
              (CHAN_CTRL_RX_CHAN_MASK & (chan << CHAN_CTRL_RX_CHAN_SHIFT)) | // Receive Channel
1428
              (CHAN_CTRL_RXFPRF_MASK & (config->prf << CHAN_CTRL_RXFPRF_SHIFT)) | // RX PRF
1429
              ((CHAN_CTRL_TNSSFD|CHAN_CTRL_RNSSFD) & (nsSfd_result << CHAN_CTRL_TNSSFD_SHIFT)) | // nsSFD enable RX&TX
1430
              (CHAN_CTRL_DWSFD & (useDWnsSFD << CHAN_CTRL_DWSFD_SHIFT)) | // Use DW nsSFD
1431
              (CHAN_CTRL_TX_PCOD_MASK & (config->txCode << CHAN_CTRL_TX_PCOD_SHIFT)) | // TX Preamble Code
1432
              (CHAN_CTRL_RX_PCOD_MASK & (config->rxCode << CHAN_CTRL_RX_PCOD_SHIFT)) ; // RX Preamble Code
1433
1434
    dwt_write32bitreg(CHAN_CTRL_ID,regval) ;
1435
1436
    // Set up TX Preamble Size, PRF and Data Rate
1437
    pdw1000local->txFCTRL = ((config->txPreambLength | config->prf) << TX_FCTRL_TXPRF_SHFT) | (config->dataRate << TX_FCTRL_TXBR_SHFT);
1438
    dwt_write32bitreg(TX_FCTRL_ID, pdw1000local->txFCTRL);
1439
1440
    // The SFD transmit pattern is initialised by the DW1000 upon a user TX request, but (due to an IC issue) it is not done for an auto-ACK TX. The
1441
    // SYS_CTRL write below works around this issue, by simultaneously initiating and aborting a transmission, which correctly initialises the SFD
1442
    // after its configuration or reconfiguration.
1443
    // This issue is not documented at the time of writing this code. It should be in next release of DW1000 User Manual (v2.09, from July 2016).
1444
    dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, SYS_CTRL_TXSTRT | SYS_CTRL_TRXOFF); // Request TX start and TRX off at the same time
1445
} // end dwt_configure()
1446
1447
/*! ------------------------------------------------------------------------------------------------------------------
1448
 * @fn dwt_setrxantennadelay()
1449
 *
1450
 * @brief This API function writes the antenna delay (in time units) to RX registers
1451
 *
1452
 * input parameters:
1453
 * @param rxDelay - this is the total (RX) antenna delay value, which
1454
 *                          will be programmed into the RX register
1455
 *
1456
 * output parameters
1457
 *
1458
 * no return value
1459
 */
1460
void dwt_setrxantennadelay(uint16_t rxDelay)
1461
{
1462
    // Set the RX antenna delay for auto TX timestamp adjustment
1463
    dwt_write16bitoffsetreg(LDE_IF_ID, LDE_RXANTD_OFFSET, rxDelay);
1464
}
1465
1466
/*! ------------------------------------------------------------------------------------------------------------------
1467
 * @fn dwt_settxantennadelay()
1468
 *
1469
 * @brief This API function writes the antenna delay (in time units) to TX registers
1470
 *
1471
 * input parameters:
1472
 * @param txDelay - this is the total (TX) antenna delay value, which
1473
 *                          will be programmed into the TX delay register
1474
 *
1475
 * output parameters
1476
 *
1477
 * no return value
1478
 */
1479
void dwt_settxantennadelay(uint16_t txDelay)
1480
{
1481
    // Set the TX antenna delay for auto TX timestamp adjustment
1482
    dwt_write16bitoffsetreg(TX_ANTD_ID, TX_ANTD_OFFSET, txDelay);
1483
}
1484
1485
/*! ------------------------------------------------------------------------------------------------------------------
1486
 * @fn dwt_writetxdata()
1487
 *
1488
 * @brief This API function writes the supplied TX data into the DW1000's
1489
 * TX buffer.  The input parameters are the data length in bytes and a pointer
1490
 * to those data bytes.
1491
 *
1492
 * input parameters
1493
 * @param txFrameLength  - This is the total frame length, including the two byte CRC.
1494
 *                         Note: this is the length of TX message (including the 2 byte CRC) - max is 1023
1495
 *                         standard PHR mode allows up to 127 bytes
1496
 *                         if > 127 is programmed, DWT_PHRMODE_EXT needs to be set in the phrMode configuration
1497
 *                         see dwt_configure function
1498
 * @param txFrameBytes   - Pointer to the user’s buffer containing the data to send.
1499
 * @param txBufferOffset - This specifies an offset in the DW1000’s TX Buffer at which to start writing data.
1500
 *
1501
 * output parameters
1502
 *
1503
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
1504
 */
1505
int dwt_writetxdata(uint16_t txFrameLength, uint8_t *txFrameBytes, uint16_t txBufferOffset)
1506
{
1507
#ifdef DWT_API_ERROR_CHECK
1508
    assert(txFrameLength >= 2);
1509
    assert((pdw1000local->longFrames && (txFrameLength <= 1023)) || (txFrameLength <= 127));
1510
    assert((txBufferOffset + txFrameLength) <= 1024);
1511
#endif
1512
1513
    if ((txBufferOffset + txFrameLength) <= 1024)
1514
    {
1515
        // Write the data to the IC TX buffer, (-2 bytes for auto generated CRC)
1516
        dwt_writetodevice( TX_BUFFER_ID, txBufferOffset, txFrameLength-2, txFrameBytes);
1517
        return DWT_SUCCESS;
1518
    }
1519
    else
1520
    {
1521
        return DWT_ERROR;
1522
    }
1523
} // end dwt_writetxdata()
1524
1525
/*! ------------------------------------------------------------------------------------------------------------------
1526
 * @fn dwt_writetxfctrl()
1527
 *
1528
 * @brief This API function configures the TX frame control register before the transmission of a frame
1529
 *
1530
 * input parameters:
1531
 * @param txFrameLength - this is the length of TX message (including the 2 byte CRC) - max is 1023
1532
 *                              NOTE: standard PHR mode allows up to 127 bytes
1533
 *                              if > 127 is programmed, DWT_PHRMODE_EXT needs to be set in the phrMode configuration
1534
 *                              see dwt_configure function
1535
 * @param txBufferOffset - the offset in the tx buffer to start writing the data
1536
 * @param ranging - 1 if this is a ranging frame, else 0
1537
 *
1538
 * output parameters
1539
 *
1540
 * no return value
1541
 */
1542
void dwt_writetxfctrl(uint16_t txFrameLength, uint16_t txBufferOffset, int ranging)
1543
{
1544
1545
#ifdef DWT_API_ERROR_CHECK
1546
    assert((pdw1000local->longFrames && (txFrameLength <= 1023)) || (txFrameLength <= 127));
1547
#endif
1548
1549
    // Write the frame length to the TX frame control register
1550
    // pdw1000local->txFCTRL has kept configured bit rate information
1551
    uint32_t reg32 = pdw1000local->txFCTRL | txFrameLength | (txBufferOffset << TX_FCTRL_TXBOFFS_SHFT) | (ranging << TX_FCTRL_TR_SHFT);
1552
    dwt_write32bitreg(TX_FCTRL_ID, reg32);
1553
} // end dwt_writetxfctrl()
1554
1555
1556
/*! ------------------------------------------------------------------------------------------------------------------
1557
 * @fn dwt_readrxdata()
1558
 *
1559
 * @brief This is used to read the data from the RX buffer, from an offset location give by offset parameter
1560
 *
1561
 * input parameters
1562
 * @param buffer - the buffer into which the data will be read
1563
 * @param length - the length of data to read (in bytes)
1564
 * @param rxBufferOffset - the offset in the rx buffer from which to read the data
1565
 *
1566
 * output parameters
1567
 *
1568
 * no return value
1569
 */
1570
void dwt_readrxdata(uint8_t *buffer, uint16_t length, uint16_t rxBufferOffset)
1571
{
1572
    dwt_readfromdevice(RX_BUFFER_ID,rxBufferOffset,length,buffer) ;
1573
}
1574
1575
/*! ------------------------------------------------------------------------------------------------------------------
1576
 * @fn dwt_readaccdata()
1577
 *
1578
 * @brief This is used to read the data from the Accumulator buffer, from an offset location give by offset parameter
1579
 *
1580
 * NOTE: Because of an internal memory access delay when reading the accumulator the first octet output is a dummy octet
1581
 *       that should be discarded. This is true no matter what sub-index the read begins at.
1582
 *
1583
 * input parameters
1584
 * @param buffer - the buffer into which the data will be read
1585
 * @param length - the length of data to read (in bytes)
1586
 * @param accOffset - the offset in the acc buffer from which to read the data
1587
 *
1588
 * output parameters
1589
 *
1590
 * no return value
1591
 */
1592
void dwt_readaccdata(uint8_t *buffer, uint16_t len, uint16_t accOffset)
1593
{
1594
    // Force on the ACC clocks if we are sequenced
1595
    _dwt_enableclocks(READ_ACC_ON);
1596
1597
    dwt_readfromdevice(ACC_MEM_ID,accOffset,len,buffer) ;
1598
1599
    _dwt_enableclocks(READ_ACC_OFF); // Revert clocks back
1600
}
1601
1602
/*! ------------------------------------------------------------------------------------------------------------------
1603
 * @fn dwt_readdiagnostics()
1604
 *
1605
 * @brief this function reads the RX signal quality diagnostic data
1606
 *
1607
 * input parameters
1608
 * @param diagnostics - diagnostic structure pointer, this will contain the diagnostic data read from the DW1000
1609
 *
1610
 * output parameters
1611
 *
1612
 * no return value
1613
 */
1614
void dwt_readdiagnostics(dwt_rxdiag_t *diagnostics)
1615
{
1616
    // Read the HW FP index
1617
    diagnostics->firstPath = dwt_read16bitoffsetreg(RX_TIME_ID, RX_TIME_FP_INDEX_OFFSET);
1618
1619
    // LDE diagnostic data
1620
    diagnostics->maxNoise = dwt_read16bitoffsetreg(LDE_IF_ID, LDE_THRESH_OFFSET);
1621
1622
    // Read all 8 bytes in one SPI transaction
1623
    dwt_readfromdevice(RX_FQUAL_ID, 0x0, 8, (uint8_t*)&diagnostics->stdNoise);
1624
1625
    diagnostics->firstPathAmp1 = dwt_read16bitoffsetreg(RX_TIME_ID, RX_TIME_FP_AMPL1_OFFSET);
1626
1627
    diagnostics->rxPreamCount = (dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXPACC_MASK) >> RX_FINFO_RXPACC_SHIFT  ;
1628
}
1629
1630
/*! ------------------------------------------------------------------------------------------------------------------
1631
 * @fn dwt_readtxtimestamp()
1632
 *
1633
 * @brief This is used to read the TX timestamp (adjusted with the programmed antenna delay)
1634
 *
1635
 * input parameters
1636
 * @param timestamp - a pointer to a 5-byte buffer which will store the read TX timestamp time
1637
 *
1638
 * output parameters - the timestamp buffer will contain the value after the function call
1639
 *
1640
 * no return value
1641
 */
1642
void dwt_readtxtimestamp(uint8_t * timestamp)
1643
{
1644
    dwt_readfromdevice(TX_TIME_ID, TX_TIME_TX_STAMP_OFFSET, TX_TIME_TX_STAMP_LEN, timestamp) ; // Read bytes directly into buffer
1645
}
1646
1647
/*! ------------------------------------------------------------------------------------------------------------------
1648
 * @fn dwt_readtxtimestamphi32()
1649
 *
1650
 * @brief This is used to read the high 32-bits of the TX timestamp (adjusted with the programmed antenna delay)
1651
 *
1652
 * input parameters
1653
 *
1654
 * output parameters
1655
 *
1656
 * returns high 32-bits of TX timestamp
1657
 */
1658
uint32_t dwt_readtxtimestamphi32(void)
1659
{
1660
    return dwt_read32bitoffsetreg(TX_TIME_ID, 1); // Offset is 1 to get the 4 upper bytes out of 5
1661
}
1662
1663
/*! ------------------------------------------------------------------------------------------------------------------
1664
 * @fn dwt_readtxtimestamplo32()
1665
 *
1666
 * @brief This is used to read the low 32-bits of the TX timestamp (adjusted with the programmed antenna delay)
1667
 *
1668
 * input parameters
1669
 *
1670
 * output parameters
1671
 *
1672
 * returns low 32-bits of TX timestamp
1673
 */
1674
uint32_t dwt_readtxtimestamplo32(void)
1675
{
1676
    return dwt_read32bitreg(TX_TIME_ID); // Read TX TIME as a 32-bit register to get the 4 lower bytes out of 5
1677
}
1678
1679
/*! ------------------------------------------------------------------------------------------------------------------
1680
 * @fn dwt_readrxtimestamp()
1681
 *
1682
 * @brief This is used to read the RX timestamp (adjusted time of arrival)
1683
 *
1684
 * input parameters
1685
 * @param timestamp - a pointer to a 5-byte buffer which will store the read RX timestamp time
1686
 *
1687
 * output parameters - the timestamp buffer will contain the value after the function call
1688
 *
1689
 * no return value
1690
 */
1691
void dwt_readrxtimestamp(uint8_t * timestamp)
1692
{
1693
    dwt_readfromdevice(RX_TIME_ID, RX_TIME_RX_STAMP_OFFSET, RX_TIME_RX_STAMP_LEN, timestamp) ; // Get the adjusted time of arrival
1694
}
1695
1696
/*! ------------------------------------------------------------------------------------------------------------------
1697
 * @fn dwt_readrxtimestamphi32()
1698
 *
1699
 * @brief This is used to read the high 32-bits of the RX timestamp (adjusted with the programmed antenna delay)
1700
 *
1701
 * input parameters
1702
 *
1703
 * output parameters
1704
 *
1705
 * returns high 32-bits of RX timestamp
1706
 */
1707
uint32_t dwt_readrxtimestamphi32(void)
1708
{
1709
    return dwt_read32bitoffsetreg(RX_TIME_ID, 1); // Offset is 1 to get the 4 upper bytes out of 5
1710
}
1711
1712
/*! ------------------------------------------------------------------------------------------------------------------
1713
 * @fn dwt_readrxtimestamplo32()
1714
 *
1715
 * @brief This is used to read the low 32-bits of the RX timestamp (adjusted with the programmed antenna delay)
1716
 *
1717
 * input parameters
1718
 *
1719
 * output parameters
1720
 *
1721
 * returns low 32-bits of RX timestamp
1722
 */
1723
uint32_t dwt_readrxtimestamplo32(void)
1724
{
1725
    return dwt_read32bitreg(RX_TIME_ID); // Read RX TIME as a 32-bit register to get the 4 lower bytes out of 5
1726
}
1727
1728
/*! ------------------------------------------------------------------------------------------------------------------
1729
 * @fn dwt_readsystimestamphi32()
1730
 *
1731
 * @brief This is used to read the high 32-bits of the system time
1732
 *
1733
 * input parameters
1734
 *
1735
 * output parameters
1736
 *
1737
 * returns high 32-bits of system time timestamp
1738
 */
1739
uint32_t dwt_readsystimestamphi32(void)
1740
{
1741
    return dwt_read32bitoffsetreg(SYS_TIME_ID, 1); // Offset is 1 to get the 4 upper bytes out of 5
1742
}
1743
1744
/*! ------------------------------------------------------------------------------------------------------------------
1745
 * @fn dwt_readsystime()
1746
 *
1747
 * @brief This is used to read the system time
1748
 *
1749
 * input parameters
1750
 * @param timestamp - a pointer to a 5-byte buffer which will store the read system time
1751
 *
1752
 * output parameters
1753
 * @param timestamp - the timestamp buffer will contain the value after the function call
1754
 *
1755
 * no return value
1756
 */
1757
void dwt_readsystime(uint8_t * timestamp)
1758
{
1759
    dwt_readfromdevice(SYS_TIME_ID, SYS_TIME_OFFSET, SYS_TIME_LEN, timestamp) ;
1760
}
1761
1762
/*! ------------------------------------------------------------------------------------------------------------------
1763
 * @fn dwt_writetodevice()
1764
 *
1765
 * @brief  this function is used to write to the DW1000 device registers
1766
 * Notes:
1767
 *        1. Firstly we create a header (the first byte is a header byte)
1768
 *        a. check if sub index is used, if subindexing is used - set bit-6 to 1 to signify that the sub-index address follows the register index byte
1769
 *        b. set bit-7 (or with 0x80) for write operation
1770
 *        c. if extended sub address index is used (i.e. if index > 127) set bit-7 of the first sub-index byte following the first header byte
1771
 *
1772
 *        2. Write the header followed by the data bytes to the DW1000 device
1773
 *
1774
 *
1775
 * input parameters:
1776
 * @param recordNumber  - ID of register file or buffer being accessed
1777
 * @param index         - byte index into register file or buffer being accessed
1778
 * @param length        - number of bytes being written
1779
 * @param buffer        - pointer to buffer containing the 'length' bytes to be written
1780
 *
1781
 * output parameters
1782
 *
1783
 * no return value
1784
 */
1785
void dwt_writetodevice
1786
(
1787
    uint16_t      recordNumber,
1788
    uint16_t      index,
1789
    uint32_t      length,
1790
    const uint8_t *buffer
1791
)
1792
{
1793
    uint8_t header[3] ; // Buffer to compose header in
1794
    int   cnt = 0; // Counter for length of header
1795
#ifdef DWT_API_ERROR_CHECK
1796
    assert(recordNumber <= 0x3F); // Record number is limited to 6-bits.
1797
#endif
1798
1799
    // Write message header selecting WRITE operation and addresses as appropriate (this is one to three bytes long)
1800
    if (index == 0) // For index of 0, no sub-index is required
1801
    {
1802
        header[cnt++] = 0x80 | recordNumber ; // Bit-7 is WRITE operation, bit-6 zero=NO sub-addressing, bits 5-0 is reg file id
1803
    }
1804
    else
1805
    {
1806
#ifdef DWT_API_ERROR_CHECK
1807
        assert((index <= 0x7FFF) && ((index + length) <= 0x7FFF)); // Index and sub-addressable area are limited to 15-bits.
1808
#endif
1809
        header[cnt++] = 0xC0 | recordNumber ; // Bit-7 is WRITE operation, bit-6 one=sub-address follows, bits 5-0 is reg file id
1810
1811
        if (index <= 127) // For non-zero index < 127, just a single sub-index byte is required
1812
        {
1813
            header[cnt++] = (uint8_t)index ; // Bit-7 zero means no extension, bits 6-0 is index.
1814
        }
1815
        else
1816
        {
1817
            header[cnt++] = 0x80 | (uint8_t)(index) ; // Bit-7 one means extended index, bits 6-0 is low seven bits of index.
1818
            header[cnt++] =  (uint8_t) (index >> 7) ; // 8-bit value = high eight bits of index.
1819
        }
1820
    }
1821
1822
    // Write it to the SPI
1823
    _alld_dw1000_writespi(cnt,header,length,buffer);
1824
} // end dwt_writetodevice()
1825
1826
/*! ------------------------------------------------------------------------------------------------------------------
1827
 * @fn dwt_readfromdevice()
1828
 *
1829
 * @brief  this function is used to read from the DW1000 device registers
1830
 * Notes:
1831
 *        1. Firstly we create a header (the first byte is a header byte)
1832
 *        a. check if sub index is used, if subindexing is used - set bit-6 to 1 to signify that the sub-index address follows the register index byte
1833
 *        b. set bit-7 (or with 0x80) for write operation
1834
 *        c. if extended sub address index is used (i.e. if index > 127) set bit-7 of the first sub-index byte following the first header byte
1835
 *
1836
 *        2. Write the header followed by the data bytes to the DW1000 device
1837
 *        3. Store the read data in the input buffer
1838
 *
1839
 * input parameters:
1840
 * @param recordNumber  - ID of register file or buffer being accessed
1841
 * @param index         - byte index into register file or buffer being accessed
1842
 * @param length        - number of bytes being read
1843
 * @param buffer        - pointer to buffer in which to return the read data.
1844
 *
1845
 * output parameters
1846
 *
1847
 * no return value
1848
 */
1849
void dwt_readfromdevice
1850
(
1851
    uint16_t  recordNumber,
1852
    uint16_t  index,
1853
    uint32_t  length,
1854
    uint8_t   *buffer
1855
)
1856
{
1857
    uint8_t header[3] ; // Buffer to compose header in
1858
    int   cnt = 0; // Counter for length of header
1859
#ifdef DWT_API_ERROR_CHECK
1860
    assert(recordNumber <= 0x3F); // Record number is limited to 6-bits.
1861
#endif
1862
1863
    // Write message header selecting READ operation and addresses as appropriate (this is one to three bytes long)
1864
    if (index == 0) // For index of 0, no sub-index is required
1865
    {
1866
        header[cnt++] = (uint8_t) recordNumber ; // Bit-7 zero is READ operation, bit-6 zero=NO sub-addressing, bits 5-0 is reg file id
1867
    }
1868
    else
1869
    {
1870
#ifdef DWT_API_ERROR_CHECK
1871
        assert((index <= 0x7FFF) && ((index + length) <= 0x7FFF)); // Index and sub-addressable area are limited to 15-bits.
1872
#endif
1873
        header[cnt++] = (uint8_t)(0x40 | recordNumber) ; // Bit-7 zero is READ operation, bit-6 one=sub-address follows, bits 5-0 is reg file id
1874
1875
        if (index <= 127) // For non-zero index < 127, just a single sub-index byte is required
1876
        {
1877
            header[cnt++] = (uint8_t) index ; // Bit-7 zero means no extension, bits 6-0 is index.
1878
        }
1879
        else
1880
        {
1881
            header[cnt++] = 0x80 | (uint8_t)(index) ; // Bit-7 one means extended index, bits 6-0 is low seven bits of index.
1882
            header[cnt++] =  (uint8_t) (index >> 7) ; // 8-bit value = high eight bits of index.
1883
        }
1884
    }
1885
1886
    // Do the read from the SPI
1887
    _alld_dw1000_readspi(cnt, header, length, buffer);  // result is stored in the buffer
1888
} // end dwt_readfromdevice()
1889
1890
1891
1892
/*! ------------------------------------------------------------------------------------------------------------------
1893
 * @fn dwt_read32bitoffsetreg()
1894
 *
1895
 * @brief  this function is used to read 32-bit value from the DW1000 device registers
1896
 *
1897
 * input parameters:
1898
 * @param regFileID - ID of register file or buffer being accessed
1899
 * @param regOffset - the index into register file or buffer being accessed
1900
 *
1901
 * output parameters
1902
 *
1903
 * returns 32 bit register value
1904
 */
1905
uint32_t dwt_read32bitoffsetreg(int regFileID,int regOffset)
1906
{
1907
    uint32_t  regval = 0 ;
1908
    int     j ;
1909
    uint8_t   buffer[4] ;
1910
1911
    dwt_readfromdevice(regFileID,regOffset,4,buffer); // Read 4 bytes (32-bits) register into buffer
1912
1913
    for (j = 3 ; j >= 0 ; j --)
1914
    {
1915
        regval = (regval << 8) + buffer[j] ;
1916
    }
1917
    return regval ;
1918
1919
} // end dwt_read32bitoffsetreg()
1920
1921
/*! ------------------------------------------------------------------------------------------------------------------
1922
 * @fn dwt_read16bitoffsetreg()
1923
 *
1924
 * @brief  this function is used to read 16-bit value from the DW1000 device registers
1925
 *
1926
 * input parameters:
1927
 * @param regFileID - ID of register file or buffer being accessed
1928
 * @param regOffset - the index into register file or buffer being accessed
1929
 *
1930
 * output parameters
1931
 *
1932
 * returns 16 bit register value
1933
 */
1934
uint16_t dwt_read16bitoffsetreg(int regFileID,int regOffset)
1935
{
1936
    uint16_t  regval = 0 ;
1937
    uint8_t   buffer[2] ;
1938
1939
    dwt_readfromdevice(regFileID,regOffset,2,buffer); // Read 2 bytes (16-bits) register into buffer
1940
1941
    regval = (buffer[1] << 8) + buffer[0] ;
1942
    return regval ;
1943
1944
} // end dwt_read16bitoffsetreg()
1945
1946
/*! ------------------------------------------------------------------------------------------------------------------
1947
 * @fn dwt_read8bitoffsetreg()
1948
 *
1949
 * @brief  this function is used to read an 8-bit value from the DW1000 device registers
1950
 *
1951
 * input parameters:
1952
 * @param regFileID - ID of register file or buffer being accessed
1953
 * @param regOffset - the index into register file or buffer being accessed
1954
 *
1955
 * output parameters
1956
 *
1957
 * returns 8-bit register value
1958
 */
1959
uint8_t dwt_read8bitoffsetreg(int regFileID, int regOffset)
1960
{
1961
    uint8_t regval;
1962
1963
    dwt_readfromdevice(regFileID, regOffset, 1, &regval);
1964
1965
    return regval ;
1966
}
1967
1968
/*! ------------------------------------------------------------------------------------------------------------------
1969
 * @fn dwt_write8bitoffsetreg()
1970
 *
1971
 * @brief  this function is used to write an 8-bit value to the DW1000 device registers
1972
 *
1973
 * input parameters:
1974
 * @param regFileID - ID of register file or buffer being accessed
1975
 * @param regOffset - the index into register file or buffer being accessed
1976
 * @param regval    - the value to write
1977
 *
1978
 * output parameters
1979
 *
1980
 * no return value
1981
 */
1982
void dwt_write8bitoffsetreg(int regFileID, int regOffset, uint8_t regval)
1983
{
1984
    dwt_writetodevice(regFileID, regOffset, 1, &regval);
1985
}
1986
1987
/*! ------------------------------------------------------------------------------------------------------------------
1988
 * @fn dwt_write16bitoffsetreg()
1989
 *
1990
 * @brief  this function is used to write 16-bit value to the DW1000 device registers
1991
 *
1992
 * input parameters:
1993
 * @param regFileID - ID of register file or buffer being accessed
1994
 * @param regOffset - the index into register file or buffer being accessed
1995
 * @param regval    - the value to write
1996
 *
1997
 * output parameters
1998
 *
1999
 * no return value
2000
 */
2001
void dwt_write16bitoffsetreg(int regFileID,int regOffset,uint16_t regval)
2002
{
2003
    uint8_t   buffer[2] ;
2004
2005
    buffer[0] = regval & 0xFF;
2006
    buffer[1] = regval >> 8 ;
2007
2008
    dwt_writetodevice(regFileID,regOffset,2,buffer);
2009
} // end dwt_write16bitoffsetreg()
2010
2011
/*! ------------------------------------------------------------------------------------------------------------------
2012
 * @fn dwt_write32bitoffsetreg()
2013
 *
2014
 * @brief  this function is used to write 32-bit value to the DW1000 device registers
2015
 *
2016
 * input parameters:
2017
 * @param regFileID - ID of register file or buffer being accessed
2018
 * @param regOffset - the index into register file or buffer being accessed
2019
 * @param regval    - the value to write
2020
 *
2021
 * output parameters
2022
 *
2023
 * no return value
2024
 */
2025
void dwt_write32bitoffsetreg(int regFileID,int regOffset,uint32_t regval)
2026
{
2027
    int     j ;
2028
    uint8_t   buffer[4] ;
2029
2030
    for ( j = 0 ; j < 4 ; j++ )
2031
    {
2032
        buffer[j] = regval & 0xff ;
2033
        regval >>= 8 ;
2034
    }
2035
2036
    dwt_writetodevice(regFileID,regOffset,4,buffer);
2037
} // end dwt_write32bitoffsetreg()
2038
2039
/*! ------------------------------------------------------------------------------------------------------------------
2040
 * @fn dwt_enableframefilter()
2041
 *
2042
 * @brief This is used to enable the frame filtering - (the default option is to
2043
 * accept any data and ACK frames with correct destination address
2044
 *
2045
 * input parameters
2046
 * @param - bitmask - enables/disables the frame filtering options according to
2047
 *      DWT_FF_NOTYPE_EN        0x000   no frame types allowed
2048
 *      DWT_FF_COORD_EN         0x002   behave as coordinator (can receive frames with no destination address (PAN ID has to match))
2049
 *      DWT_FF_BEACON_EN        0x004   beacon frames allowed
2050
 *      DWT_FF_DATA_EN          0x008   data frames allowed
2051
 *      DWT_FF_ACK_EN           0x010   ack frames allowed
2052
 *      DWT_FF_MAC_EN           0x020   mac control frames allowed
2053
 *      DWT_FF_RSVD_EN          0x040   reserved frame types allowed
2054
 *
2055
 * output parameters
2056
 *
2057
 * no return value
2058
 */
2059
void dwt_enableframefilter(uint16_t enable)
2060
{
2061
    uint32_t sysconfig = SYS_CFG_MASK & dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
2062
2063
    if(enable)
2064
    {
2065
        // Enable frame filtering and configure frame types
2066
        sysconfig &= ~(SYS_CFG_FF_ALL_EN); // Clear all
2067
        sysconfig |= (enable & SYS_CFG_FF_ALL_EN) | SYS_CFG_FFE;
2068
    }
2069
    else
2070
    {
2071
        sysconfig &= ~(SYS_CFG_FFE);
2072
    }
2073
2074
    pdw1000local->sysCFGreg = sysconfig ;
2075
    dwt_write32bitreg(SYS_CFG_ID,sysconfig) ;
2076
}
2077
2078
/*! ------------------------------------------------------------------------------------------------------------------
2079
 * @fn dwt_setpanid()
2080
 *
2081
 * @brief This is used to set the PAN ID
2082
 *
2083
 * input parameters
2084
 * @param panID - this is the PAN ID
2085
 *
2086
 * output parameters
2087
 *
2088
 * no return value
2089
 */
2090
void dwt_setpanid(uint16_t panID)
2091
{
2092
    // PAN ID is high 16 bits of register
2093
    dwt_write16bitoffsetreg(PANADR_ID, PANADR_PAN_ID_OFFSET, panID);
2094
}
2095
2096
/*! ------------------------------------------------------------------------------------------------------------------
2097
 * @fn dwt_setaddress16()
2098
 *
2099
 * @brief This is used to set 16-bit (short) address
2100
 *
2101
 * input parameters
2102
 * @param shortAddress - this sets the 16 bit short address
2103
 *
2104
 * output parameters
2105
 *
2106
 * no return value
2107
 */
2108
void dwt_setaddress16(uint16_t shortAddress)
2109
{
2110
    // Short address into low 16 bits
2111
    dwt_write16bitoffsetreg(PANADR_ID, PANADR_SHORT_ADDR_OFFSET, shortAddress);
2112
}
2113
2114
/*! ------------------------------------------------------------------------------------------------------------------
2115
 * @fn dwt_seteui()
2116
 *
2117
 * @brief This is used to set the EUI 64-bit (long) address
2118
 *
2119
 * input parameters
2120
 * @param eui64 - this is the pointer to a buffer that contains the 64bit address
2121
 *
2122
 * output parameters
2123
 *
2124
 * no return value
2125
 */
2126
void dwt_seteui(uint8_t *eui64)
2127
{
2128
    dwt_writetodevice(EUI_64_ID, EUI_64_OFFSET, EUI_64_LEN, eui64);
2129
}
2130
2131
/*! ------------------------------------------------------------------------------------------------------------------
2132
 * @fn dwt_geteui()
2133
 *
2134
 * @brief This is used to get the EUI 64-bit from the DW1000
2135
 *
2136
 * input parameters
2137
 * @param eui64 - this is the pointer to a buffer that will contain the read 64-bit EUI value
2138
 *
2139
 * output parameters
2140
 *
2141
 * no return value
2142
 */
2143
void dwt_geteui(uint8_t *eui64)
2144
{
2145
    dwt_readfromdevice(EUI_64_ID, EUI_64_OFFSET, EUI_64_LEN, eui64);
2146
}
2147
2148
/*! ------------------------------------------------------------------------------------------------------------------
2149
 * @fn dwt_otpread()
2150
 *
2151
 * @brief This is used to read the OTP data from given address into provided array
2152
 *
2153
 * input parameters
2154
 * @param address - this is the OTP address to read from
2155
 * @param array - this is the pointer to the array into which to read the data
2156
 * @param length - this is the number of 32 bit words to read (array needs to be at least this length)
2157
 *
2158
 * output parameters
2159
 *
2160
 * no return value
2161
 */
2162
void dwt_otpread(uint32_t address, uint32_t *array, uint8_t length)
2163
{
2164
    int i;
2165
2166
    _dwt_enableclocks(FORCE_SYS_XTI); // NOTE: Set system clock to XTAL - this is necessary to make sure the values read by _dwt_otpread are reliable
2167
2168
    for(i=0; i<length; i++)
2169
    {
2170
        array[i] = _dwt_otpread(address + i) ;
2171
    }
2172
2173
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Restore system clock to PLL
2174
2175
    return ;
2176
}
2177
2178
/*! ------------------------------------------------------------------------------------------------------------------
2179
 * @fn _dwt_otpread()
2180
 *
2181
 * @brief function to read the OTP memory. Ensure that MR,MRa,MRb are reset to 0.
2182
 *
2183
 * input parameters
2184
 * @param address - address to read at
2185
 *
2186
 * output parameters
2187
 *
2188
 * returns the 32bit of read data
2189
 */
2190
uint32_t _dwt_otpread(uint32_t address)
2191
{
2192
    uint32_t ret_data;
2193
2194
    // Write the address
2195
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_ADDR, address);
2196
2197
    // Perform OTP Read - Manual read mode has to be set
2198
    dwt_write8bitoffsetreg(OTP_IF_ID, OTP_CTRL, OTP_CTRL_OTPREAD | OTP_CTRL_OTPRDEN);
2199
    dwt_write8bitoffsetreg(OTP_IF_ID, OTP_CTRL, 0x00); // OTPREAD is self clearing but OTPRDEN is not
2200
2201
    // Read read data, available 40ns after rising edge of OTP_READ
2202
    ret_data = dwt_read32bitoffsetreg(OTP_IF_ID, OTP_RDAT);
2203
2204
    // Return the 32bit of read data
2205
    return ret_data;
2206
}
2207
2208
/*! ------------------------------------------------------------------------------------------------------------------
2209
 * @fn _dwt_otpsetmrregs()
2210
 *
2211
 * @brief Configure the MR registers for initial programming (enable charge pump).
2212
 * Read margin is used to stress the read back from the
2213
 * programmed bit. In normal operation this is relaxed.
2214
 *
2215
 * input parameters
2216
 * @param mode - "0" : Reset all to 0x0:           MRA=0x0000, MRB=0x0000, MR=0x0000
2217
 *               "1" : Set for inital programming: MRA=0x9220, MRB=0x000E, MR=0x1024
2218
 *               "2" : Set for soak programming:   MRA=0x9220, MRB=0x0003, MR=0x1824
2219
 *               "3" : High Vpp:                   MRA=0x9220, MRB=0x004E, MR=0x1824
2220
 *               "4" : Low Read Margin:            MRA=0x0000, MRB=0x0003, MR=0x0000
2221
 *               "5" : Array Clean:                MRA=0x0049, MRB=0x0003, MR=0x0024
2222
 *               "4" : Very Low Read Margin:       MRA=0x0000, MRB=0x0003, MR=0x0000
2223
 *
2224
 * output parameters
2225
 *
2226
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2227
 */
2228
uint32_t _dwt_otpsetmrregs(int mode)
2229
{
2230
    uint8_t rd_buf[4];
2231
    uint8_t wr_buf[4];
2232
    uint32_t mra=0,mrb=0,mr=0;
2233
2234
    // PROGRAMME MRA
2235
    // Set MRA, MODE_SEL
2236
    wr_buf[0] = 0x03;
2237
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL+1,1,wr_buf);
2238
2239
    // Load data
2240
    switch(mode&0x0f) {
2241
    case 0x0 :
2242
        mr =0x0000;
2243
        mra=0x0000;
2244
        mrb=0x0000;
2245
        break;
2246
    case 0x1 :
2247
        mr =0x1024;
2248
        mra=0x9220; // Enable CPP mon
2249
        mrb=0x000e;
2250
        break;
2251
    case 0x2 :
2252
        mr =0x1824;
2253
        mra=0x9220;
2254
        mrb=0x0003;
2255
        break;
2256
    case 0x3 :
2257
        mr =0x1824;
2258
        mra=0x9220;
2259
        mrb=0x004e;
2260
        break;
2261
    case 0x4 :
2262
        mr =0x0000;
2263
        mra=0x0000;
2264
        mrb=0x0003;
2265
        break;
2266
    case 0x5 :
2267
        mr =0x0024;
2268
        mra=0x0000;
2269
        mrb=0x0003;
2270
        break;
2271
    default :
2272
        return DWT_ERROR;
2273
    }
2274
2275
    wr_buf[0] = mra & 0x00ff;
2276
    wr_buf[1] = (mra & 0xff00)>>8;
2277
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2278
2279
2280
    // Set WRITE_MR
2281
    wr_buf[0] = 0x08;
2282
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2283
2284
    // Wait?
2285
2286
    // Set Clear Mode sel
2287
    wr_buf[0] = 0x02;
2288
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2289
2290
    // Set AUX update, write MR
2291
    wr_buf[0] = 0x88;
2292
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2293
    // Clear write MR
2294
    wr_buf[0] = 0x80;
2295
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2296
    // Clear AUX update
2297
    wr_buf[0] = 0x00;
2298
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2299
2300
    ///////////////////////////////////////////
2301
    // PROGRAM MRB
2302
    // Set SLOW, MRB, MODE_SEL
2303
    wr_buf[0] = 0x05;
2304
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2305
2306
    wr_buf[0] = mrb & 0x00ff;
2307
    wr_buf[1] = (mrb & 0xff00)>>8;
2308
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2309
2310
    // Set WRITE_MR
2311
    wr_buf[0] = 0x08;
2312
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2313
2314
    // Wait?
2315
2316
    // Set Clear Mode sel
2317
    wr_buf[0] = 0x04;
2318
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2319
2320
    // Set AUX update, write MR
2321
    wr_buf[0] = 0x88;
2322
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2323
    // Clear write MR
2324
    wr_buf[0] = 0x80;
2325
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2326
    // Clear AUX update
2327
    wr_buf[0] = 0x00;
2328
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2329
2330
    ///////////////////////////////////////////
2331
    // PROGRAM MR
2332
    // Set SLOW, MODE_SEL
2333
    wr_buf[0] = 0x01;
2334
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2335
    // Load data
2336
2337
    wr_buf[0] = mr & 0x00ff;
2338
    wr_buf[1] = (mr & 0xff00)>>8;
2339
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2340
2341
    // Set WRITE_MR
2342
    wr_buf[0] = 0x08;
2343
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2344
2345
    // Wait?
2346
    deca_sleep(10);
2347
    // Set Clear Mode sel
2348
    wr_buf[0] = 0x00;
2349
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2350
2351
    // Read confirm mode writes.
2352
    // Set man override, MRA_SEL
2353
    wr_buf[0] = OTP_CTRL_OTPRDEN;
2354
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2355
    wr_buf[0] = 0x02;
2356
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2357
    // MRB_SEL
2358
    wr_buf[0] = 0x04;
2359
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2360
    deca_sleep(100);
2361
2362
    // Clear mode sel
2363
    wr_buf[0] = 0x00;
2364
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2365
    // Clear MAN_OVERRIDE
2366
    wr_buf[0] = 0x00;
2367
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2368
2369
    deca_sleep(10);
2370
2371
    if (((mode&0x0f) == 0x1)||((mode&0x0f) == 0x2))
2372
    {
2373
        // Read status register
2374
        dwt_readfromdevice(OTP_IF_ID, OTP_STAT,1,rd_buf);
2375
    }
2376
2377
    return DWT_SUCCESS;
2378
}
2379
2380
/*! ------------------------------------------------------------------------------------------------------------------
2381
 * @fn _dwt_otpprogword32()
2382
 *
2383
 * @brief function to program the OTP memory. Ensure that MR,MRa,MRb are reset to 0.
2384
 * VNM Charge pump needs to be enabled (see _dwt_otpsetmrregs)
2385
 * Note the address is only 11 bits long.
2386
 *
2387
 * input parameters
2388
 * @param address - address to read at
2389
 *
2390
 * output parameters
2391
 *
2392
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2393
 */
2394
uint32_t _dwt_otpprogword32(uint32_t data, uint16_t address)
2395
{
2396
    uint8_t rd_buf[1];
2397
    uint8_t wr_buf[4];
2398
    uint8_t otp_done;
2399
2400
    // Read status register
2401
    dwt_readfromdevice(OTP_IF_ID, OTP_STAT, 1, rd_buf);
2402
2403
    if((rd_buf[0] & 0x02) != 0x02)
2404
    {
2405
        return DWT_ERROR;
2406
    }
2407
2408
    // Write the data
2409
    wr_buf[3] = (data>>24) & 0xff;
2410
    wr_buf[2] = (data>>16) & 0xff;
2411
    wr_buf[1] = (data>>8) & 0xff;
2412
    wr_buf[0] = data & 0xff;
2413
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT, 4, wr_buf);
2414
2415
    // Write the address [10:0]
2416
    wr_buf[1] = (address>>8) & 0x07;
2417
    wr_buf[0] = address & 0xff;
2418
    dwt_writetodevice(OTP_IF_ID, OTP_ADDR, 2, wr_buf);
2419
2420
    // Enable Sequenced programming
2421
    wr_buf[0] = OTP_CTRL_OTPPROG;
2422
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL, 1, wr_buf);
2423
    wr_buf[0] = 0x00; // And clear
2424
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL, 1, wr_buf);
2425
2426
    // WAIT for status to flag PRGM OK..
2427
    otp_done = 0;
2428
    while(otp_done == 0)
2429
    {
2430
        deca_sleep(1);
2431
        dwt_readfromdevice(OTP_IF_ID, OTP_STAT, 1, rd_buf);
2432
2433
        if((rd_buf[0] & 0x01) == 0x01)
2434
        {
2435
            otp_done = 1;
2436
        }
2437
    }
2438
2439
    return DWT_SUCCESS;
2440
}
2441
2442
/*! ------------------------------------------------------------------------------------------------------------------
2443
 * @fn dwt_otpwriteandverify()
2444
 *
2445
 * @brief This is used to program 32-bit value into the DW1000 OTP memory.
2446
 *
2447
 * input parameters
2448
 * @param value - this is the 32-bit value to be programmed into OTP
2449
 * @param address - this is the 16-bit OTP address into which the 32-bit value is programmed
2450
 *
2451
 * output parameters
2452
 *
2453
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2454
 */
2455
int dwt_otpwriteandverify(uint32_t value, uint16_t address)
2456
{
2457
    int prog_ok = DWT_SUCCESS;
2458
    int retry = 0;
2459
    // Firstly set the system clock to crystal
2460
    _dwt_enableclocks(FORCE_SYS_XTI); //set system clock to XTI
2461
2462
    //
2463
    //!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!
2464
    //Set the supply to 3.7V
2465
    //
2466
2467
    _dwt_otpsetmrregs(1); // Set mode for programming
2468
2469
    // For each value to program - the readback/check is done couple of times to verify it has programmed successfully
2470
    while(1)
2471
    {
2472
        _dwt_otpprogword32(value, address);
2473
2474
        if(_dwt_otpread(address) == value)
2475
        {
2476
            break;
2477
        }
2478
        retry++;
2479
        if(retry==5)
2480
        {
2481
            break;
2482
        }
2483
    }
2484
2485
    // Even if the above does not exit before retry reaches 5, the programming has probably been successful
2486
2487
    _dwt_otpsetmrregs(4); // Set mode for reading
2488
2489
    if(_dwt_otpread(address) != value) // If this does not pass please check voltage supply on VDDIO
2490
    {
2491
        prog_ok = DWT_ERROR;
2492
    }
2493
2494
    _dwt_otpsetmrregs(0); // Setting OTP mode register for low RM read - resetting the device would be alternative
2495
2496
    return prog_ok;
2497
}
2498
2499
/*! ------------------------------------------------------------------------------------------------------------------
2500
 * @fn _dwt_aonconfigupload()
2501
 *
2502
 * @brief This function uploads always on (AON) configuration, as set in the AON_CFG0_OFFSET register.
2503
 *
2504
 * input parameters
2505
 *
2506
 * output parameters
2507
 *
2508
 * no return value
2509
 */
2510
void _dwt_aonconfigupload(void)
2511
{
2512
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_UPL_CFG);
2513
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00); // Clear the register
2514
}
2515
2516
/*! ------------------------------------------------------------------------------------------------------------------
2517
 * @fn _dwt_aonarrayupload()
2518
 *
2519
 * @brief This function uploads always on (AON) data array and configuration. Thus if this function is used, then _dwt_aonconfigupload
2520
 * is not necessary. The DW1000 will go so SLEEP straight after this if the DWT_SLP_EN has been set.
2521
 *
2522
 * input parameters
2523
 *
2524
 * output parameters
2525
 *
2526
 * no return value
2527
 */
2528
void _dwt_aonarrayupload(void)
2529
{
2530
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00); // Clear the register
2531
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_SAVE);
2532
}
2533
2534
/*! ------------------------------------------------------------------------------------------------------------------
2535
 * @fn dwt_entersleep()
2536
 *
2537
 * @brief This function puts the device into deep sleep or sleep. dwt_configuresleep() should be called first
2538
 * to configure the sleep and on-wake/wake-up parameters
2539
 *
2540
 * input parameters
2541
 *
2542
 * output parameters
2543
 *
2544
 * no return value
2545
 */
2546
void dwt_entersleep(void)
2547
{
2548
    // Copy config to AON - upload the new configuration
2549
    _dwt_aonarrayupload();
2550
}
2551
2552
/*! ------------------------------------------------------------------------------------------------------------------
2553
 * @fn dwt_configuresleepcnt()
2554
 *
2555
 * @brief sets the sleep counter to new value, this function programs the high 16-bits of the 28-bit counter
2556
 *
2557
 * NOTE: this function needs to be run before dwt_configuresleep, also the SPI frequency has to be < 3MHz
2558
 *
2559
 * input parameters
2560
 * @param sleepcnt - this it value of the sleep counter to program
2561
 *
2562
 * output parameters
2563
 *
2564
 * no return value
2565
 */
2566
void dwt_configuresleepcnt(uint16_t sleepcnt)
2567
{
2568
    // Force system clock to crystal
2569
    _dwt_enableclocks(FORCE_SYS_XTI);
2570
2571
    // Reset sleep configuration to make sure we don't accidentally go to sleep
2572
    dwt_write8bitoffsetreg(AON_ID, AON_CFG0_OFFSET, 0x00); // NB: this write change the default LPCLKDIVA value which is not used anyway.
2573
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, 0x00);
2574
2575
    // Disable the sleep counter
2576
    _dwt_aonconfigupload();
2577
2578
    // Set new value
2579
    dwt_write16bitoffsetreg(AON_ID, AON_CFG0_OFFSET + AON_CFG0_SLEEP_TIM_OFFSET, sleepcnt);
2580
    _dwt_aonconfigupload();
2581
2582
    // Enable the sleep counter
2583
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, AON_CFG1_SLEEP_CEN);
2584
    _dwt_aonconfigupload();
2585
2586
    // Put system PLL back on
2587
    _dwt_enableclocks(ENABLE_ALL_SEQ);
2588
}
2589
2590
2591
/*! ------------------------------------------------------------------------------------------------------------------
2592
 * @fn dwt_calibratesleepcnt()
2593
 *
2594
 * @brief calibrates the local oscillator as its frequency can vary between 7 and 13kHz depending on temp and voltage
2595
 *
2596
 * NOTE: this function needs to be run before dwt_configuresleepcnt, so that we know what the counter units are
2597
 *
2598
 * input parameters
2599
 *
2600
 * output parameters
2601
 *
2602
 * returns the number of XTAL/2 cycles per low-power oscillator cycle. LP OSC frequency = 19.2 MHz/return value
2603
 */
2604
uint16_t dwt_calibratesleepcnt(void)
2605
{
2606
    uint16_t result;
2607
2608
    // Enable calibration of the sleep counter
2609
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, AON_CFG1_LPOSC_CAL);
2610
    _dwt_aonconfigupload();
2611
2612
    // Disable calibration of the sleep counter
2613
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, 0x00);
2614
    _dwt_aonconfigupload();
2615
2616
    // Force system clock to crystal
2617
    _dwt_enableclocks(FORCE_SYS_XTI);
2618
2619
    deca_sleep(1);
2620
2621
    // Read the number of XTAL/2 cycles one LP oscillator cycle took.
2622
    // Set up address - Read upper byte first
2623
    dwt_write8bitoffsetreg(AON_ID, AON_ADDR_OFFSET, AON_ADDR_LPOSC_CAL_1);
2624
2625
    // Enable manual override
2626
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB);
2627
2628
    // Read confirm data that was written
2629
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB | AON_CTRL_DCA_READ);
2630
2631
    // Read back byte from AON
2632
    result = dwt_read8bitoffsetreg(AON_ID, AON_RDAT_OFFSET);
2633
    result <<= 8;
2634
2635
    // Set up address - Read lower byte
2636
    dwt_write8bitoffsetreg(AON_ID, AON_ADDR_OFFSET, AON_ADDR_LPOSC_CAL_0);
2637
2638
    // Enable manual override
2639
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB);
2640
2641
    // Read confirm data that was written
2642
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB | AON_CTRL_DCA_READ);
2643
2644
    // Read back byte from AON
2645
    result |= dwt_read8bitoffsetreg(AON_ID, AON_RDAT_OFFSET);
2646
2647
    // Disable manual override
2648
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00);
2649
2650
    // Put system PLL back on
2651
    _dwt_enableclocks(ENABLE_ALL_SEQ);
2652
2653
    // Returns the number of XTAL/2 cycles per one LP OSC cycle
2654
    // This can be converted into LP OSC frequency by 19.2 MHz/result
2655
    return result;
2656
}
2657
2658
/*! ------------------------------------------------------------------------------------------------------------------
2659
 * @fn dwt_configuresleep()
2660
 *
2661
 * @brief configures the device for both DEEP_SLEEP and SLEEP modes, and on-wake mode
2662
 * i.e. before entering the sleep, the device should be programmed for TX or RX, then upon "waking up" the TX/RX settings
2663
 * will be preserved and the device can immediately perform the desired action TX/RX
2664
 *
2665
 * NOTE: e.g. Tag operation - after deep sleep, the device needs to just load the TX buffer and send the frame
2666
 *
2667
 *
2668
 *      mode: the array and LDE code (OTP/ROM) and LDO tune, and set sleep persist
2669
 *      DWT_PRESRV_SLEEP 0x0100 - preserve sleep
2670
 *      DWT_LOADOPSET    0x0080 - load operating parameter set on wakeup
2671
 *      DWT_CONFIG       0x0040 - download the AON array into the HIF (configuration download)
2672
 *      DWT_LOADEUI      0x0008
2673
 *      DWT_GOTORX       0x0002
2674
 *      DWT_TANDV        0x0001
2675
 *
2676
 *      wake: wake up parameters
2677
 *      DWT_XTAL_EN      0x10 - keep XTAL running during sleep
2678
 *      DWT_WAKE_SLPCNT  0x8 - wake up after sleep count
2679
 *      DWT_WAKE_CS      0x4 - wake up on chip select
2680
 *      DWT_WAKE_WK      0x2 - wake up on WAKEUP PIN
2681
 *      DWT_SLP_EN       0x1 - enable sleep/deep sleep functionality
2682
 *
2683
 * input parameters
2684
 * @param mode - config on-wake parameters
2685
 * @param wake - config wake up parameters
2686
 *
2687
 * output parameters
2688
 *
2689
 * no return value
2690
 */
2691
void dwt_configuresleep(uint16_t mode, uint8_t wake)
2692
{
2693
    // Add predefined sleep settings before writing the mode
2694
    mode |= pdw1000local->sleep_mode;
2695
    dwt_write16bitoffsetreg(AON_ID, AON_WCFG_OFFSET, mode);
2696
2697
    dwt_write8bitoffsetreg(AON_ID, AON_CFG0_OFFSET, wake);
2698
}
2699
2700
/*! ------------------------------------------------------------------------------------------------------------------
2701
 * @fn dwt_entersleepaftertx(int enable)
2702
 *
2703
 * @brief sets the auto TX to sleep bit. This means that after a frame
2704
 * transmission the device will enter deep sleep mode. The dwt_configuresleep() function
2705
 * needs to be called before this to configure the on-wake settings
2706
 *
2707
 * NOTE: the IRQ line has to be low/inactive (i.e. no pending events)
2708
 *
2709
 * input parameters
2710
 * @param enable - 1 to configure the device to enter deep sleep after TX, 0 - disables the configuration
2711
 *
2712
 * output parameters
2713
 *
2714
 * no return value
2715
 */
2716
void dwt_entersleepaftertx(int enable)
2717
{
2718
    uint32_t reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET);
2719
    // Set the auto TX -> sleep bit
2720
    if(enable)
2721
    {
2722
        reg |= PMSC_CTRL1_ATXSLP;
2723
    }
2724
    else
2725
    {
2726
        reg &= ~(PMSC_CTRL1_ATXSLP);
2727
    }
2728
    dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, reg);
2729
}
2730
2731
2732
/*! ------------------------------------------------------------------------------------------------------------------
2733
 * @fn dwt_spicswakeup()
2734
 *
2735
 * @brief wake up the device from sleep mode using the SPI read,
2736
 * the device will wake up on chip select line going low if the line is held low for at least 500us.
2737
 * To define the length depending on the time one wants to hold
2738
 * the chip select line low, use the following formula:
2739
 *
2740
 *      length (bytes) = time (s) * byte_rate (Hz)
2741
 *
2742
 * where fastest byte_rate is spi_rate (Hz) / 8 if the SPI is sending the bytes back-to-back.
2743
 * To save time and power, a system designer could determine byte_rate value more precisely.
2744
 *
2745
 * NOTE: Alternatively the device can be waken up with WAKE_UP pin if configured for that operation
2746
 *
2747
 * input parameters
2748
 * @param buff   - this is a pointer to the dummy buffer which will be used in the SPI read transaction used for the WAKE UP of the device
2749
 * @param length - this is the length of the dummy buffer
2750
 *
2751
 * output parameters
2752
 *
2753
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2754
 */
2755
int dwt_spicswakeup(uint8_t *buff, uint16_t length)
2756
{
2757
    if(dwt_readdevid() != DWT_DEVICE_ID) // Device was in deep sleep (the first read fails)
2758
    {
2759
        // Need to keep chip select line low for at least 500us
2760
        dwt_readfromdevice(0x0, 0x0, length, buff); // Do a long read to wake up the chip (hold the chip select low)
2761
2762
        // Need 5ms for XTAL to start and stabilise (could wait for PLL lock IRQ status bit !!!)
2763
        // NOTE: Polling of the STATUS register is not possible unless frequency is < 3MHz
2764
        deca_sleep(5);
2765
    }
2766
    else
2767
    {
2768
        return DWT_SUCCESS;
2769
    }
2770
    // DEBUG - check if still in sleep mode
2771
    if(dwt_readdevid() != DWT_DEVICE_ID)
2772
    {
2773
        return DWT_ERROR;
2774
    }
2775
2776
    return DWT_SUCCESS;
2777
}
2778
2779
/*! ------------------------------------------------------------------------------------------------------------------
2780
 * @fn _dwt_configlde()
2781
 *
2782
 * @brief configure LDE algorithm parameters
2783
 *
2784
 * input parameters
2785
 * @param prf   -   this is the PRF index (0 or 1) 0 corresponds to 16 and 1 to 64 PRF
2786
 *
2787
 * output parameters
2788
 *
2789
 * no return value
2790
 */
2791
void _dwt_configlde(int prfIndex)
2792
{
2793
    dwt_write8bitoffsetreg(LDE_IF_ID, LDE_CFG1_OFFSET, LDE_PARAM1); // 8-bit configuration register
2794
2795
    if(prfIndex)
2796
    {
2797
        dwt_write16bitoffsetreg( LDE_IF_ID, LDE_CFG2_OFFSET, (uint16_t) LDE_PARAM3_64); // 16-bit LDE configuration tuning register
2798
    }
2799
    else
2800
    {
2801
        dwt_write16bitoffsetreg( LDE_IF_ID, LDE_CFG2_OFFSET, (uint16_t) LDE_PARAM3_16);
2802
    }
2803
}
2804
2805
2806
/*! ------------------------------------------------------------------------------------------------------------------
2807
 * @fn _dwt_loaducodefromrom()
2808
 *
2809
 * @brief  load ucode from OTP MEMORY or ROM
2810
 *
2811
 * input parameters
2812
 *
2813
 * output parameters
2814
 *
2815
 * no return value
2816
 */
2817
void _dwt_loaducodefromrom(void)
2818
{
2819
    // Set up clocks
2820
    _dwt_enableclocks(FORCE_LDE);
2821
2822
    // Kick off the LDE load
2823
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_CTRL, OTP_CTRL_LDELOAD); // Set load LDE kick bit
2824
2825
    deca_sleep(1); // Allow time for code to upload (should take up to 120 us)
2826
2827
    // Default clocks (ENABLE_ALL_SEQ)
2828
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
2829
}
2830
2831
/*! ------------------------------------------------------------------------------------------------------------------
2832
 * @fn dwt_loadopsettabfromotp()
2833
 *
2834
 * @brief This is used to select which Operational Parameter Set table to load from OTP memory
2835
 *
2836
 * input parameters
2837
 * @param ops_sel - Operational Parameter Set table to load:
2838
 *                  DWT_OPSET_64LEN = 0x0 - load the operational parameter set table for 64 length preamble configuration
2839
 *                  DWT_OPSET_TIGHT = 0x1 - load the operational parameter set table for tight xtal offsets (<1ppm)
2840
 *                  DWT_OPSET_DEFLT = 0x2 - load the default operational parameter set table (this is loaded from reset)
2841
 *
2842
 * output parameters
2843
 *
2844
 * no return value
2845
 */
2846
void dwt_loadopsettabfromotp(uint8_t ops_sel)
2847
{
2848
    uint16_t reg = ((ops_sel << OTP_SF_OPS_SEL_SHFT) & OTP_SF_OPS_SEL_MASK) | OTP_SF_OPS_KICK; // Select defined OPS table and trigger its loading
2849
2850
    // Set up clocks
2851
    _dwt_enableclocks(FORCE_LDE);
2852
2853
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_SF, reg);
2854
2855
    // Default clocks (ENABLE_ALL_SEQ)
2856
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
2857
2858
}
2859
2860
/*! ------------------------------------------------------------------------------------------------------------------
2861
 * @fn dwt_setsmarttxpower()
2862
 *
2863
 * @brief This call enables or disables the smart TX power feature.
2864
 *
2865
 * input parameters
2866
 * @param enable - this enables or disables the TX smart power (1 = enable, 0 = disable)
2867
 *
2868
 * output parameters
2869
 *
2870
 * no return value
2871
 */
2872
void dwt_setsmarttxpower(int enable)
2873
{
2874
    // Config system register
2875
    pdw1000local->sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
2876
2877
    // Disable smart power configuration
2878
    if(enable)
2879
    {
2880
        pdw1000local->sysCFGreg &= ~(SYS_CFG_DIS_STXP) ;
2881
    }
2882
    else
2883
    {
2884
        pdw1000local->sysCFGreg |= SYS_CFG_DIS_STXP ;
2885
    }
2886
2887
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2888
}
2889
2890
2891
/*! ------------------------------------------------------------------------------------------------------------------
2892
 * @fn dwt_enableautoack()
2893
 *
2894
 * @brief This call enables the auto-ACK feature. If the responseDelayTime (parameter) is 0, the ACK will be sent a.s.a.p.
2895
 * otherwise it will be sent with a programmed delay (in symbols), max is 255.
2896
 * NOTE: needs to have frame filtering enabled as well
2897
 *
2898
 * input parameters
2899
 * @param responseDelayTime - if non-zero the ACK is sent after this delay, max is 255.
2900
 *
2901
 * output parameters
2902
 *
2903
 * no return value
2904
 */
2905
void dwt_enableautoack(uint8_t responseDelayTime)
2906
{
2907
    // Set auto ACK reply delay
2908
    dwt_write8bitoffsetreg(ACK_RESP_T_ID, ACK_RESP_T_ACK_TIM_OFFSET, responseDelayTime); // In symbols
2909
    // Enable auto ACK
2910
    pdw1000local->sysCFGreg |= SYS_CFG_AUTOACK;
2911
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2912
}
2913
2914
/*! ------------------------------------------------------------------------------------------------------------------
2915
 * @fn dwt_setdblrxbuffmode()
2916
 *
2917
 * @brief This call enables the double receive buffer mode
2918
 *
2919
 * input parameters
2920
 * @param enable - 1 to enable, 0 to disable the double buffer mode
2921
 *
2922
 * output parameters
2923
 *
2924
 * no return value
2925
 */
2926
void dwt_setdblrxbuffmode(int enable)
2927
{
2928
    if(enable)
2929
    {
2930
        // Enable double RX buffer mode
2931
        pdw1000local->sysCFGreg &= ~SYS_CFG_DIS_DRXB;
2932
        pdw1000local->dblbuffon = 1;
2933
    }
2934
    else
2935
    {
2936
        // Disable double RX buffer mode
2937
        pdw1000local->sysCFGreg |= SYS_CFG_DIS_DRXB;
2938
        pdw1000local->dblbuffon = 0;
2939
    }
2940
2941
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2942
}
2943
2944
/*! ------------------------------------------------------------------------------------------------------------------
2945
 * @fn dwt_setrxaftertxdelay()
2946
 *
2947
 * @brief This sets the receiver turn on delay time after a transmission of a frame
2948
 *
2949
 * input parameters
2950
 * @param rxDelayTime - (20 bits) - the delay is in UWB microseconds
2951
 *
2952
 * output parameters
2953
 *
2954
 * no return value
2955
 */
2956
void dwt_setrxaftertxdelay(uint32_t rxDelayTime)
2957
{
2958
    uint32_t val = dwt_read32bitreg(ACK_RESP_T_ID) ; // Read ACK_RESP_T_ID register
2959
2960
    val &= ~(ACK_RESP_T_W4R_TIM_MASK) ; // Clear the timer (19:0)
2961
2962
    val |= (rxDelayTime & ACK_RESP_T_W4R_TIM_MASK) ; // In UWB microseconds (e.g. turn the receiver on 20uus after TX)
2963
2964
    dwt_write32bitreg(ACK_RESP_T_ID, val) ;
2965
}
2966
2967
/*! ------------------------------------------------------------------------------------------------------------------
2968
 * @fn dwt_setcallbacks()
2969
 *
2970
 * @brief This function is used to register the different callbacks called when one of the corresponding event occurs.
2971
 *
2972
 * NOTE: Callbacks can be undefined (set to NULL). In this case, dwt_isr() will process the event as usual but the 'null'
2973
 * callback will not be called.
2974
 *
2975
 * input parameters
2976
 * @param cbTxDone - the pointer to the TX confirmation event callback function
2977
 * @param cbRxOk - the pointer to the RX good frame event callback function
2978
 * @param cbRxTo - the pointer to the RX timeout events callback function
2979
 * @param cbRxErr - the pointer to the RX error events callback function
2980
 *
2981
 * output parameters
2982
 *
2983
 * no return value
2984
 */
2985
void dwt_setcallbacks(dwt_cb_t cbTxDone, dwt_cb_t cbRxOk, dwt_cb_t cbRxTo, dwt_cb_t cbRxErr)
2986
{
2987
    pdw1000local->cbTxDone = cbTxDone;
2988
    pdw1000local->cbRxOk = cbRxOk;
2989
    pdw1000local->cbRxTo = cbRxTo;
2990
    pdw1000local->cbRxErr = cbRxErr;
2991
}
2992
2993
/*! ------------------------------------------------------------------------------------------------------------------
2994
 * @fn dwt_checkirq()
2995
 *
2996
 * @brief This function checks if the IRQ line is active - this is used instead of interrupt handler
2997
 *
2998
 * input parameters
2999
 *
3000
 * output parameters
3001
 *
3002
 * return value is 1 if the IRQS bit is set and 0 otherwise
3003
 */
3004
uint8_t dwt_checkirq(void)
3005
{
3006
    return (dwt_read8bitoffsetreg(SYS_STATUS_ID, SYS_STATUS_OFFSET) & SYS_STATUS_IRQS); // Reading the lower byte only is enough for this operation
3007
}
3008
3009
/*! ------------------------------------------------------------------------------------------------------------------
3010
 * @fn dwt_isr()
3011
 *
3012
 * @brief This is the DW1000's general Interrupt Service Routine. It will process/report the following events:
3013
 *          - RXFCG (through cbRxOk callback)
3014
 *          - TXFRS (through cbTxDone callback)
3015
 *          - RXRFTO/RXPTO (through cbRxTo callback)
3016
 *          - RXPHE/RXFCE/RXRFSL/RXSFDTO/AFFREJ/LDEERR (through cbRxTo cbRxErr)
3017
 *        For all events, corresponding interrupts are cleared and necessary resets are performed. In addition, in the RXFCG case,
3018
 *        received frame information and frame control are read before calling the callback. If double buffering is activated, it
3019
 *        will also toggle between reception buffers once the reception callback processing has ended.
3020
 *
3021
 *        /!\ This version of the ISR supports double buffering but does not support automatic RX re-enabling!
3022
 *
3023
 * NOTE:  In PC based system using (Cheetah or ARM) USB to SPI converter there can be no interrupts, however we still need something
3024
 *        to take the place of it and operate in a polled way. In an embedded system this function should be configured to be triggered
3025
 *        on any of the interrupts described above.
3026

3027
 * input parameters
3028
 *
3029
 * output parameters
3030
 *
3031
 * no return value
3032
 */
3033
void dwt_isr(void)
3034
{
3035
    uint32_t status = pdw1000local->cbData.status = dwt_read32bitreg(SYS_STATUS_ID); // Read status register low 32bits
3036
3037
    // Handle RX good frame event
3038
    if(status & SYS_STATUS_RXFCG)
3039
    {
3040
        uint16_t finfo16;
3041
        uint16_t len;
3042
3043
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_GOOD); // Clear all receive status bits
3044
3045
        pdw1000local->cbData.rx_flags = 0;
3046
3047
        // Read frame info - Only the first two bytes of the register are used here.
3048
        finfo16 = dwt_read16bitoffsetreg(RX_FINFO_ID, RX_FINFO_OFFSET);
3049
3050
        // Report frame length - Standard frame length up to 127, extended frame length up to 1023 bytes
3051
        len = finfo16 & RX_FINFO_RXFL_MASK_1023;
3052
        if(pdw1000local->longFrames == 0)
3053
        {
3054
            len &= RX_FINFO_RXFLEN_MASK;
3055
        }
3056
        pdw1000local->cbData.datalength = len;
3057
3058
        // Report ranging bit
3059
        if(finfo16 & RX_FINFO_RNG)
3060
        {
3061
            pdw1000local->cbData.rx_flags |= DWT_CB_DATA_RX_FLAG_RNG;
3062
        }
3063
3064
        // Report frame control - First bytes of the received frame.
3065
        dwt_readfromdevice(RX_BUFFER_ID, 0, FCTRL_LEN_MAX, pdw1000local->cbData.fctrl);
3066
3067
        // Because of a previous frame not being received properly, AAT bit can be set upon the proper reception of a frame not requesting for
3068
        // acknowledgement (ACK frame is not actually sent though). If the AAT bit is set, check ACK request bit in frame control to confirm (this
3069
        // implementation works only for IEEE802.15.4-2011 compliant frames).
3070
        // This issue is not documented at the time of writing this code. It should be in next release of DW1000 User Manual (v2.09, from July 2016).
3071
        if((status & SYS_STATUS_AAT) && ((pdw1000local->cbData.fctrl[0] & FCTRL_ACK_REQ_MASK) == 0))
3072
        {
3073
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_AAT); // Clear AAT status bit in register
3074
            pdw1000local->cbData.status &= ~SYS_STATUS_AAT; // Clear AAT status bit in callback data register copy
3075
            pdw1000local->wait4resp = 0;
3076
        }
3077
3078
        // Call the corresponding callback if present
3079
        if(pdw1000local->cbRxOk != NULL)
3080
        {
3081
            pdw1000local->cbRxOk(&pdw1000local->cbData);
3082
        }
3083
3084
        if (pdw1000local->dblbuffon)
3085
        {
3086
            // Toggle the Host side Receive Buffer Pointer
3087
            dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_HRBT_OFFSET, 1);
3088
        }
3089
    }
3090
3091
    // Handle TX confirmation event
3092
    if(status & SYS_STATUS_TXFRS)
3093
    {
3094
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_TX); // Clear TX event bits
3095
3096
        // In the case where this TXFRS interrupt is due to the automatic transmission of an ACK solicited by a response (with ACK request bit set)
3097
        // that we receive through using wait4resp to a previous TX (and assuming that the IRQ processing of that TX has already been handled), then
3098
        // we need to handle the IC issue which turns on the RX again in this situation (i.e. because it is wrongly applying the wait4resp after the
3099
        // ACK TX).
3100
        // See section "Transmit and automatically wait for response" in DW1000 User Manual
3101
        if((status & SYS_STATUS_AAT) && pdw1000local->wait4resp)
3102
        {
3103
            dwt_forcetrxoff(); // Turn the RX off
3104
            dwt_rxreset(); // Reset in case we were late and a frame was already being received
3105
        }
3106
3107
        // Call the corresponding callback if present
3108
        if(pdw1000local->cbTxDone != NULL)
3109
        {
3110
            pdw1000local->cbTxDone(&pdw1000local->cbData);
3111
        }
3112
    }
3113
3114
    // Handle frame reception/preamble detect timeout events
3115
    if(status & SYS_STATUS_ALL_RX_TO)
3116
    {
3117
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXRFTO); // Clear RX timeout event bits
3118
3119
        pdw1000local->wait4resp = 0;
3120
3121
        // Because of an issue with receiver restart after error conditions, an RX reset must be applied after any error or timeout event to ensure
3122
        // the next good frame's timestamp is computed correctly.
3123
        // See section "RX Message timestamp" in DW1000 User Manual.
3124
        dwt_forcetrxoff();
3125
        dwt_rxreset();
3126
3127
        // Call the corresponding callback if present
3128
        if(pdw1000local->cbRxTo != NULL)
3129
        {
3130
            pdw1000local->cbRxTo(&pdw1000local->cbData);
3131
        }
3132
    }
3133
3134
    // Handle RX errors events
3135
    if(status & SYS_STATUS_ALL_RX_ERR)
3136
    {
3137
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR); // Clear RX error event bits
3138
3139
        pdw1000local->wait4resp = 0;
3140
3141
        // Because of an issue with receiver restart after error conditions, an RX reset must be applied after any error or timeout event to ensure
3142
        // the next good frame's timestamp is computed correctly.
3143
        // See section "RX Message timestamp" in DW1000 User Manual.
3144
        dwt_forcetrxoff();
3145
        dwt_rxreset();
3146
3147
        // Call the corresponding callback if present
3148
        if(pdw1000local->cbRxErr != NULL)
3149
        {
3150
            pdw1000local->cbRxErr(&pdw1000local->cbData);
3151
        }
3152
    }
3153
}
3154
3155
/*! ------------------------------------------------------------------------------------------------------------------
3156
 * @fn dwt_isr_lplisten()
3157
 *
3158
 * @brief This is the DW1000's Interrupt Service Routine to use when low-power listening scheme is implemented. It will
3159
 *        only process/report the RXFCG event (through cbRxOk callback).
3160
 *        It clears RXFCG interrupt and reads received frame information and frame control before calling the callback.
3161
 *
3162
 *        /!\ This version of the ISR is designed for single buffering case only!
3163
 *
3164
 * input parameters
3165
 *
3166
 * output parameters
3167
 *
3168
 * no return value
3169
 */
3170
void dwt_lowpowerlistenisr(void)
3171
{
3172
    uint32_t status = pdw1000local->cbData.status = dwt_read32bitreg(SYS_STATUS_ID); // Read status register low 32bits
3173
    uint16_t finfo16;
3174
    uint16_t len;
3175
3176
    // The only interrupt handled when in low-power listening mode is RX good frame so proceed directly to the handling of the received frame.
3177
3178
    // Deactivate low-power listening before clearing the interrupt. If not, the DW1000 will go back to sleep as soon as the interrupt is cleared.
3179
    dwt_setlowpowerlistening(0);
3180
3181
    dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_GOOD); // Clear all receive status bits
3182
3183
    pdw1000local->cbData.rx_flags = 0;
3184
3185
    // Read frame info - Only the first two bytes of the register are used here.
3186
    finfo16 = dwt_read16bitoffsetreg(RX_FINFO_ID, 0);
3187
3188
    // Report frame length - Standard frame length up to 127, extended frame length up to 1023 bytes
3189
    len = finfo16 & RX_FINFO_RXFL_MASK_1023;
3190
    if(pdw1000local->longFrames == 0)
3191
    {
3192
        len &= RX_FINFO_RXFLEN_MASK;
3193
    }
3194
    pdw1000local->cbData.datalength = len;
3195
3196
    // Report ranging bit
3197
    if(finfo16 & RX_FINFO_RNG)
3198
    {
3199
        pdw1000local->cbData.rx_flags |= DWT_CB_DATA_RX_FLAG_RNG;
3200
    }
3201
3202
    // Report frame control - First bytes of the received frame.
3203
    dwt_readfromdevice(RX_BUFFER_ID, 0, FCTRL_LEN_MAX, pdw1000local->cbData.fctrl);
3204
3205
    // Because of a previous frame not being received properly, AAT bit can be set upon the proper reception of a frame not requesting for
3206
    // acknowledgement (ACK frame is not actually sent though). If the AAT bit is set, check ACK request bit in frame control to confirm (this
3207
    // implementation works only for IEEE802.15.4-2011 compliant frames).
3208
    // This issue is not documented at the time of writing this code. It should be in next release of DW1000 User Manual (v2.09, from July 2016).
3209
    if((status & SYS_STATUS_AAT) && ((pdw1000local->cbData.fctrl[0] & FCTRL_ACK_REQ_MASK) == 0))
3210
    {
3211
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_AAT); // Clear AAT status bit in register
3212
        pdw1000local->cbData.status &= ~SYS_STATUS_AAT; // Clear AAT status bit in callback data register copy
3213
        pdw1000local->wait4resp = 0;
3214
    }
3215
3216
    // Call the corresponding callback if present
3217
    if(pdw1000local->cbRxOk != NULL)
3218
    {
3219
        pdw1000local->cbRxOk(&pdw1000local->cbData);
3220
    }
3221
}
3222
3223
/*! ------------------------------------------------------------------------------------------------------------------
3224
 * @fn dwt_setleds()
3225
 *
3226
 * @brief This is used to set up Tx/Rx GPIOs which could be used to control LEDs
3227
 * Note: not completely IC dependent, also needs board with LEDS fitted on right I/O lines
3228
 *       this function enables GPIOs 2 and 3 which are connected to LED3 and LED4 on EVB1000
3229
 *
3230
 * input parameters
3231
 * @param mode - this is a bit field interpreted as follows:
3232
 *          - bit 0: 1 to enable LEDs, 0 to disable them
3233
 *          - bit 1: 1 to make LEDs blink once on init. Only valid if bit 0 is set (enable LEDs)
3234
 *          - bit 2 to 7: reserved
3235
 *
3236
 * output parameters none
3237
 *
3238
 * no return value
3239
 */
3240
void dwt_setleds(uint8_t mode)
3241
{
3242
    uint32_t reg;
3243
3244
    if (mode & DWT_LEDS_ENABLE)
3245
    {
3246
        // Set up MFIO for LED output.
3247
        reg = dwt_read32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET);
3248
        reg &= ~(GPIO_MSGP2_MASK | GPIO_MSGP3_MASK);
3249
        reg |= (GPIO_PIN2_RXLED | GPIO_PIN3_TXLED);
3250
        dwt_write32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET, reg);
3251
3252
        // Enable LP Oscillator to run from counter and turn on de-bounce clock.
3253
        reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET);
3254
        reg |= (PMSC_CTRL0_GPDCE | PMSC_CTRL0_KHZCLEN);
3255
        dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, reg);
3256
3257
        // Enable LEDs to blink and set default blink time.
3258
        reg = PMSC_LEDC_BLNKEN | PMSC_LEDC_BLINK_TIME_DEF;
3259
        // Make LEDs blink once if requested.
3260
        if (mode & DWT_LEDS_INIT_BLINK)
3261
        {
3262
            reg |= PMSC_LEDC_BLINK_NOW_ALL;
3263
        }
3264
        dwt_write32bitoffsetreg(PMSC_ID, PMSC_LEDC_OFFSET, reg);
3265
        // Clear force blink bits if needed.
3266
        if(mode & DWT_LEDS_INIT_BLINK)
3267
        {
3268
            reg &= ~PMSC_LEDC_BLINK_NOW_ALL;
3269
            dwt_write32bitoffsetreg(PMSC_ID, PMSC_LEDC_OFFSET, reg);
3270
        }
3271
    }
3272
    else
3273
    {
3274
        // Clear the GPIO bits that are used for LED control.
3275
        reg = dwt_read32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET);
3276
        reg &= ~(GPIO_MSGP2_MASK | GPIO_MSGP3_MASK);
3277
        dwt_write32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET, reg);
3278
    }
3279
}
3280
3281
/*! ------------------------------------------------------------------------------------------------------------------
3282
 * @fn _dwt_enableclocks()
3283
 *
3284
 * @brief function to enable/disable clocks to particular digital blocks/system
3285
 *
3286
 * input parameters
3287
 * @param clocks - set of clocks to enable/disable
3288
 *
3289
 * output parameters none
3290
 *
3291
 * no return value
3292
 */
3293
void _dwt_enableclocks(int clocks)
3294
{
3295
    uint8_t reg[2];
3296
3297
    dwt_readfromdevice(PMSC_ID, PMSC_CTRL0_OFFSET, 2, reg);
3298
    switch(clocks)
3299
    {
3300
        case ENABLE_ALL_SEQ:
3301
        {
3302
            reg[0] = 0x00 ;
3303
            reg[1] = reg[1] & 0xfe;
3304
        }
3305
        break;
3306
        case FORCE_SYS_XTI:
3307
        {
3308
            // System and RX
3309
            reg[0] = 0x01 | (reg[0] & 0xfc);
3310
        }
3311
        break;
3312
        case FORCE_SYS_PLL:
3313
        {
3314
            // System
3315
            reg[0] = 0x02 | (reg[0] & 0xfc);
3316
        }
3317
        break;
3318
        case READ_ACC_ON:
3319
        {
3320
            reg[0] = 0x48 | (reg[0] & 0xb3);
3321
            reg[1] = 0x80 | reg[1];
3322
        }
3323
        break;
3324
        case READ_ACC_OFF:
3325
        {
3326
            reg[0] = reg[0] & 0xb3;
3327
            reg[1] = 0x7f & reg[1];
3328
        }
3329
        break;
3330
        case FORCE_OTP_ON:
3331
        {
3332
            reg[1] = 0x02 | reg[1];
3333
        }
3334
        break;
3335
        case FORCE_OTP_OFF:
3336
        {
3337
            reg[1] = reg[1] & 0xfd;
3338
        }
3339
        break;
3340
        case FORCE_TX_PLL:
3341
        {
3342
            reg[0] = 0x20 | (reg[0] & 0xcf);
3343
        }
3344
        break;
3345
        case FORCE_LDE:
3346
        {
3347
            reg[0] = 0x01;
3348
            reg[1] = 0x03;
3349
        }
3350
        break;
3351
        default:
3352
        break;
3353
    }
3354
3355
3356
    // Need to write lower byte separately before setting the higher byte(s)
3357
    dwt_writetodevice(PMSC_ID, PMSC_CTRL0_OFFSET, 1, &reg[0]);
3358
    dwt_writetodevice(PMSC_ID, 0x1, 1, &reg[1]);
3359
3360
} // end _dwt_enableclocks()
3361
3362
/*! ------------------------------------------------------------------------------------------------------------------
3363
 * @fn _dwt_disablesequencing()
3364
 *
3365
 * @brief This function disables the TX blocks sequencing, it disables PMSC control of RF blocks, system clock is also set to XTAL
3366
 *
3367
 * input parameters none
3368
 *
3369
 * output parameters none
3370
 *
3371
 * no return value
3372
 */
3373
void _dwt_disablesequencing(void) // Disable sequencing and go to state "INIT"
3374
{
3375
    _dwt_enableclocks(FORCE_SYS_XTI); // Set system clock to XTI
3376
3377
    dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, PMSC_CTRL1_PKTSEQ_DISABLE); // Disable PMSC ctrl of RF and RX clk blocks
3378
}
3379
3380
/*! ------------------------------------------------------------------------------------------------------------------
3381
 * @fn dwt_setdelayedtrxtime()
3382
 *
3383
 * @brief This API function configures the delayed transmit time or the delayed RX on time
3384
 *
3385
 * input parameters
3386
 * @param starttime - the TX/RX start time (the 32 bits should be the high 32 bits of the system time at which to send the message,
3387
 * or at which to turn on the receiver)
3388
 *
3389
 * output parameters none
3390
 *
3391
 * no return value
3392
 */
3393
void dwt_setdelayedtrxtime(uint32_t starttime)
3394
{
3395
    dwt_write32bitoffsetreg(DX_TIME_ID, 1, starttime); // Write at offset 1 as the lower 9 bits of this register are ignored
3396
3397
} // end dwt_setdelayedtrxtime()
3398
3399
/*! ------------------------------------------------------------------------------------------------------------------
3400
 * @fn dwt_starttx()
3401
 *
3402
 * @brief This call initiates the transmission, input parameter indicates which TX mode is used see below
3403
 *
3404
 * input parameters:
3405
 * @param mode - if 0 immediate TX (no response expected)
3406
 *               if 1 delayed TX (no response expected)
3407
 *               if 2 immediate TX (response expected - so the receiver will be automatically turned on after TX is done)
3408
 *               if 3 delayed TX (response expected - so the receiver will be automatically turned on after TX is done)
3409
 *
3410
 * output parameters
3411
 *
3412
 * returns DWT_SUCCESS for success, or DWT_ERROR for error (e.g. a delayed transmission will fail if the delayed time has passed)
3413
 */
3414
int dwt_starttx(uint8_t mode)
3415
{
3416
    int retval = DWT_SUCCESS ;
3417
    uint8_t temp  = 0x00;
3418
    uint16_t checkTxOK = 0 ;
3419
3420
    if(mode & DWT_RESPONSE_EXPECTED)
3421
    {
3422
        temp = (uint8_t)SYS_CTRL_WAIT4RESP ; // Set wait4response bit
3423
        dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3424
        pdw1000local->wait4resp = 1;
3425
    }
3426
3427
    if (mode & DWT_START_TX_DELAYED)
3428
    {
3429
        // Both SYS_CTRL_TXSTRT and SYS_CTRL_TXDLYS to correctly enable TX
3430
        temp |= (uint8_t)(SYS_CTRL_TXDLYS | SYS_CTRL_TXSTRT) ;
3431
        dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3432
        checkTxOK = dwt_read16bitoffsetreg(SYS_STATUS_ID, 3); // Read at offset 3 to get the upper 2 bytes out of 5
3433
        if ((checkTxOK & SYS_STATUS_TXERR) == 0) // Transmit Delayed Send set over Half a Period away or Power Up error (there is enough time to send but not to power up individual blocks).
3434
        {
3435
            retval = DWT_SUCCESS ; // All okay
3436
        }
3437
        else
3438
        {
3439
            // I am taking DSHP set to Indicate that the TXDLYS was set too late for the specified DX_TIME.
3440
            // Remedial Action - (a) cancel delayed send
3441
            temp = (uint8_t)SYS_CTRL_TRXOFF; // This assumes the bit is in the lowest byte
3442
            dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3443
            // Note event Delayed TX Time too Late
3444
            // Could fall through to start a normal send (below) just sending late.....
3445
            // ... instead return and assume return value of 1 will be used to detect and recover from the issue.
3446
            pdw1000local->wait4resp = 0;
3447
            retval = DWT_ERROR ; // Failed !
3448
        }
3449
    }
3450
    else
3451
    {
3452
        temp |= (uint8_t)SYS_CTRL_TXSTRT ;
3453
        dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3454
    }
3455
3456
    return retval;
3457
3458
} // end dwt_starttx()
3459
3460
/*! ------------------------------------------------------------------------------------------------------------------
3461
 * @fn dwt_forcetrxoff()
3462
 *
3463
 * @brief This is used to turn off the transceiver
3464
 *
3465
 * input parameters
3466
 *
3467
 * output parameters
3468
 *
3469
 * no return value
3470
 */
3471
void dwt_forcetrxoff(void)
3472
{
3473
    decaIrqStatus_t stat ;
3474
    uint32_t mask;
3475
3476
    mask = dwt_read32bitreg(SYS_MASK_ID) ; // Read set interrupt mask
3477
3478
    // Need to beware of interrupts occurring in the middle of following read modify write cycle
3479
    // We can disable the radio, but before the status is cleared an interrupt can be set (e.g. the
3480
    // event has just happened before the radio was disabled)
3481
    // thus we need to disable interrupt during this operation
3482
    stat = decamutexon() ;
3483
3484
    dwt_write32bitreg(SYS_MASK_ID, 0) ; // Clear interrupt mask - so we don't get any unwanted events
3485
3486
    dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, (uint8_t)SYS_CTRL_TRXOFF) ; // Disable the radio
3487
3488
    // Forcing Transceiver off - so we do not want to see any new events that may have happened
3489
    dwt_write32bitreg(SYS_STATUS_ID, (SYS_STATUS_ALL_TX | SYS_STATUS_ALL_RX_ERR | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_GOOD));
3490
3491
    dwt_syncrxbufptrs();
3492
3493
    dwt_write32bitreg(SYS_MASK_ID, mask) ; // Set interrupt mask to what it was
3494
3495
    // Enable/restore interrupts again...
3496
    decamutexoff(stat) ;
3497
    pdw1000local->wait4resp = 0;
3498
3499
} // end deviceforcetrxoff()
3500
3501
/*! ------------------------------------------------------------------------------------------------------------------
3502
 * @fn dwt_syncrxbufptrs()
3503
 *
3504
 * @brief this function synchronizes rx buffer pointers
3505
 * need to make sure that the host/IC buffer pointers are aligned before starting RX
3506
 *
3507
 * input parameters:
3508
 *
3509
 * output parameters
3510
 *
3511
 * no return value
3512
 */
3513
void dwt_syncrxbufptrs(void)
3514
{
3515
    uint8_t  buff ;
3516
    // Need to make sure that the host/IC buffer pointers are aligned before starting RX
3517
    buff = dwt_read8bitoffsetreg(SYS_STATUS_ID, 3); // Read 1 byte at offset 3 to get the 4th byte out of 5
3518
3519
    if((buff & (SYS_STATUS_ICRBP >> 24)) !=     // IC side Receive Buffer Pointer
3520
       ((buff & (SYS_STATUS_HSRBP>>24)) << 1) ) // Host Side Receive Buffer Pointer
3521
    {
3522
        dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_HRBT_OFFSET , 0x01) ; // We need to swap RX buffer status reg (write one to toggle internally)
3523
    }
3524
}
3525
3526
/*! ------------------------------------------------------------------------------------------------------------------
3527
 * @fn dwt_setsniffmode()
3528
 *
3529
 * @brief enable/disable and configure SNIFF mode.
3530
 *
3531
 * SNIFF mode is a low-power reception mode where the receiver is sequenced on and off instead of being on all the time.
3532
 * The time spent in each state (on/off) is specified through the parameters below.
3533
 * See DW1000 User Manual section 4.5 "Low-Power SNIFF mode" for more details.
3534
 *
3535
 * input parameters:
3536
 * @param enable - 1 to enable SNIFF mode, 0 to disable. When 0, all other parameters are not taken into account.
3537
 * @param timeOn - duration of receiver ON phase, expressed in multiples of PAC size. The counter automatically adds 1 PAC
3538
 *                 size to the value set. Min value that can be set is 1 (i.e. an ON time of 2 PAC size), max value is 15.
3539
 * @param timeOff - duration of receiver OFF phase, expressed in multiples of 128/125 µs (~1 µs). Max value is 255.
3540
 *
3541
 * output parameters
3542
 *
3543
 * no return value
3544
 */
3545
void dwt_setsniffmode(int enable, uint8_t timeOn, uint8_t timeOff)
3546
{
3547
    uint32_t pmsc_reg;
3548
    if (enable)
3549
    {
3550
        /* Configure ON/OFF times and enable PLL2 on/off sequencing by SNIFF mode. */
3551
        uint16_t sniff_reg = ((timeOff << 8) | timeOn) & RX_SNIFF_MASK;
3552
        dwt_write16bitoffsetreg(RX_SNIFF_ID, RX_SNIFF_OFFSET, sniff_reg);
3553
        pmsc_reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET);
3554
        pmsc_reg |= PMSC_CTRL0_PLL2_SEQ_EN;
3555
        dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, pmsc_reg);
3556
    }
3557
    else
3558
    {
3559
        /* Clear ON/OFF times and disable PLL2 on/off sequencing by SNIFF mode. */
3560
        dwt_write16bitoffsetreg(RX_SNIFF_ID, RX_SNIFF_OFFSET, 0x0000);
3561
        pmsc_reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET);
3562
        pmsc_reg &= ~PMSC_CTRL0_PLL2_SEQ_EN;
3563
        dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, pmsc_reg);
3564
    }
3565
}
3566
3567
/*! ------------------------------------------------------------------------------------------------------------------
3568
 * @fn dwt_setlowpowerlistening()
3569
 *
3570
 * @brief enable/disable low-power listening mode.
3571
 *
3572
 * Low-power listening is a feature whereby the DW1000 is predominantly in the SLEEP state but wakes periodically, (after
3573
 * this "long sleep"), for a very short time to sample the air for a preamble sequence. This preamble sampling "listening"
3574
 * phase is actually two reception phases separated by a "short sleep" time. See DW1000 User Manual section "Low-Power
3575
 * Listening" for more details.
3576
 *
3577
 * NOTE: Before enabling low-power listening, the following functions have to be called to fully configure it:
3578
 *           - dwt_configuresleep() to configure long sleep phase. "mode" parameter should at least have DWT_PRESRV_SLEEP,
3579
 *             DWT_CONFIG and DWT_RX_EN set and "wake" parameter should at least have both DWT_WAKE_SLPCNT and DWT_SLP_EN set.
3580
 *           - dwt_calibratesleepcnt() and dwt_configuresleepcnt() to define the "long sleep" phase duration.
3581
 *           - dwt_setsnoozetime() to define the "short sleep" phase duration.
3582
 *           - dwt_setpreambledetecttimeout() to define the reception phases duration.
3583
 *           - dwt_setinterrupt() to activate RX good frame interrupt (DWT_INT_RFCG) only.
3584
 *       When configured, low-power listening mode can be triggered either by putting the DW1000 to sleep (using
3585
 *       dwt_entersleep()) or by activating reception (using dwt_rxenable()).
3586
 *
3587
 *       Please refer to the low-power listening examples (examples 8a/8b accompanying the API distribution on Decawave's
3588
 *       website). They form a working example code that shows how to use low-power listening correctly.
3589
 *
3590
 * input parameters:
3591
 * @param enable - 1 to enable low-power listening, 0 to disable.
3592
 *
3593
 * output parameters
3594
 *
3595
 * no return value
3596
 */
3597
void dwt_setlowpowerlistening(int enable)
3598
{
3599
    uint32_t pmsc_reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET);
3600
    if (enable)
3601
    {
3602
        /* Configure RX to sleep and snooze features. */
3603
        pmsc_reg |= (PMSC_CTRL1_ARXSLP | PMSC_CTRL1_SNOZE);
3604
    }
3605
    else
3606
    {
3607
        /* Reset RX to sleep and snooze features. */
3608
        pmsc_reg &= ~(PMSC_CTRL1_ARXSLP | PMSC_CTRL1_SNOZE);
3609
    }
3610
    dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, pmsc_reg);
3611
}
3612
3613
/*! ------------------------------------------------------------------------------------------------------------------
3614
 * @fn dwt_setsnoozetime()
3615
 *
3616
 * @brief Set duration of "short sleep" phase when in low-power listening mode.
3617
 *
3618
 * input parameters:
3619
 * @param snooze_time - "short sleep" phase duration, expressed in multiples of 512/19.2 µs (~26.7 µs). The counter
3620
 *                      automatically adds 1 to the value set. The smallest working value that should be set is 1,
3621
 *                      i.e. giving a snooze time of 2 units (or ~53 µs).
3622
 *
3623
 * output parameters
3624
 *
3625
 * no return value
3626
 */
3627
void dwt_setsnoozetime(uint8_t snooze_time)
3628
{
3629
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_SNOZT_OFFSET, snooze_time);
3630
}
3631
3632
/*! ------------------------------------------------------------------------------------------------------------------
3633
 * @fn dwt_rxenable()
3634
 *
3635
 * @brief This call turns on the receiver, can be immediate or delayed (depending on the mode parameter). In the case of a
3636
 * "late" error the receiver will only be turned on if the DWT_IDLE_ON_DLY_ERR is not set.
3637
 * The receiver will stay turned on, listening to any messages until
3638
 * it either receives a good frame, an error (CRC, PHY header, Reed Solomon) or  it times out (SFD, Preamble or Frame).
3639
 *
3640
 * input parameters
3641
 * @param mode - this can be one of the following allowed values:
3642
 *
3643
 * DWT_START_RX_IMMEDIATE      0 used to enbale receiver immediately
3644
 * DWT_START_RX_DELAYED        1 used to set up delayed RX, if "late" error triggers, then the RX will be enabled immediately
3645
 * (DWT_START_RX_DELAYED | DWT_IDLE_ON_DLY_ERR) 3 used to disable re-enabling of receiver if delayed RX failed due to "late" error
3646
 * (DWT_START_RX_IMMEDIATE | DWT_NO_SYNC_PTRS) 4 used to re-enable RX without trying to sync IC and host side buffer pointers, typically when
3647
 *                                               performing manual RX re-enabling in double buffering mode
3648
 *
3649
 * returns DWT_SUCCESS for success, or DWT_ERROR for error (e.g. a delayed receive enable will be too far in the future if delayed time has passed)
3650
 */
3651
int dwt_rxenable(int mode)
3652
{
3653
    uint16_t temp ;
3654
    uint8_t temp1 ;
3655
3656
    if ((mode & DWT_NO_SYNC_PTRS) == 0)
3657
    {
3658
        dwt_syncrxbufptrs();
3659
    }
3660
3661
    temp = (uint16_t)SYS_CTRL_RXENAB ;
3662
3663
    if (mode & DWT_START_RX_DELAYED)
3664
    {
3665
        temp |= (uint16_t)SYS_CTRL_RXDLYE ;
3666
    }
3667
3668
    dwt_write16bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3669
3670
    if (mode & DWT_START_RX_DELAYED) // check for errors
3671
    {
3672
        temp1 = dwt_read8bitoffsetreg(SYS_STATUS_ID, 3); // Read 1 byte at offset 3 to get the 4th byte out of 5
3673
        if ((temp1 & (SYS_STATUS_HPDWARN >> 24)) != 0) // if delay has passed do immediate RX on unless DWT_IDLE_ON_DLY_ERR is true
3674
        {
3675
            dwt_forcetrxoff(); // turn the delayed receive off
3676
3677
            if((mode & DWT_IDLE_ON_DLY_ERR) == 0) // if DWT_IDLE_ON_DLY_ERR not set then re-enable receiver
3678
            {
3679
                dwt_write16bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, SYS_CTRL_RXENAB);
3680
            }
3681
            return DWT_ERROR; // return warning indication
3682
        }
3683
    }
3684
3685
    return DWT_SUCCESS;
3686
} // end dwt_rxenable()
3687
3688
/*! ------------------------------------------------------------------------------------------------------------------
3689
 * @fn dwt_setrxtimeout()
3690
 *
3691
 * @brief This call enables RX timeout (SY_STAT_RFTO event)
3692
 *
3693
 * input parameters
3694
 * @param time - how long the receiver remains on from the RX enable command
3695
 *               The time parameter used here is in 1.0256 us (512/499.2MHz) units
3696
 *               If set to 0 the timeout is disabled.
3697
 *
3698
 * output parameters
3699
 *
3700
 * no return value
3701
 */
3702
void dwt_setrxtimeout(uint16_t time)
3703
{
3704
    uint8_t temp ;
3705
3706
    temp = dwt_read8bitoffsetreg(SYS_CFG_ID, 3); // Read at offset 3 to get the upper byte only
3707
3708
    if(time > 0)
3709
    {
3710
        dwt_write16bitoffsetreg(RX_FWTO_ID, RX_FWTO_OFFSET, time) ;
3711
3712
        temp |= (uint8_t)(SYS_CFG_RXWTOE>>24); // Shift RXWTOE mask as we read the upper byte only
3713
        // OR in 32bit value (1 bit set), I know this is in high byte.
3714
        pdw1000local->sysCFGreg |= SYS_CFG_RXWTOE;
3715
3716
        dwt_write8bitoffsetreg(SYS_CFG_ID, 3, temp); // Write at offset 3 to write the upper byte only
3717
    }
3718
    else
3719
    {
3720
        temp &= ~((uint8_t)(SYS_CFG_RXWTOE>>24)); // Shift RXWTOE mask as we read the upper byte only
3721
        // AND in inverted 32bit value (1 bit clear), I know this is in high byte.
3722
        pdw1000local->sysCFGreg &= ~(SYS_CFG_RXWTOE);
3723
3724
        dwt_write8bitoffsetreg(SYS_CFG_ID, 3, temp); // Write at offset 3 to write the upper byte only
3725
    }
3726
3727
} // end dwt_setrxtimeout()
3728
3729
3730
/*! ------------------------------------------------------------------------------------------------------------------
3731
 * @fn dwt_setpreambledetecttimeout()
3732
 *
3733
 * @brief This call enables preamble timeout (SY_STAT_RXPTO event)
3734
 *
3735
 * input parameters
3736
 * @param  timeout - Preamble detection timeout, expressed in multiples of PAC size. The counter automatically adds 1 PAC
3737
 *                   size to the value set. Min value that can be set is 1 (i.e. a timeout of 2 PAC size).
3738
 *
3739
 * output parameters
3740
 *
3741
 * no return value
3742
 */
3743
void dwt_setpreambledetecttimeout(uint16_t timeout)
3744
{
3745
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_PRETOC_OFFSET, timeout);
3746
}
3747
3748
/*! ------------------------------------------------------------------------------------------------------------------
3749
 * @fn void dwt_setinterrupt()
3750
 *
3751
 * @brief This function enables the specified events to trigger an interrupt.
3752
 * The following events can be enabled:
3753
 * DWT_INT_TFRS         0x00000080          // frame sent
3754
 * DWT_INT_RFCG         0x00004000          // frame received with good CRC
3755
 * DWT_INT_RPHE         0x00001000          // receiver PHY header error
3756
 * DWT_INT_RFCE         0x00008000          // receiver CRC error
3757
 * DWT_INT_RFSL         0x00010000          // receiver sync loss error
3758
 * DWT_INT_RFTO         0x00020000          // frame wait timeout
3759
 * DWT_INT_RXPTO        0x00200000          // preamble detect timeout
3760
 * DWT_INT_SFDT         0x04000000          // SFD timeout
3761
 * DWT_INT_ARFE         0x20000000          // frame rejected (due to frame filtering configuration)
3762
 *
3763
 *
3764
 * input parameters:
3765
 * @param bitmask - sets the events which will generate interrupt
3766
 * @param enable - if set the interrupts are enabled else they are cleared
3767
 *
3768
 * output parameters
3769
 *
3770
 * no return value
3771
 */
3772
void dwt_setinterrupt(uint32_t bitmask, uint8_t enable)
3773
{
3774
    decaIrqStatus_t stat ;
3775
    uint32_t mask ;
3776
3777
    // Need to beware of interrupts occurring in the middle of following read modify write cycle
3778
    stat = decamutexon() ;
3779
3780
    mask = dwt_read32bitreg(SYS_MASK_ID) ; // Read register
3781
3782
    if(enable)
3783
    {
3784
        mask |= bitmask ;
3785
    }
3786
    else
3787
    {
3788
        mask &= ~bitmask ; // Clear the bit
3789
    }
3790
    dwt_write32bitreg(SYS_MASK_ID,mask) ; // New value
3791
3792
    decamutexoff(stat) ;
3793
}
3794
3795
/*! ------------------------------------------------------------------------------------------------------------------
3796
 * @fn dwt_configeventcounters()
3797
 *
3798
 * @brief This is used to enable/disable the event counter in the IC
3799
 *
3800
 * input parameters
3801
 * @param - enable - 1 enables (and reset), 0 disables the event counters
3802
 * output parameters
3803
 *
3804
 * no return value
3805
 */
3806
void dwt_configeventcounters(int enable)
3807
{
3808
    // Need to clear and disable, can't just clear
3809
    dwt_write8bitoffsetreg(DIG_DIAG_ID, EVC_CTRL_OFFSET, (uint8_t)(EVC_CLR));
3810
3811
    if(enable)
3812
    {
3813
        dwt_write8bitoffsetreg(DIG_DIAG_ID, EVC_CTRL_OFFSET, (uint8_t)(EVC_EN)); // Enable
3814
    }
3815
}
3816
3817
/*! ------------------------------------------------------------------------------------------------------------------
3818
 * @fn dwt_readeventcounters()
3819
 *
3820
 * @brief This is used to read the event counters in the IC
3821
 *
3822
 * input parameters
3823
 * @param counters - pointer to the dwt_deviceentcnts_t structure which will hold the read data
3824
 *
3825
 * output parameters
3826
 *
3827
 * no return value
3828
 */
3829
void dwt_readeventcounters(dwt_deviceentcnts_t *counters)
3830
{
3831
    uint32_t temp;
3832
3833
    temp= dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_PHE_OFFSET); // Read sync loss (31-16), PHE (15-0)
3834
    counters->PHE = temp & 0xFFF;
3835
    counters->RSL = (temp >> 16) & 0xFFF;
3836
3837
    temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_FCG_OFFSET); // Read CRC bad (31-16), CRC good (15-0)
3838
    counters->CRCG = temp & 0xFFF;
3839
    counters->CRCB = (temp >> 16) & 0xFFF;
3840
3841
    temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_FFR_OFFSET); // Overruns (31-16), address errors (15-0)
3842
    counters->ARFE = temp & 0xFFF;
3843
    counters->OVER = (temp >> 16) & 0xFFF;
3844
3845
    temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_STO_OFFSET); // Read PTO (31-16), SFDTO (15-0)
3846
    counters->PTO = (temp >> 16) & 0xFFF;
3847
    counters->SFDTO = temp & 0xFFF;
3848
3849
    temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_FWTO_OFFSET); // Read RX TO (31-16), TXFRAME (15-0)
3850
    counters->TXF = (temp >> 16) & 0xFFF;
3851
    counters->RTO = temp & 0xFFF;
3852
3853
    temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_HPW_OFFSET); // Read half period warning events
3854
    counters->HPW = temp & 0xFFF;
3855
    counters->TXW = (temp >> 16) & 0xFFF;                       // Power-up warning events
3856
3857
}
3858
3859
/*! ------------------------------------------------------------------------------------------------------------------
3860
 * @fn dwt_rxreset()
3861
 *
3862
 * @brief this function resets the receiver of the DW1000
3863
 *
3864
 * input parameters:
3865
 *
3866
 * output parameters
3867
 *
3868
 * no return value
3869
 */
3870
void dwt_rxreset(void)
3871
{
3872
    // Set RX reset
3873
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_SOFTRESET_OFFSET, PMSC_CTRL0_RESET_RX);
3874
3875
    // Clear RX reset
3876
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_SOFTRESET_OFFSET, PMSC_CTRL0_RESET_CLEAR);
3877
}
3878
3879
/*! ------------------------------------------------------------------------------------------------------------------
3880
 * @fn dwt_softreset()
3881
 *
3882
 * @brief this function resets the DW1000
3883
 *
3884
 * input parameters:
3885
 *
3886
 * output parameters
3887
 *
3888
 * no return value
3889
 */
3890
void dwt_softreset(void)
3891
{
3892
    _dwt_disablesequencing();
3893
3894
    // Clear any AON auto download bits (as reset will trigger AON download)
3895
    dwt_write16bitoffsetreg(AON_ID, AON_WCFG_OFFSET, 0x00);
3896
    // Clear the wake-up configuration
3897
    dwt_write8bitoffsetreg(AON_ID, AON_CFG0_OFFSET, 0x00);
3898
    // Upload the new configuration
3899
    _dwt_aonarrayupload();
3900
3901
    // Reset HIF, TX, RX and PMSC
3902
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_SOFTRESET_OFFSET, PMSC_CTRL0_RESET_ALL);
3903
3904
    // DW1000 needs a 10us sleep to let clk PLL lock after reset - the PLL will automatically lock after the reset
3905
    // Could also have polled the PLL lock flag, but then the SPI needs to be < 3MHz !! So a simple delay is easier
3906
    deca_sleep(1);
3907
3908
    // Clear reset
3909
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_SOFTRESET_OFFSET, PMSC_CTRL0_RESET_CLEAR);
3910
3911
    pdw1000local->wait4resp = 0;
3912
}
3913
3914
/*! ------------------------------------------------------------------------------------------------------------------
3915
 * @fn dwt_setxtaltrim()
3916
 *
3917
 * @brief This is used to adjust the crystal frequency
3918
 *
3919
 * input parameters:
3920
 * @param   value - crystal trim value (in range 0x0 to 0x1F) 31 steps (~1.5ppm per step)
3921
 *
3922
 * output parameters
3923
 *
3924
 * no return value
3925
 */
3926
void dwt_setxtaltrim(uint8_t value)
3927
{
3928
    // The 3 MSb in this 8-bit register must be kept to 0b011 to avoid any malfunction.
3929
    uint8_t reg_val = (3 << 5) | (value & FS_XTALT_MASK);
3930
    dwt_write8bitoffsetreg(FS_CTRL_ID, FS_XTALT_OFFSET, reg_val);
3931
}
3932
3933
/*! ------------------------------------------------------------------------------------------------------------------
3934
 * @fn dwt_getinitxtaltrim()
3935
 *
3936
 * @brief This function returns the value of XTAL trim that has been applied during initialisation (dwt_init). This can
3937
 *        be either the value read in OTP memory or a default value.
3938
 *
3939
 * NOTE: The value returned by this function is the initial value only! It is not updated on dwt_setxtaltrim calls.
3940
 *
3941
 * input parameters
3942
 *
3943
 * output parameters
3944
 *
3945
 * returns the XTAL trim value set upon initialisation
3946
 */
3947
uint8_t dwt_getinitxtaltrim(void)
3948
{
3949
    return pdw1000local->init_xtrim;
3950
}
3951
3952
/*! ------------------------------------------------------------------------------------------------------------------
3953
 * @fn dwt_configcwmode()
3954
 *
3955
 * @brief this function sets the DW1000 to transmit cw signal at specific channel frequency
3956
 *
3957
 * input parameters:
3958
 * @param chan - specifies the operating channel (e.g. 1, 2, 3, 4, 5, 6 or 7)
3959
 *
3960
 * output parameters
3961
 *
3962
 * no return value
3963
 */
3964
void dwt_configcwmode(uint8_t chan)
3965
{
3966
#ifdef DWT_API_ERROR_CHECK
3967
    assert((chan >= 1) && (chan <= 7) && (chan != 6));
3968
#endif
3969
3970
    //
3971
    // Disable TX/RX RF block sequencing (needed for cw frame mode)
3972
    //
3973
    _dwt_disablesequencing();
3974
3975
    // Config RF pll (for a given channel)
3976
    // Configure PLL2/RF PLL block CFG/TUNE
3977
    dwt_write32bitoffsetreg(FS_CTRL_ID, FS_PLLCFG_OFFSET, fs_pll_cfg[chan_idx[chan]]);
3978
    dwt_write8bitoffsetreg(FS_CTRL_ID, FS_PLLTUNE_OFFSET, fs_pll_tune[chan_idx[chan]]);
3979
    // PLL wont be enabled until a TX/RX enable is issued later on
3980
    // Configure RF TX blocks (for specified channel and prf)
3981
    // Config RF TX control
3982
    dwt_write32bitoffsetreg(RF_CONF_ID, RF_TXCTRL_OFFSET, tx_config[chan_idx[chan]]);
3983
3984
    //
3985
    // Enable RF PLL
3986
    //
3987
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXPLLPOWEN_MASK); // Enable LDO and RF PLL blocks
3988
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXALLEN_MASK); // Enable the rest of TX blocks
3989
3990
    //
3991
    // Configure TX clocks
3992
    //
3993
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, 0x22);
3994
    dwt_write8bitoffsetreg(PMSC_ID, 0x1, 0x07);
3995
3996
    // Disable fine grain TX sequencing
3997
    dwt_setfinegraintxseq(0);
3998
3999
    // Configure CW mode
4000
    dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGTEST_OFFSET, TC_PGTEST_CW);
4001
}
4002
4003
/*! ------------------------------------------------------------------------------------------------------------------
4004
 * @fn dwt_configcontinuousframemode()
4005
 *
4006
 * @brief this function sets the DW1000 to continuous tx frame mode for regulatory approvals testing.
4007
 *
4008
 * input parameters:
4009
 * @param framerepetitionrate - This is a 32-bit value that is used to set the interval between transmissions.
4010
*  The minimum value is 4. The units are approximately 8 ns. (or more precisely 512/(499.2e6*128) seconds)).
4011
 *
4012
 * output parameters
4013
 *
4014
 * no return value
4015
 */
4016
void dwt_configcontinuousframemode(uint32_t framerepetitionrate)
4017
{
4018
    //
4019
    // Disable TX/RX RF block sequencing (needed for continuous frame mode)
4020
    //
4021
    _dwt_disablesequencing();
4022
4023
    //
4024
    // Enable RF PLL and TX blocks
4025
    //
4026
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXPLLPOWEN_MASK); // Enable LDO and RF PLL blocks
4027
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXALLEN_MASK); // Enable the rest of TX blocks
4028
4029
    //
4030
    // Configure TX clocks
4031
    //
4032
    _dwt_enableclocks(FORCE_SYS_PLL);
4033
    _dwt_enableclocks(FORCE_TX_PLL);
4034
4035
    // Set the frame repetition rate
4036
    if(framerepetitionrate < 4)
4037
    {
4038
        framerepetitionrate = 4;
4039
    }
4040
    dwt_write32bitreg(DX_TIME_ID, framerepetitionrate);
4041
4042
    //
4043
    // Configure continuous frame TX
4044
    //
4045
    dwt_write8bitoffsetreg(DIG_DIAG_ID, DIAG_TMC_OFFSET, (uint8_t)(DIAG_TMC_TX_PSTM)); // Turn the tx power spectrum test mode - continuous sending of frames
4046
}
4047
4048
/*! ------------------------------------------------------------------------------------------------------------------
4049
 * @fn dwt_readtempvbat()
4050
 *
4051
 * @brief this function reads the battery voltage and temperature of the MP
4052
 * The values read here will be the current values sampled by DW1000 AtoD converters.
4053
 * Note on Temperature: the temperature value needs to be converted to give the real temperature
4054
 * the formula is: 1.13 * reading - 113.0
4055
 * Note on Voltage: the voltage value needs to be converted to give the real voltage
4056
 * the formula is: 0.0057 * reading + 2.3
4057
 *
4058
 * NB: To correctly read the temperature this read should be done with xtal clock
4059
 * however that means that the receiver will be switched off, if receiver needs to be on then
4060
 * the timer is used to make sure the value is stable before reading
4061
 *
4062
 * input parameters:
4063
 * @param fastSPI - set to 1 if SPI rate > than 3MHz is used
4064
 *
4065
 * output parameters
4066
 *
4067
 * returns  (temp_raw<<8)|(vbat_raw)
4068
 */
4069
uint16_t dwt_readtempvbat(uint8_t fastSPI)
4070
{
4071
    uint8_t wr_buf[2];
4072
    uint8_t vbat_raw;
4073
    uint8_t temp_raw;
4074
4075
    // These writes should be single writes and in sequence
4076
    wr_buf[0] = 0x80; // Enable TLD Bias
4077
    dwt_writetodevice(RF_CONF_ID,0x11,1,wr_buf);
4078
4079
    wr_buf[0] = 0x0A; // Enable TLD Bias and ADC Bias
4080
    dwt_writetodevice(RF_CONF_ID,0x12,1,wr_buf);
4081
4082
    wr_buf[0] = 0x0f; // Enable Outputs (only after Biases are up and running)
4083
    dwt_writetodevice(RF_CONF_ID,0x12,1,wr_buf);    //
4084
4085
    // Reading All SAR inputs
4086
    wr_buf[0] = 0x00;
4087
    dwt_writetodevice(TX_CAL_ID, TC_SARL_SAR_C,1,wr_buf);
4088
    wr_buf[0] = 0x01; // Set SAR enable
4089
    dwt_writetodevice(TX_CAL_ID, TC_SARL_SAR_C,1,wr_buf);
4090
4091
    if(fastSPI == 1)
4092
    {
4093
        deca_sleep(1); // If using PLL clocks(and fast SPI rate) then this sleep is needed
4094
        // Read voltage and temperature.
4095
        dwt_readfromdevice(TX_CAL_ID, TC_SARL_SAR_LVBAT_OFFSET,2,wr_buf);
4096
    }
4097
    else //change to a slow clock
4098
    {
4099
        _dwt_enableclocks(FORCE_SYS_XTI); // NOTE: set system clock to XTI - this is necessary to make sure the values read are reliable
4100
        // Read voltage and temperature.
4101
        dwt_readfromdevice(TX_CAL_ID, TC_SARL_SAR_LVBAT_OFFSET,2,wr_buf);
4102
        // Default clocks (ENABLE_ALL_SEQ)
4103
        _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
4104
    }
4105
4106
    vbat_raw = wr_buf[0];
4107
    temp_raw = wr_buf[1];
4108
4109
    wr_buf[0] = 0x00; // Clear SAR enable
4110
    dwt_writetodevice(TX_CAL_ID, TC_SARL_SAR_C,1,wr_buf);
4111
4112
    return ((temp_raw<<8)|(vbat_raw));
4113
}
4114
4115
/*! ------------------------------------------------------------------------------------------------------------------
4116
 * @fn dwt_readwakeuptemp()
4117
 *
4118
 * @brief this function reads the temperature of the DW1000 that was sampled
4119
 * on waking from Sleep/Deepsleep. They are not current values, but read on last
4120
 * wakeup if DWT_TANDV bit is set in mode parameter of dwt_configuresleep
4121
 *
4122
 * input parameters:
4123
 *
4124
 * output parameters:
4125
 *
4126
 * returns: 8-bit raw temperature sensor value
4127
 */
4128
uint8_t dwt_readwakeuptemp(void)
4129
{
4130
    return dwt_read8bitoffsetreg(TX_CAL_ID, TC_SARL_SAR_LTEMP_OFFSET);
4131
}
4132
4133
/*! ------------------------------------------------------------------------------------------------------------------
4134
 * @fn dwt_readwakeupvbat()
4135
 *
4136
 * @brief this function reads the battery voltage of the DW1000 that was sampled
4137
 * on waking from Sleep/Deepsleep. They are not current values, but read on last
4138
 * wakeup if DWT_TANDV bit is set in mode parameter of dwt_configuresleep
4139
 *
4140
 * input parameters:
4141
 *
4142
 * output parameters:
4143
 *
4144
 * returns: 8-bit raw battery voltage sensor value
4145
 */
4146
uint8_t dwt_readwakeupvbat(void)
4147
{
4148
    return dwt_read8bitoffsetreg(TX_CAL_ID, TC_SARL_SAR_LVBAT_OFFSET);
4149
}
4150
4151
/*! ------------------------------------------------------------------------------------------------------------------
4152
 * @fn dwt_calcbandwidthtempadj()
4153
 *
4154
 * @brief this function determines the corrected bandwidth setting (PG_DELAY register setting)
4155
 * of the DW1000 which changes over temperature.
4156
 *
4157
 * input parameters:
4158
 * @param target_count - uint16_t - the PG count target to reach in order to correct the bandwidth
4159
 *
4160
 * output parameters:
4161
 *
4162
 * returns: (uint32) The setting to be programmed into the PG_DELAY value
4163
 */
4164
uint32_t dwt_calcbandwidthtempadj(uint16_t target_count)
4165
{
4166
    int i;
4167
    uint32_t bit_field, curr_bw;
4168
    int32_t delta_count = 0;
4169
    uint32_t best_bw = 0;
4170
    uint16_t raw_count = 0;
4171
    int32_t delta_lowest;
4172
4173
    // Used to store the current values of the registers so that they can be restored after
4174
    uint8_t old_pmsc_ctrl0;
4175
    uint16_t old_pmsc_ctrl1;
4176
    uint32_t old_rf_conf_txpow_mask;
4177
4178
    // Record the current values of these registers, to restore later
4179
    old_pmsc_ctrl0 = dwt_read8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET);
4180
    old_pmsc_ctrl1 = dwt_read16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET);
4181
    old_rf_conf_txpow_mask = dwt_read32bitreg(RF_CONF_ID);
4182
4183
    //  Set clock to XTAL
4184
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, PMSC_CTRL0_SYSCLKS_19M);
4185
4186
    //  Disable sequencing
4187
    dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, PMSC_CTRL1_PKTSEQ_DISABLE);
4188
4189
    //  Turn on CLK PLL, Mix Bias and PG
4190
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXPOW_MASK | RF_CONF_PGMIXBIASEN_MASK);
4191
4192
    //  Set sys and TX clock to PLL
4193
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, PMSC_CTRL0_SYSCLKS_125M | PMSC_CTRL0_TXCLKS_125M);
4194
4195
    // Set the MSB high for first guess
4196
    curr_bw = 0x80;
4197
    // Set starting bit
4198
    bit_field = 0x80;
4199
    // Initial lowest delta is the maximum difference that we should allow the count value to be from the target.
4200
    // If the algorithm is successful, it will be overwritten by a smaller value where the count value is closer
4201
    // to the target
4202
    delta_lowest = 300;
4203
4204
    for (i = 0; i < 7; i++)
4205
    {
4206
        // start with 0xc0 and test.
4207
        bit_field = bit_field >> 1;
4208
        curr_bw = curr_bw | bit_field;
4209
4210
        // Write bw setting to PG_DELAY register
4211
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGDELAY_OFFSET, curr_bw);
4212
4213
        // Set cal direction and time
4214
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGCCTRL_OFFSET, TC_PGCCTRL_DIR_CONV | TC_PGCCTRL_TMEAS_MASK);
4215
4216
        // Start cal
4217
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGCCTRL_OFFSET, TC_PGCCTRL_DIR_CONV | TC_PGCCTRL_TMEAS_MASK | TC_PGCCTRL_CALSTART);
4218
        // Allow cal to complete
4219
        deca_sleep(100);
4220
4221
        // Read count value from the PG cal block
4222
        raw_count = dwt_read16bitoffsetreg(TX_CAL_ID, TC_PGCAL_STATUS_OFFSET) & TC_PGCAL_STATUS_DELAY_MASK;
4223
4224
        // lets keep track of the closest value to the target in case we overshoot
4225
        delta_count = abs((int)raw_count - (int)target_count);
4226
        if (delta_count < delta_lowest)
4227
        {
4228
            delta_lowest = delta_count;
4229
            best_bw = curr_bw;
4230
        }
4231
4232
        // Test the count results
4233
        if (raw_count > target_count)
4234
            // Count was lower, BW was lower so increase PG DELAY
4235
            curr_bw = curr_bw | bit_field;
4236
        else
4237
            // Count was higher
4238
            curr_bw = curr_bw & (~(bit_field));
4239
    }
4240
4241
    // Restore old register values
4242
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, old_pmsc_ctrl0);
4243
    dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, old_pmsc_ctrl1);
4244
    dwt_write32bitreg(RF_CONF_ID, old_rf_conf_txpow_mask);
4245
4246
    // Returns the best PG_DELAY setting
4247
    return best_bw;
4248
}
4249
4250
4251
/*! ------------------------------------------------------------------------------------------------------------------
4252
 * @fn _dwt_computetxpowersetting()
4253
 *
4254
 * @brief this function calculates the appropriate change to the TX_POWER register to compensate
4255
 * the TX power output at different temperatures.
4256
 *
4257
 * input parameters:
4258
 * @param ref_powerreg - uint32_t - the TX_POWER register value recorded when reference measurements were made
4259
 * @param power_adj - uint32_t - the adjustment in power level to be made, in 0.5dB steps
4260
 *
4261
 * output parameters:
4262
 *
4263
 * returns: (uint32) The setting to be programmed into the TX_POWER register
4264
 */
4265
uint32_t _dwt_computetxpowersetting(uint32_t ref_powerreg, int32_t power_adj)
4266
{
4267
    int32_t da_attn_change, mixer_gain_change;
4268
    uint8_t current_da_attn, current_mixer_gain;
4269
    uint8_t new_da_attn, new_mixer_gain;
4270
    uint32_t new_regval = 0;
4271
    int i;
4272
4273
    for(i = 0; i < 4; i++)
4274
    {
4275
        da_attn_change = 0;
4276
        mixer_gain_change = power_adj;
4277
        current_da_attn = ((ref_powerreg >> (i*8)) & 0xE0) >> 5;
4278
        current_mixer_gain = (ref_powerreg >> (i*8)) & 0x1F;
4279
4280
        // Mixer gain gives best performance between 4 and 20
4281
        while((current_mixer_gain + mixer_gain_change < 4) ||
4282
              (current_mixer_gain + mixer_gain_change > 20))
4283
        {
4284
            // If mixer gain goes outside bounds, adjust the DA attenuation to compensate
4285
            if(current_mixer_gain + mixer_gain_change > 20)
4286
            {
4287
                da_attn_change += 1;
4288
                mixer_gain_change -= (int) (DA_ATTN_STEP / MIXER_GAIN_STEP);
4289
            }
4290
            else if(current_mixer_gain + mixer_gain_change < 4)
4291
            {
4292
                da_attn_change += 1;
4293
                mixer_gain_change += (int) (DA_ATTN_STEP / MIXER_GAIN_STEP);
4294
            }
4295
        }
4296
4297
        new_da_attn = current_da_attn + da_attn_change;
4298
        new_mixer_gain = current_mixer_gain + mixer_gain_change;
4299
4300
        new_regval |= ((uint32_t) ((new_da_attn << 5) | new_mixer_gain)) << (i * 8);
4301
    }
4302
4303
    return (uint32_t)new_regval;
4304
}
4305
4306
/*! ------------------------------------------------------------------------------------------------------------------
4307
 * @fn dwt_calcpowertempadj()
4308
 *
4309
 * @brief this function determines the corrected power setting (TX_POWER setting) for the
4310
 * DW1000 which changes over temperature.
4311
 *
4312
 * input parameters:
4313
 * @param channel - uint8_t - the channel at which compensation of power level will be applied
4314
 * @param ref_powerreg - uint32_t - the TX_POWER register value recorded when reference measurements were made
4315
 * @param current_temperature - double - the current ambient temperature in degrees Celcius
4316
 * @param reference_temperature - double - the temperature at which reference measurements were made
4317
 * output parameters: None
4318
 *
4319
 * returns: (uint32) The corrected TX_POWER register value
4320
 */
4321
 uint32_t dwt_calcpowertempadj
4322
(
4323
       uint8_t channel,
4324
       uint32_t ref_powerreg,
4325
       double curr_temp,
4326
       double ref_temp
4327
)
4328
{
4329
    double delta_temp;
4330
    double delta_power;
4331
4332
    // Find the temperature differential
4333
    delta_temp = curr_temp - ref_temp;
4334
4335
    // Calculate the expected power differential at the current temperature
4336
    delta_power = delta_temp * txpwr_compensation[chan_idx[channel]];
4337
4338
    // Adjust the TX_POWER register value
4339
    return _dwt_computetxpowersetting(ref_powerreg, (int32_t)(delta_power / MIXER_GAIN_STEP));
4340
}
4341
4342
/*! ------------------------------------------------------------------------------------------------------------------
4343
 * @fn dwt_calcpgcount()
4344
 *
4345
 * @brief this function calculates the value in the pulse generator counter register (PGC_STATUS) for a given PG_DELAY
4346
 * This is used to take a reference measurement, and the value recorded as the reference is used to adjust the
4347
 * bandwidth of the device when the temperature changes.
4348
 *
4349
 * input parameters:
4350
 * @param pgdly - uint8_t - the PG_DELAY to set (to control bandwidth), and to find the corresponding count value for
4351
 * output parameters: None
4352
 *
4353
 * returns: (uint16) PGC_STATUS count value calculated from the provided PG_DELAY value - used as reference for later
4354
 * bandwidth adjustments
4355
 */
4356
uint16_t dwt_calcpgcount(uint8_t pgdly)
4357
{
4358
    // Perform PG count read ten times and take an average to smooth out any noise
4359
    const int NUM_SAMPLES = 10;
4360
    uint32_t sum_count = 0;
4361
    uint16_t average_count = 0, count = 0;
4362
    int i = 0;
4363
4364
    // Used to store the current values of the registers so that they can be restored after
4365
    uint8_t old_pmsc_ctrl0;
4366
    uint16_t old_pmsc_ctrl1;
4367
    uint32_t old_rf_conf_txpow_mask;
4368
4369
    // Record the current values of these registers, to restore later
4370
    old_pmsc_ctrl0 = dwt_read8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET);
4371
    old_pmsc_ctrl1 = dwt_read16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET);
4372
    old_rf_conf_txpow_mask = dwt_read32bitreg(RF_CONF_ID);
4373
4374
    //  Set clock to XTAL
4375
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, PMSC_CTRL0_SYSCLKS_19M);
4376
    //  Disable sequencing
4377
    dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, PMSC_CTRL1_PKTSEQ_DISABLE);
4378
    //  Turn on CLK PLL, Mix Bias and PG
4379
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXPOW_MASK | RF_CONF_PGMIXBIASEN_MASK);
4380
    //  Set sys and TX clock to PLL
4381
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, PMSC_CTRL0_SYSCLKS_125M | PMSC_CTRL0_TXCLKS_125M);
4382
4383
    for(i = 0; i < NUM_SAMPLES; i++) {
4384
        // Write bw setting to PG_DELAY register
4385
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGDELAY_OFFSET, pgdly);
4386
4387
        // Set cal direction and time
4388
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGCCTRL_OFFSET, TC_PGCCTRL_DIR_CONV | TC_PGCCTRL_TMEAS_MASK);
4389
4390
        // Start cal
4391
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGCCTRL_OFFSET, TC_PGCCTRL_DIR_CONV | TC_PGCCTRL_TMEAS_MASK | TC_PGCCTRL_CALSTART);
4392
4393
        // Allow cal to complete - the TC_PGCCTRL_CALSTART bit will clear automatically
4394
        deca_sleep(100);
4395
4396
        // Read count value from the PG cal block
4397
        count = dwt_read16bitoffsetreg(TX_CAL_ID, TC_PGCAL_STATUS_OFFSET) & TC_PGCAL_STATUS_DELAY_MASK;
4398
4399
        sum_count += count;
4400
    }
4401
4402
     // Restore old register values
4403
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, old_pmsc_ctrl0);
4404
    dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, old_pmsc_ctrl1);
4405
    dwt_write32bitreg(RF_CONF_ID, old_rf_conf_txpow_mask);
4406
4407
    average_count = (int)(sum_count / NUM_SAMPLES);
4408
    return average_count;
4409
}
4410
4411
4412
/* ===============================================================================================
4413
   List of expected (known) device ID handled by this software
4414
   ===============================================================================================
4415

4416
    0xDECA0130                               // DW1000 - MP
4417

4418
   ===============================================================================================
4419
*/
4420
4421
/****************************************************************************************************************************************************
4422
 *
4423
 * Declaration of platform-dependent lower level functions.
4424
 *
4425
 ****************************************************************************************************************************************************/
4426
4427
/*
4428
 * DW1000 Hardware dependent functions: SPI, EXTI
4429
 */
4430
4431
4432
/*! ------------------------------------------------------------------------------------------------------------------
4433
 * Function: _alld_dw1000_writespi()
4434
 *
4435
 * Low level abstract function for DW1000 to write to the SPI
4436
 * Takes two separate byte buffers for write header and write data
4437
 * returns 0 for success, or -1 for error
4438
 */
4439
#pragma GCC optimize ("O3")
4440
static int _alld_dw1000_writespi(uint16_t headerLength,
4441
               const        uint8_t *headerBuffer,
4442
               uint32_t bodyLength,
4443
               const        uint8_t *bodyBuffer)
4444
{
4445
4446
    uint8_t buffer[bodyLength + 3];
4447
    memcpy(buffer, headerBuffer, headerLength); //copy data to buffer
4448
    memcpy(&buffer[headerLength], bodyBuffer, bodyLength); //copy data to buffer
4449
4450
    apalSPITransmit(pdw1000local->driver->spid,
4451
                    buffer,
4452
                    bodyLength + headerLength); // send header and data
4453
4454
    return 0;
4455
} // end writetospi()
4456
4457
4458
/*! ------------------------------------------------------------------------------------------------------------------
4459
 * Function: _alld_dw1000_readspi()
4460
 *
4461
 * Low level abstract function for DW1000 to read from the SPI
4462
 * Takes two separate byte buffers for write header and read data
4463
 * returns the offset into read buffer where first byte of read data may be found,
4464
 * or returns -1 if there was an error
4465
 */
4466
#pragma GCC optimize ("O3")
4467
static int _alld_dw1000_readspi(uint16_t headerLength,
4468
                const uint8_t *headerBuffer,
4469
                uint32_t readlength,
4470
                uint8_t *readBuffer)
4471
{
4472
    //uint8_t spi_TmpBuffer[BUFFLEN];
4473
    //assert_param(headerLength+readlength < BUFFLEN );
4474
4475
    apalSPITransmitAndReceive(pdw1000local->driver->spid,
4476
                              headerBuffer,
4477
                              (uint8_t*) readBuffer,
4478
                              headerLength,
4479
                              readlength);
4480
4481
    return 0;
4482
} // end readfromspi()
4483
4484
4485
/****************************************************************************//**
4486
 *
4487
 *         alld_dw1000.c                                        IRQ section
4488
 *
4489
 *******************************************************************************/
4490
4491
4492
/*! ------------------------------------------------------------------------------------------------------------------
4493
 * Function: decamutexon()
4494
 *
4495
 * Description: This function should disable interrupts. This is called at the start of a critical section
4496
 * It returns the irq state before disable, this value is used to re-enable in decamutexoff call
4497
 *
4498
 * Note: The body of this function is platform specific
4499
 *
4500
 * input parameters:        
4501
 *
4502
 * output parameters
4503
 *
4504
 * returns the state of the DW1000 interrupt
4505
 */
4506
decaIrqStatus_t decamutexon(void)           
4507
{
4508
    //decaIrqStatus_t s = port_GetEXT_IRQStatus();
4509
4510
    //if(s) {
4511
                //port_DisableEXT_IRQ(); //disable the external interrupt line
4512
    //}
4513
    //return s ;   // return state before disable, value is used to re-enable in decamutexoff call
4514
4515
    //palDisablePadEvent(DW1000Driver.gpio_exti->port, DW1000Driver.gpio_exti->pad);
4516
    //return 1;
4517
    return 1;
4518
}
4519
4520
/*! ------------------------------------------------------------------------------------------------------------------
4521
 * Function: decamutexoff()
4522
 *
4523
 * Description: This function should re-enable interrupts, or at least restore their state as returned(&saved) by decamutexon 
4524
 * This is called at the end of a critical section
4525
 *
4526
 * Note: The body of this function is platform specific
4527
 *
4528
 * input parameters:        
4529
 * @param s - the state of the DW1000 interrupt as returned by decamutexon
4530
 *
4531
 * output parameters
4532
 *
4533
 * returns the state of the DW1000 interrupt
4534
 */
4535
void decamutexoff(decaIrqStatus_t s)
4536
{
4537
    (void) s;
4538
    //if(s) { //need to check the port state as we can't use level sensitive interrupt on the STM ARM
4539
    //    palEnablePadEvent(DW1000Driver.gpio_exti->port, DW1000Driver.gpio_exti->pad, APAL2CH_EDGE(moduleGpioWlGdo2.meta.edge));
4540
    //        }
4541
    return;
4542
}
4543
4544
4545
/*! Wrapper function to be used by decadriver. Declared in deca_device_api.h 
4546
 *
4547
 */
4548
inline void deca_sleep(unsigned int time_ms)
4549
{
4550
    aosThdMSleep(time_ms);
4551
}
4552
4553
4554
void port_set_dw1000_slowrate(){ // NOT SUPPORTED
4555
    return;
4556
}
4557
4558
void port_set_dw1000_fastrate(){ // NOT SUPPORTED
4559
    return;
4560
}
4561
4562
void port_wakeup_dw1000_fast(){ // NOT SUPPORTED
4563
    return;
4564
}
4565
4566
uint32_t portGetTickCnt(){
4567
    return (uint32_t) chVTGetSystemTimeX();
4568
}
4569
4570
4571
4572
4573
#endif /* defined(AMIROLLD_CFG_USE_DW1000) */