Statistics
| Branch: | Tag: | Revision:

amiro-lld / source / DW1000 / v1 / alld_dw1000_v1.c @ 33f54213

History | View | Annotate | Download (151 KB)

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

3020
 * input parameters
3021
 *
3022
 * output parameters
3023
 *
3024
 * no return value
3025
 */
3026
void dwt_isr(void)
3027
{
3028
    uint32_t status = pdw1000local->cbData.status = dwt_read32bitreg(SYS_STATUS_ID); // Read status register low 32bits
3029
3030
    // Handle RX good frame event
3031
    if(status & SYS_STATUS_RXFCG)
3032
    {
3033
        uint16_t finfo16;
3034
        uint16_t len;
3035
3036
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_GOOD); // Clear all receive status bits
3037
3038
        pdw1000local->cbData.rx_flags = 0;
3039
3040
        // Read frame info - Only the first two bytes of the register are used here.
3041
        finfo16 = dwt_read16bitoffsetreg(RX_FINFO_ID, RX_FINFO_OFFSET);
3042
3043
        // Report frame length - Standard frame length up to 127, extended frame length up to 1023 bytes
3044
        len = finfo16 & RX_FINFO_RXFL_MASK_1023;
3045
        if(pdw1000local->longFrames == 0)
3046
        {
3047
            len &= RX_FINFO_RXFLEN_MASK;
3048
        }
3049
        pdw1000local->cbData.datalength = len;
3050
3051
        // Report ranging bit
3052
        if(finfo16 & RX_FINFO_RNG)
3053
        {
3054
            pdw1000local->cbData.rx_flags |= DWT_CB_DATA_RX_FLAG_RNG;
3055
        }
3056
3057
        // Report frame control - First bytes of the received frame.
3058
        dwt_readfromdevice(RX_BUFFER_ID, 0, FCTRL_LEN_MAX, pdw1000local->cbData.fctrl);
3059
3060
        // Because of a previous frame not being received properly, AAT bit can be set upon the proper reception of a frame not requesting for
3061
        // acknowledgement (ACK frame is not actually sent though). If the AAT bit is set, check ACK request bit in frame control to confirm (this
3062
        // implementation works only for IEEE802.15.4-2011 compliant frames).
3063
        // 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).
3064
        if((status & SYS_STATUS_AAT) && ((pdw1000local->cbData.fctrl[0] & FCTRL_ACK_REQ_MASK) == 0))
3065
        {
3066
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_AAT); // Clear AAT status bit in register
3067
            pdw1000local->cbData.status &= ~SYS_STATUS_AAT; // Clear AAT status bit in callback data register copy
3068
            pdw1000local->wait4resp = 0;
3069
        }
3070
3071
        // Call the corresponding callback if present
3072
        if(pdw1000local->cbRxOk != NULL)
3073
        {
3074
            pdw1000local->cbRxOk(&pdw1000local->cbData);
3075
        }
3076
3077
        if (pdw1000local->dblbuffon)
3078
        {
3079
            // Toggle the Host side Receive Buffer Pointer
3080
            dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_HRBT_OFFSET, 1);
3081
        }
3082
    }
3083
3084
    // Handle TX confirmation event
3085
    if(status & SYS_STATUS_TXFRS)
3086
    {
3087
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_TX); // Clear TX event bits
3088
3089
        // 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)
3090
        // that we receive through using wait4resp to a previous TX (and assuming that the IRQ processing of that TX has already been handled), then
3091
        // 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
3092
        // ACK TX).
3093
        // See section "Transmit and automatically wait for response" in DW1000 User Manual
3094
        if((status & SYS_STATUS_AAT) && pdw1000local->wait4resp)
3095
        {
3096
            dwt_forcetrxoff(); // Turn the RX off
3097
            dwt_rxreset(); // Reset in case we were late and a frame was already being received
3098
        }
3099
3100
        // Call the corresponding callback if present
3101
        if(pdw1000local->cbTxDone != NULL)
3102
        {
3103
            pdw1000local->cbTxDone(&pdw1000local->cbData);
3104
        }
3105
    }
3106
3107
    // Handle frame reception/preamble detect timeout events
3108
    if(status & SYS_STATUS_ALL_RX_TO)
3109
    {
3110
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXRFTO); // Clear RX timeout event bits
3111
3112
        pdw1000local->wait4resp = 0;
3113
3114
        // Because of an issue with receiver restart after error conditions, an RX reset must be applied after any error or timeout event to ensure
3115
        // the next good frame's timestamp is computed correctly.
3116
        // See section "RX Message timestamp" in DW1000 User Manual.
3117
        dwt_forcetrxoff();
3118
        dwt_rxreset();
3119
3120
        // Call the corresponding callback if present
3121
        if(pdw1000local->cbRxTo != NULL)
3122
        {
3123
            pdw1000local->cbRxTo(&pdw1000local->cbData);
3124
        }
3125
    }
3126
3127
    // Handle RX errors events
3128
    if(status & SYS_STATUS_ALL_RX_ERR)
3129
    {
3130
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR); // Clear RX error event bits
3131
3132
        pdw1000local->wait4resp = 0;
3133
3134
        // Because of an issue with receiver restart after error conditions, an RX reset must be applied after any error or timeout event to ensure
3135
        // the next good frame's timestamp is computed correctly.
3136
        // See section "RX Message timestamp" in DW1000 User Manual.
3137
        dwt_forcetrxoff();
3138
        dwt_rxreset();
3139
3140
        // Call the corresponding callback if present
3141
        if(pdw1000local->cbRxErr != NULL)
3142
        {
3143
            pdw1000local->cbRxErr(&pdw1000local->cbData);
3144
        }
3145
    }
3146
}
3147
3148
/*! ------------------------------------------------------------------------------------------------------------------
3149
 * @fn dwt_isr_lplisten()
3150
 *
3151
 * @brief This is the DW1000's Interrupt Service Routine to use when low-power listening scheme is implemented. It will
3152
 *        only process/report the RXFCG event (through cbRxOk callback).
3153
 *        It clears RXFCG interrupt and reads received frame information and frame control before calling the callback.
3154
 *
3155
 *        /!\ This version of the ISR is designed for single buffering case only!
3156
 *
3157
 * input parameters
3158
 *
3159
 * output parameters
3160
 *
3161
 * no return value
3162
 */
3163
void dwt_lowpowerlistenisr(void)
3164
{
3165
    uint32_t status = pdw1000local->cbData.status = dwt_read32bitreg(SYS_STATUS_ID); // Read status register low 32bits
3166
    uint16_t finfo16;
3167
    uint16_t len;
3168
3169
    // The only interrupt handled when in low-power listening mode is RX good frame so proceed directly to the handling of the received frame.
3170
3171
    // Deactivate low-power listening before clearing the interrupt. If not, the DW1000 will go back to sleep as soon as the interrupt is cleared.
3172
    dwt_setlowpowerlistening(0);
3173
3174
    dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_GOOD); // Clear all receive status bits
3175
3176
    pdw1000local->cbData.rx_flags = 0;
3177
3178
    // Read frame info - Only the first two bytes of the register are used here.
3179
    finfo16 = dwt_read16bitoffsetreg(RX_FINFO_ID, 0);
3180
3181
    // Report frame length - Standard frame length up to 127, extended frame length up to 1023 bytes
3182
    len = finfo16 & RX_FINFO_RXFL_MASK_1023;
3183
    if(pdw1000local->longFrames == 0)
3184
    {
3185
        len &= RX_FINFO_RXFLEN_MASK;
3186
    }
3187
    pdw1000local->cbData.datalength = len;
3188
3189
    // Report ranging bit
3190
    if(finfo16 & RX_FINFO_RNG)
3191
    {
3192
        pdw1000local->cbData.rx_flags |= DWT_CB_DATA_RX_FLAG_RNG;
3193
    }
3194
3195
    // Report frame control - First bytes of the received frame.
3196
    dwt_readfromdevice(RX_BUFFER_ID, 0, FCTRL_LEN_MAX, pdw1000local->cbData.fctrl);
3197
3198
    // Because of a previous frame not being received properly, AAT bit can be set upon the proper reception of a frame not requesting for
3199
    // acknowledgement (ACK frame is not actually sent though). If the AAT bit is set, check ACK request bit in frame control to confirm (this
3200
    // implementation works only for IEEE802.15.4-2011 compliant frames).
3201
    // 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).
3202
    if((status & SYS_STATUS_AAT) && ((pdw1000local->cbData.fctrl[0] & FCTRL_ACK_REQ_MASK) == 0))
3203
    {
3204
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_AAT); // Clear AAT status bit in register
3205
        pdw1000local->cbData.status &= ~SYS_STATUS_AAT; // Clear AAT status bit in callback data register copy
3206
        pdw1000local->wait4resp = 0;
3207
    }
3208
3209
    // Call the corresponding callback if present
3210
    if(pdw1000local->cbRxOk != NULL)
3211
    {
3212
        pdw1000local->cbRxOk(&pdw1000local->cbData);
3213
    }
3214
}
3215
3216
/*! ------------------------------------------------------------------------------------------------------------------
3217
 * @fn dwt_setleds()
3218
 *
3219
 * @brief This is used to set up Tx/Rx GPIOs which could be used to control LEDs
3220
 * Note: not completely IC dependent, also needs board with LEDS fitted on right I/O lines
3221
 *       this function enables GPIOs 2 and 3 which are connected to LED3 and LED4 on EVB1000
3222
 *
3223
 * input parameters
3224
 * @param mode - this is a bit field interpreted as follows:
3225
 *          - bit 0: 1 to enable LEDs, 0 to disable them
3226
 *          - bit 1: 1 to make LEDs blink once on init. Only valid if bit 0 is set (enable LEDs)
3227
 *          - bit 2 to 7: reserved
3228
 *
3229
 * output parameters none
3230
 *
3231
 * no return value
3232
 */
3233
void dwt_setleds(uint8_t mode)
3234
{
3235
    uint32_t reg;
3236
3237
    if (mode & DWT_LEDS_ENABLE)
3238
    {
3239
        // Set up MFIO for LED output.
3240
        reg = dwt_read32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET);
3241
        reg &= ~(GPIO_MSGP2_MASK | GPIO_MSGP3_MASK);
3242
        reg |= (GPIO_PIN2_RXLED | GPIO_PIN3_TXLED);
3243
        dwt_write32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET, reg);
3244
3245
        // Enable LP Oscillator to run from counter and turn on de-bounce clock.
3246
        reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET);
3247
        reg |= (PMSC_CTRL0_GPDCE | PMSC_CTRL0_KHZCLEN);
3248
        dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, reg);
3249
3250
        // Enable LEDs to blink and set default blink time.
3251
        reg = PMSC_LEDC_BLNKEN | PMSC_LEDC_BLINK_TIME_DEF;
3252
        // Make LEDs blink once if requested.
3253
        if (mode & DWT_LEDS_INIT_BLINK)
3254
        {
3255
            reg |= PMSC_LEDC_BLINK_NOW_ALL;
3256
        }
3257
        dwt_write32bitoffsetreg(PMSC_ID, PMSC_LEDC_OFFSET, reg);
3258
        // Clear force blink bits if needed.
3259
        if(mode & DWT_LEDS_INIT_BLINK)
3260
        {
3261
            reg &= ~PMSC_LEDC_BLINK_NOW_ALL;
3262
            dwt_write32bitoffsetreg(PMSC_ID, PMSC_LEDC_OFFSET, reg);
3263
        }
3264
    }
3265
    else
3266
    {
3267
        // Clear the GPIO bits that are used for LED control.
3268
        reg = dwt_read32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET);
3269
        reg &= ~(GPIO_MSGP2_MASK | GPIO_MSGP3_MASK);
3270
        dwt_write32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET, reg);
3271
    }
3272
}
3273
3274
/*! ------------------------------------------------------------------------------------------------------------------
3275
 * @fn _dwt_enableclocks()
3276
 *
3277
 * @brief function to enable/disable clocks to particular digital blocks/system
3278
 *
3279
 * input parameters
3280
 * @param clocks - set of clocks to enable/disable
3281
 *
3282
 * output parameters none
3283
 *
3284
 * no return value
3285
 */
3286
void _dwt_enableclocks(int clocks)
3287
{
3288
    uint8_t reg[2];
3289
3290
    dwt_readfromdevice(PMSC_ID, PMSC_CTRL0_OFFSET, 2, reg);
3291
    switch(clocks)
3292
    {
3293
        case ENABLE_ALL_SEQ:
3294
        {
3295
            reg[0] = 0x00 ;
3296
            reg[1] = reg[1] & 0xfe;
3297
        }
3298
        break;
3299
        case FORCE_SYS_XTI:
3300
        {
3301
            // System and RX
3302
            reg[0] = 0x01 | (reg[0] & 0xfc);
3303
        }
3304
        break;
3305
        case FORCE_SYS_PLL:
3306
        {
3307
            // System
3308
            reg[0] = 0x02 | (reg[0] & 0xfc);
3309
        }
3310
        break;
3311
        case READ_ACC_ON:
3312
        {
3313
            reg[0] = 0x48 | (reg[0] & 0xb3);
3314
            reg[1] = 0x80 | reg[1];
3315
        }
3316
        break;
3317
        case READ_ACC_OFF:
3318
        {
3319
            reg[0] = reg[0] & 0xb3;
3320
            reg[1] = 0x7f & reg[1];
3321
        }
3322
        break;
3323
        case FORCE_OTP_ON:
3324
        {
3325
            reg[1] = 0x02 | reg[1];
3326
        }
3327
        break;
3328
        case FORCE_OTP_OFF:
3329
        {
3330
            reg[1] = reg[1] & 0xfd;
3331
        }
3332
        break;
3333
        case FORCE_TX_PLL:
3334
        {
3335
            reg[0] = 0x20 | (reg[0] & 0xcf);
3336
        }
3337
        break;
3338
        case FORCE_LDE:
3339
        {
3340
            reg[0] = 0x01;
3341
            reg[1] = 0x03;
3342
        }
3343
        break;
3344
        default:
3345
        break;
3346
    }
3347
3348
3349
    // Need to write lower byte separately before setting the higher byte(s)
3350
    dwt_writetodevice(PMSC_ID, PMSC_CTRL0_OFFSET, 1, &reg[0]);
3351
    dwt_writetodevice(PMSC_ID, 0x1, 1, &reg[1]);
3352
3353
} // end _dwt_enableclocks()
3354
3355
/*! ------------------------------------------------------------------------------------------------------------------
3356
 * @fn _dwt_disablesequencing()
3357
 *
3358
 * @brief This function disables the TX blocks sequencing, it disables PMSC control of RF blocks, system clock is also set to XTAL
3359
 *
3360
 * input parameters none
3361
 *
3362
 * output parameters none
3363
 *
3364
 * no return value
3365
 */
3366
void _dwt_disablesequencing(void) // Disable sequencing and go to state "INIT"
3367
{
3368
    _dwt_enableclocks(FORCE_SYS_XTI); // Set system clock to XTI
3369
3370
    dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, PMSC_CTRL1_PKTSEQ_DISABLE); // Disable PMSC ctrl of RF and RX clk blocks
3371
}
3372
3373
/*! ------------------------------------------------------------------------------------------------------------------
3374
 * @fn dwt_setdelayedtrxtime()
3375
 *
3376
 * @brief This API function configures the delayed transmit time or the delayed RX on time
3377
 *
3378
 * input parameters
3379
 * @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,
3380
 * or at which to turn on the receiver)
3381
 *
3382
 * output parameters none
3383
 *
3384
 * no return value
3385
 */
3386
void dwt_setdelayedtrxtime(uint32_t starttime)
3387
{
3388
    dwt_write32bitoffsetreg(DX_TIME_ID, 1, starttime); // Write at offset 1 as the lower 9 bits of this register are ignored
3389
3390
} // end dwt_setdelayedtrxtime()
3391
3392
/*! ------------------------------------------------------------------------------------------------------------------
3393
 * @fn dwt_starttx()
3394
 *
3395
 * @brief This call initiates the transmission, input parameter indicates which TX mode is used see below
3396
 *
3397
 * input parameters:
3398
 * @param mode - if 0 immediate TX (no response expected)
3399
 *               if 1 delayed TX (no response expected)
3400
 *               if 2 immediate TX (response expected - so the receiver will be automatically turned on after TX is done)
3401
 *               if 3 delayed TX (response expected - so the receiver will be automatically turned on after TX is done)
3402
 *
3403
 * output parameters
3404
 *
3405
 * returns DWT_SUCCESS for success, or DWT_ERROR for error (e.g. a delayed transmission will fail if the delayed time has passed)
3406
 */
3407
int dwt_starttx(uint8_t mode)
3408
{
3409
    int retval = DWT_SUCCESS ;
3410
    uint8_t temp  = 0x00;
3411
    uint16_t checkTxOK = 0 ;
3412
3413
    if(mode & DWT_RESPONSE_EXPECTED)
3414
    {
3415
        temp = (uint8_t)SYS_CTRL_WAIT4RESP ; // Set wait4response bit
3416
        dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3417
        pdw1000local->wait4resp = 1;
3418
    }
3419
3420
    if (mode & DWT_START_TX_DELAYED)
3421
    {
3422
        // Both SYS_CTRL_TXSTRT and SYS_CTRL_TXDLYS to correctly enable TX
3423
        temp |= (uint8_t)(SYS_CTRL_TXDLYS | SYS_CTRL_TXSTRT) ;
3424
        dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3425
        checkTxOK = dwt_read16bitoffsetreg(SYS_STATUS_ID, 3); // Read at offset 3 to get the upper 2 bytes out of 5
3426
        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).
3427
        {
3428
            retval = DWT_SUCCESS ; // All okay
3429
        }
3430
        else
3431
        {
3432
            // I am taking DSHP set to Indicate that the TXDLYS was set too late for the specified DX_TIME.
3433
            // Remedial Action - (a) cancel delayed send
3434
            temp = (uint8_t)SYS_CTRL_TRXOFF; // This assumes the bit is in the lowest byte
3435
            dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3436
            // Note event Delayed TX Time too Late
3437
            // Could fall through to start a normal send (below) just sending late.....
3438
            // ... instead return and assume return value of 1 will be used to detect and recover from the issue.
3439
            pdw1000local->wait4resp = 0;
3440
            retval = DWT_ERROR ; // Failed !
3441
        }
3442
    }
3443
    else
3444
    {
3445
        temp |= (uint8_t)SYS_CTRL_TXSTRT ;
3446
        dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3447
    }
3448
3449
    return retval;
3450
3451
} // end dwt_starttx()
3452
3453
/*! ------------------------------------------------------------------------------------------------------------------
3454
 * @fn dwt_forcetrxoff()
3455
 *
3456
 * @brief This is used to turn off the transceiver
3457
 *
3458
 * input parameters
3459
 *
3460
 * output parameters
3461
 *
3462
 * no return value
3463
 */
3464
void dwt_forcetrxoff(void)
3465
{
3466
    decaIrqStatus_t stat ;
3467
    uint32_t mask;
3468
3469
    mask = dwt_read32bitreg(SYS_MASK_ID) ; // Read set interrupt mask
3470
3471
    // Need to beware of interrupts occurring in the middle of following read modify write cycle
3472
    // We can disable the radio, but before the status is cleared an interrupt can be set (e.g. the
3473
    // event has just happened before the radio was disabled)
3474
    // thus we need to disable interrupt during this operation
3475
    stat = decamutexon() ;
3476
3477
    dwt_write32bitreg(SYS_MASK_ID, 0) ; // Clear interrupt mask - so we don't get any unwanted events
3478
3479
    dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, (uint8_t)SYS_CTRL_TRXOFF) ; // Disable the radio
3480
3481
    // Forcing Transceiver off - so we do not want to see any new events that may have happened
3482
    dwt_write32bitreg(SYS_STATUS_ID, (SYS_STATUS_ALL_TX | SYS_STATUS_ALL_RX_ERR | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_GOOD));
3483
3484
    dwt_syncrxbufptrs();
3485
3486
    dwt_write32bitreg(SYS_MASK_ID, mask) ; // Set interrupt mask to what it was
3487
3488
    // Enable/restore interrupts again...
3489
    decamutexoff(stat) ;
3490
    pdw1000local->wait4resp = 0;
3491
3492
} // end deviceforcetrxoff()
3493
3494
/*! ------------------------------------------------------------------------------------------------------------------
3495
 * @fn dwt_syncrxbufptrs()
3496
 *
3497
 * @brief this function synchronizes rx buffer pointers
3498
 * need to make sure that the host/IC buffer pointers are aligned before starting RX
3499
 *
3500
 * input parameters:
3501
 *
3502
 * output parameters
3503
 *
3504
 * no return value
3505
 */
3506
void dwt_syncrxbufptrs(void)
3507
{
3508
    uint8_t  buff ;
3509
    // Need to make sure that the host/IC buffer pointers are aligned before starti