Statistics
| Branch: | Tag: | Revision:

amiro-lld / source / DW1000 / v1 / alld_dw1000_v1.c @ 69a601a5

History | View | Annotate | Download (151.183 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
32
#include <alld_DW1000.h>
33
34
#if (defined(AMIROLLD_CFG_DW1000) && (AMIROLLD_CFG_DW1000 == 1)) || defined(__DOXYGEN__)
35
36
#include <aos_thread.h>
37
#include <assert.h>
38
#include <string.h>
39
#include <stdlib.h>
40
#include <math.h>
41
42
43
// Defines for enable_clocks function
44
#define FORCE_SYS_XTI  0
45
#define ENABLE_ALL_SEQ 1
46
#define FORCE_SYS_PLL  2
47
#define READ_ACC_ON    7
48
#define READ_ACC_OFF   8
49
#define FORCE_OTP_ON   11
50
#define FORCE_OTP_OFF  12
51
#define FORCE_TX_PLL   13
52
#define FORCE_LDE      14
53
54
// Defines for ACK request bitmask in DATA and MAC COMMAND frame control (first byte) - Used to detect AAT bit wrongly set.
55
#define FCTRL_ACK_REQ_MASK 0x20
56
// Frame control maximum length in bytes.
57
#define FCTRL_LEN_MAX 2
58
59
60
/**
61
 * Move to the header file <alld_dw1000_v1.h>
62
*/
63
//#define NUM_BR 3
64
//#define NUM_PRF 2
65
//#define NUM_PACS 4
66
//#define NUM_BW 2            //2 bandwidths are supported
67
//#define NUM_SFD 2           //supported number of SFDs - standard = 0, non-standard = 1
68
//#define NUM_CH 6            //supported channels are 1, 2, 3, 4, 5, 7
69
//#define NUM_CH_SUPPORTED 8  //supported channels are '0', 1, 2, 3, 4, 5, '6', 7
70
//#define PCODES 25           //supported preamble codes
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
//int dwt_initialise(const uint16_t config, DW1000Driver* drv)
1017
int dwt_initialise(const uint16_t config)  // TODO:
1018
{
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
//    pdw1000local->driver = drv;  // TODO:
1032
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
//    _alld_dw1000_writespi(cnt,header,length,buffer);
1817
    writetospi(cnt,header,length,buffer);  // TODO
1818
} // end dwt_writetodevice()
1819
1820
/*! ------------------------------------------------------------------------------------------------------------------
1821
 * @fn dwt_readfromdevice()
1822
 *
1823
 * @brief  this function is used to read from the DW1000 device registers
1824
 * Notes:
1825
 *        1. Firstly we create a header (the first byte is a header byte)
1826
 *        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
1827
 *        b. set bit-7 (or with 0x80) for write operation
1828
 *        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
1829
 *
1830
 *        2. Write the header followed by the data bytes to the DW1000 device
1831
 *        3. Store the read data in the input buffer
1832
 *
1833
 * input parameters:
1834
 * @param recordNumber  - ID of register file or buffer being accessed
1835
 * @param index         - byte index into register file or buffer being accessed
1836
 * @param length        - number of bytes being read
1837
 * @param buffer        - pointer to buffer in which to return the read data.
1838
 *
1839
 * output parameters
1840
 *
1841
 * no return value
1842
 */
1843
void dwt_readfromdevice
1844
(
1845
    uint16_t  recordNumber,
1846
    uint16_t  index,
1847
    uint32_t  length,
1848
    uint8_t   *buffer
1849
)
1850
{
1851
    uint8_t header[3] ; // Buffer to compose header in
1852
    int   cnt = 0; // Counter for length of header
1853
#ifdef DWT_API_ERROR_CHECK
1854
    assert(recordNumber <= 0x3F); // Record number is limited to 6-bits.
1855
#endif
1856
1857
    // Write message header selecting READ operation and addresses as appropriate (this is one to three bytes long)
1858
    if (index == 0) // For index of 0, no sub-index is required
1859
    {
1860
        header[cnt++] = (uint8_t) recordNumber ; // Bit-7 zero is READ operation, bit-6 zero=NO sub-addressing, bits 5-0 is reg file id
1861
    }
1862
    else
1863
    {
1864
#ifdef DWT_API_ERROR_CHECK
1865
        assert((index <= 0x7FFF) && ((index + length) <= 0x7FFF)); // Index and sub-addressable area are limited to 15-bits.
1866
#endif
1867
        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
1868
1869
        if (index <= 127) // For non-zero index < 127, just a single sub-index byte is required
1870
        {
1871
            header[cnt++] = (uint8_t) index ; // Bit-7 zero means no extension, bits 6-0 is index.
1872
        }
1873
        else
1874
        {
1875
            header[cnt++] = 0x80 | (uint8_t)(index) ; // Bit-7 one means extended index, bits 6-0 is low seven bits of index.
1876
            header[cnt++] =  (uint8_t) (index >> 7) ; // 8-bit value = high eight bits of index.
1877
        }
1878
    }
1879
1880
    // Do the read from the SPI
1881
//    _alld_dw1000_readspi(cnt, header, length, buffer);  // result is stored in the buffer
1882
    readfromspi(cnt, header, length, buffer);  // TODO:
1883
} // end dwt_readfromdevice()
1884
1885
1886
1887
/*! ------------------------------------------------------------------------------------------------------------------
1888
 * @fn dwt_read32bitoffsetreg()
1889
 *
1890
 * @brief  this function is used to read 32-bit value from the DW1000 device registers
1891
 *
1892
 * input parameters:
1893
 * @param regFileID - ID of register file or buffer being accessed
1894
 * @param regOffset - the index into register file or buffer being accessed
1895
 *
1896
 * output parameters
1897
 *
1898
 * returns 32 bit register value
1899
 */
1900
uint32_t dwt_read32bitoffsetreg(int regFileID,int regOffset)
1901
{
1902
    uint32_t  regval = 0 ;
1903
    int     j ;
1904
    uint8_t   buffer[4] ;
1905
1906
    dwt_readfromdevice(regFileID,regOffset,4,buffer); // Read 4 bytes (32-bits) register into buffer
1907
1908
    for (j = 3 ; j >= 0 ; j --)
1909
    {
1910
        regval = (regval << 8) + buffer[j] ;
1911
    }
1912
    return regval ;
1913
1914
} // end dwt_read32bitoffsetreg()
1915
1916
/*! ------------------------------------------------------------------------------------------------------------------
1917
 * @fn dwt_read16bitoffsetreg()
1918
 *
1919
 * @brief  this function is used to read 16-bit value from the DW1000 device registers
1920
 *
1921
 * input parameters:
1922
 * @param regFileID - ID of register file or buffer being accessed
1923
 * @param regOffset - the index into register file or buffer being accessed
1924
 *
1925
 * output parameters
1926
 *
1927
 * returns 16 bit register value
1928
 */
1929
uint16_t dwt_read16bitoffsetreg(int regFileID,int regOffset)
1930
{
1931
    uint16_t  regval = 0 ;
1932
    uint8_t   buffer[2] ;
1933
1934
    dwt_readfromdevice(regFileID,regOffset,2,buffer); // Read 2 bytes (16-bits) register into buffer
1935
1936
    regval = (buffer[1] << 8) + buffer[0] ;
1937
    return regval ;
1938
1939
} // end dwt_read16bitoffsetreg()
1940
1941
/*! ------------------------------------------------------------------------------------------------------------------
1942
 * @fn dwt_read8bitoffsetreg()
1943
 *
1944
 * @brief  this function is used to read an 8-bit value from the DW1000 device registers
1945
 *
1946
 * input parameters:
1947
 * @param regFileID - ID of register file or buffer being accessed
1948
 * @param regOffset - the index into register file or buffer being accessed
1949
 *
1950
 * output parameters
1951
 *
1952
 * returns 8-bit register value
1953
 */
1954
uint8_t dwt_read8bitoffsetreg(int regFileID, int regOffset)
1955
{
1956
    uint8_t regval;
1957
1958
    dwt_readfromdevice(regFileID, regOffset, 1, &regval);
1959
1960
    return regval ;
1961
}
1962
1963
/*! ------------------------------------------------------------------------------------------------------------------
1964
 * @fn dwt_write8bitoffsetreg()
1965
 *
1966
 * @brief  this function is used to write an 8-bit value to the DW1000 device registers
1967
 *
1968
 * input parameters:
1969
 * @param regFileID - ID of register file or buffer being accessed
1970
 * @param regOffset - the index into register file or buffer being accessed
1971
 * @param regval    - the value to write
1972
 *
1973
 * output parameters
1974
 *
1975
 * no return value
1976
 */
1977
void dwt_write8bitoffsetreg(int regFileID, int regOffset, uint8_t regval)
1978
{
1979
    dwt_writetodevice(regFileID, regOffset, 1, &regval);
1980
}
1981
1982
/*! ------------------------------------------------------------------------------------------------------------------
1983
 * @fn dwt_write16bitoffsetreg()
1984
 *
1985
 * @brief  this function is used to write 16-bit value to the DW1000 device registers
1986
 *
1987
 * input parameters:
1988
 * @param regFileID - ID of register file or buffer being accessed
1989
 * @param regOffset - the index into register file or buffer being accessed
1990
 * @param regval    - the value to write
1991
 *
1992
 * output parameters
1993
 *
1994
 * no return value
1995
 */
1996
void dwt_write16bitoffsetreg(int regFileID,int regOffset,uint16_t regval)
1997
{
1998
    uint8_t   buffer[2] ;
1999
2000
    buffer[0] = regval & 0xFF;
2001
    buffer[1] = regval >> 8 ;
2002
2003
    dwt_writetodevice(regFileID,regOffset,2,buffer);
2004
} // end dwt_write16bitoffsetreg()
2005
2006
/*! ------------------------------------------------------------------------------------------------------------------
2007
 * @fn dwt_write32bitoffsetreg()
2008
 *
2009
 * @brief  this function is used to write 32-bit value to the DW1000 device registers
2010
 *
2011
 * input parameters:
2012
 * @param regFileID - ID of register file or buffer being accessed
2013
 * @param regOffset - the index into register file or buffer being accessed
2014
 * @param regval    - the value to write
2015
 *
2016
 * output parameters
2017
 *
2018
 * no return value
2019
 */
2020
void dwt_write32bitoffsetreg(int regFileID,int regOffset,uint32_t regval)
2021
{
2022
    int     j ;
2023
    uint8_t   buffer[4] ;
2024
2025
    for ( j = 0 ; j < 4 ; j++ )
2026
    {
2027
        buffer[j] = regval & 0xff ;
2028
        regval >>= 8 ;
2029
    }
2030
2031
    dwt_writetodevice(regFileID,regOffset,4,buffer);
2032
} // end dwt_write32bitoffsetreg()
2033
2034
/*! ------------------------------------------------------------------------------------------------------------------
2035
 * @fn dwt_enableframefilter()
2036
 *
2037
 * @brief This is used to enable the frame filtering - (the default option is to
2038
 * accept any data and ACK frames with correct destination address
2039
 *
2040
 * input parameters
2041
 * @param - bitmask - enables/disables the frame filtering options according to
2042
 *      DWT_FF_NOTYPE_EN        0x000   no frame types allowed
2043
 *      DWT_FF_COORD_EN         0x002   behave as coordinator (can receive frames with no destination address (PAN ID has to match))
2044
 *      DWT_FF_BEACON_EN        0x004   beacon frames allowed
2045
 *      DWT_FF_DATA_EN          0x008   data frames allowed
2046
 *      DWT_FF_ACK_EN           0x010   ack frames allowed
2047
 *      DWT_FF_MAC_EN           0x020   mac control frames allowed
2048
 *      DWT_FF_RSVD_EN          0x040   reserved frame types allowed
2049
 *
2050
 * output parameters
2051
 *
2052
 * no return value
2053
 */
2054
void dwt_enableframefilter(uint16_t enable)
2055
{
2056
    uint32_t sysconfig = SYS_CFG_MASK & dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
2057
2058
    if(enable)
2059
    {
2060
        // Enable frame filtering and configure frame types
2061
        sysconfig &= ~(SYS_CFG_FF_ALL_EN); // Clear all
2062
        sysconfig |= (enable & SYS_CFG_FF_ALL_EN) | SYS_CFG_FFE;
2063
    }
2064
    else
2065
    {
2066
        sysconfig &= ~(SYS_CFG_FFE);
2067
    }
2068
2069
    pdw1000local->sysCFGreg = sysconfig ;
2070
    dwt_write32bitreg(SYS_CFG_ID,sysconfig) ;
2071
}
2072
2073
/*! ------------------------------------------------------------------------------------------------------------------
2074
 * @fn dwt_setpanid()
2075
 *
2076
 * @brief This is used to set the PAN ID
2077
 *
2078
 * input parameters
2079
 * @param panID - this is the PAN ID
2080
 *
2081
 * output parameters
2082
 *
2083
 * no return value
2084
 */
2085
void dwt_setpanid(uint16_t panID)
2086
{
2087
    // PAN ID is high 16 bits of register
2088
    dwt_write16bitoffsetreg(PANADR_ID, PANADR_PAN_ID_OFFSET, panID);
2089
}
2090
2091
/*! ------------------------------------------------------------------------------------------------------------------
2092
 * @fn dwt_setaddress16()
2093
 *
2094
 * @brief This is used to set 16-bit (short) address
2095
 *
2096
 * input parameters
2097
 * @param shortAddress - this sets the 16 bit short address
2098
 *
2099
 * output parameters
2100
 *
2101
 * no return value
2102
 */
2103
void dwt_setaddress16(uint16_t shortAddress)
2104
{
2105
    // Short address into low 16 bits
2106
    dwt_write16bitoffsetreg(PANADR_ID, PANADR_SHORT_ADDR_OFFSET, shortAddress);
2107
}
2108
2109
/*! ------------------------------------------------------------------------------------------------------------------
2110
 * @fn dwt_seteui()
2111
 *
2112
 * @brief This is used to set the EUI 64-bit (long) address
2113
 *
2114
 * input parameters
2115
 * @param eui64 - this is the pointer to a buffer that contains the 64bit address
2116
 *
2117
 * output parameters
2118
 *
2119
 * no return value
2120
 */
2121
void dwt_seteui(uint8_t *eui64)
2122
{
2123
    dwt_writetodevice(EUI_64_ID, EUI_64_OFFSET, EUI_64_LEN, eui64);
2124
}
2125
2126
/*! ------------------------------------------------------------------------------------------------------------------
2127
 * @fn dwt_geteui()
2128
 *
2129
 * @brief This is used to get the EUI 64-bit from the DW1000
2130
 *
2131
 * input parameters
2132
 * @param eui64 - this is the pointer to a buffer that will contain the read 64-bit EUI value
2133
 *
2134
 * output parameters
2135
 *
2136
 * no return value
2137
 */
2138
void dwt_geteui(uint8_t *eui64)
2139
{
2140
    dwt_readfromdevice(EUI_64_ID, EUI_64_OFFSET, EUI_64_LEN, eui64);
2141
}
2142
2143
/*! ------------------------------------------------------------------------------------------------------------------
2144
 * @fn dwt_otpread()
2145
 *
2146
 * @brief This is used to read the OTP data from given address into provided array
2147
 *
2148
 * input parameters
2149
 * @param address - this is the OTP address to read from
2150
 * @param array - this is the pointer to the array into which to read the data
2151
 * @param length - this is the number of 32 bit words to read (array needs to be at least this length)
2152
 *
2153
 * output parameters
2154
 *
2155
 * no return value
2156
 */
2157
void dwt_otpread(uint32_t address, uint32_t *array, uint8_t length)
2158
{
2159
    int i;
2160
2161
    _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
2162
2163
    for(i=0; i<length; i++)
2164
    {
2165
        array[i] = _dwt_otpread(address + i) ;
2166
    }
2167
2168
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Restore system clock to PLL
2169
2170
    return ;
2171
}
2172
2173
/*! ------------------------------------------------------------------------------------------------------------------
2174
 * @fn _dwt_otpread()
2175
 *
2176
 * @brief function to read the OTP memory. Ensure that MR,MRa,MRb are reset to 0.
2177
 *
2178
 * input parameters
2179
 * @param address - address to read at
2180
 *
2181
 * output parameters
2182
 *
2183
 * returns the 32bit of read data
2184
 */
2185
uint32_t _dwt_otpread(uint32_t address)
2186
{
2187
    uint32_t ret_data;
2188
2189
    // Write the address
2190
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_ADDR, address);
2191
2192
    // Perform OTP Read - Manual read mode has to be set
2193
    dwt_write8bitoffsetreg(OTP_IF_ID, OTP_CTRL, OTP_CTRL_OTPREAD | OTP_CTRL_OTPRDEN);
2194
    dwt_write8bitoffsetreg(OTP_IF_ID, OTP_CTRL, 0x00); // OTPREAD is self clearing but OTPRDEN is not
2195
2196
    // Read read data, available 40ns after rising edge of OTP_READ
2197
    ret_data = dwt_read32bitoffsetreg(OTP_IF_ID, OTP_RDAT);
2198
2199
    // Return the 32bit of read data
2200
    return ret_data;
2201
}
2202
2203
/*! ------------------------------------------------------------------------------------------------------------------
2204
 * @fn _dwt_otpsetmrregs()
2205
 *
2206
 * @brief Configure the MR registers for initial programming (enable charge pump).
2207
 * Read margin is used to stress the read back from the
2208
 * programmed bit. In normal operation this is relaxed.
2209
 *
2210
 * input parameters
2211
 * @param mode - "0" : Reset all to 0x0:           MRA=0x0000, MRB=0x0000, MR=0x0000
2212
 *               "1" : Set for inital programming: MRA=0x9220, MRB=0x000E, MR=0x1024
2213
 *               "2" : Set for soak programming:   MRA=0x9220, MRB=0x0003, MR=0x1824
2214
 *               "3" : High Vpp:                   MRA=0x9220, MRB=0x004E, MR=0x1824
2215
 *               "4" : Low Read Margin:            MRA=0x0000, MRB=0x0003, MR=0x0000
2216
 *               "5" : Array Clean:                MRA=0x0049, MRB=0x0003, MR=0x0024
2217
 *               "4" : Very Low Read Margin:       MRA=0x0000, MRB=0x0003, MR=0x0000
2218
 *
2219
 * output parameters
2220
 *
2221
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2222
 */
2223
uint32_t _dwt_otpsetmrregs(int mode)
2224
{
2225
    uint8_t rd_buf[4];
2226
    uint8_t wr_buf[4];
2227
    uint32_t mra=0,mrb=0,mr=0;
2228
2229
    // PROGRAMME MRA
2230
    // Set MRA, MODE_SEL
2231
    wr_buf[0] = 0x03;
2232
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL+1,1,wr_buf);
2233
2234
    // Load data
2235
    switch(mode&0x0f) {
2236
    case 0x0 :
2237
        mr =0x0000;
2238
        mra=0x0000;
2239
        mrb=0x0000;
2240
        break;
2241
    case 0x1 :
2242
        mr =0x1024;
2243
        mra=0x9220; // Enable CPP mon
2244
        mrb=0x000e;
2245
        break;
2246
    case 0x2 :
2247
        mr =0x1824;
2248
        mra=0x9220;
2249
        mrb=0x0003;
2250
        break;
2251
    case 0x3 :
2252
        mr =0x1824;
2253
        mra=0x9220;
2254
        mrb=0x004e;
2255
        break;
2256
    case 0x4 :
2257
        mr =0x0000;
2258
        mra=0x0000;
2259
        mrb=0x0003;
2260
        break;
2261
    case 0x5 :
2262
        mr =0x0024;
2263
        mra=0x0000;
2264
        mrb=0x0003;
2265
        break;
2266
    default :
2267
        return DWT_ERROR;
2268
    }
2269
2270
    wr_buf[0] = mra & 0x00ff;
2271
    wr_buf[1] = (mra & 0xff00)>>8;
2272
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2273
2274
2275
    // Set WRITE_MR
2276
    wr_buf[0] = 0x08;
2277
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2278
2279
    // Wait?
2280
2281
    // Set Clear Mode sel
2282
    wr_buf[0] = 0x02;
2283
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2284
2285
    // Set AUX update, write MR
2286
    wr_buf[0] = 0x88;
2287
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2288
    // Clear write MR
2289
    wr_buf[0] = 0x80;
2290
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2291
    // Clear AUX update
2292
    wr_buf[0] = 0x00;
2293
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2294
2295
    ///////////////////////////////////////////
2296
    // PROGRAM MRB
2297
    // Set SLOW, MRB, MODE_SEL
2298
    wr_buf[0] = 0x05;
2299
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2300
2301
    wr_buf[0] = mrb & 0x00ff;
2302
    wr_buf[1] = (mrb & 0xff00)>>8;
2303
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2304
2305
    // Set WRITE_MR
2306
    wr_buf[0] = 0x08;
2307
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2308
2309
    // Wait?
2310
2311
    // Set Clear Mode sel
2312
    wr_buf[0] = 0x04;
2313
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2314
2315
    // Set AUX update, write MR
2316
    wr_buf[0] = 0x88;
2317
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2318
    // Clear write MR
2319
    wr_buf[0] = 0x80;
2320
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2321
    // Clear AUX update
2322
    wr_buf[0] = 0x00;
2323
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2324
2325
    ///////////////////////////////////////////
2326
    // PROGRAM MR
2327
    // Set SLOW, MODE_SEL
2328
    wr_buf[0] = 0x01;
2329
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2330
    // Load data
2331
2332
    wr_buf[0] = mr & 0x00ff;
2333
    wr_buf[1] = (mr & 0xff00)>>8;
2334
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2335
2336
    // Set WRITE_MR
2337
    wr_buf[0] = 0x08;
2338
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2339
2340
    // Wait?
2341
    deca_sleep(10);
2342
    // Set Clear Mode sel
2343
    wr_buf[0] = 0x00;
2344
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2345
2346
    // Read confirm mode writes.
2347
    // Set man override, MRA_SEL
2348
    wr_buf[0] = OTP_CTRL_OTPRDEN;
2349
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2350
    wr_buf[0] = 0x02;
2351
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2352
    // MRB_SEL
2353
    wr_buf[0] = 0x04;
2354
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2355
    deca_sleep(100);
2356
2357
    // Clear mode sel
2358
    wr_buf[0] = 0x00;
2359
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2360
    // Clear MAN_OVERRIDE
2361
    wr_buf[0] = 0x00;
2362
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2363
2364
    deca_sleep(10);
2365
2366
    if (((mode&0x0f) == 0x1)||((mode&0x0f) == 0x2))
2367
    {
2368
        // Read status register
2369
        dwt_readfromdevice(OTP_IF_ID, OTP_STAT,1,rd_buf);
2370
    }
2371
2372
    return DWT_SUCCESS;
2373
}
2374
2375
/*! ------------------------------------------------------------------------------------------------------------------
2376
 * @fn _dwt_otpprogword32()
2377
 *
2378
 * @brief function to program the OTP memory. Ensure that MR,MRa,MRb are reset to 0.
2379
 * VNM Charge pump needs to be enabled (see _dwt_otpsetmrregs)
2380
 * Note the address is only 11 bits long.
2381
 *
2382
 * input parameters
2383
 * @param address - address to read at
2384
 *
2385
 * output parameters
2386
 *
2387
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2388
 */
2389
uint32_t _dwt_otpprogword32(uint32_t data, uint16_t address)
2390
{
2391
    uint8_t rd_buf[1];
2392
    uint8_t wr_buf[4];
2393
    uint8_t otp_done;
2394
2395
    // Read status register
2396
    dwt_readfromdevice(OTP_IF_ID, OTP_STAT, 1, rd_buf);
2397
2398
    if((rd_buf[0] & 0x02) != 0x02)
2399
    {
2400
        return DWT_ERROR;
2401
    }
2402
2403
    // Write the data
2404
    wr_buf[3] = (data>>24) & 0xff;
2405
    wr_buf[2] = (data>>16) & 0xff;
2406
    wr_buf[1] = (data>>8) & 0xff;
2407
    wr_buf[0] = data & 0xff;
2408
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT, 4, wr_buf);
2409
2410
    // Write the address [10:0]
2411
    wr_buf[1] = (address>>8) & 0x07;
2412
    wr_buf[0] = address & 0xff;
2413
    dwt_writetodevice(OTP_IF_ID, OTP_ADDR, 2, wr_buf);
2414
2415
    // Enable Sequenced programming
2416
    wr_buf[0] = OTP_CTRL_OTPPROG;
2417
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL, 1, wr_buf);
2418
    wr_buf[0] = 0x00; // And clear
2419
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL, 1, wr_buf);
2420
2421
    // WAIT for status to flag PRGM OK..
2422
    otp_done = 0;
2423
    while(otp_done == 0)
2424
    {
2425
        deca_sleep(1);
2426
        dwt_readfromdevice(OTP_IF_ID, OTP_STAT, 1, rd_buf);
2427
2428
        if((rd_buf[0] & 0x01) == 0x01)
2429
        {
2430
            otp_done = 1;
2431
        }
2432
    }
2433
2434
    return DWT_SUCCESS;
2435
}
2436
2437
/*! ------------------------------------------------------------------------------------------------------------------
2438
 * @fn dwt_otpwriteandverify()
2439
 *
2440
 * @brief This is used to program 32-bit value into the DW1000 OTP memory.
2441
 *
2442
 * input parameters
2443
 * @param value - this is the 32-bit value to be programmed into OTP
2444
 * @param address - this is the 16-bit OTP address into which the 32-bit value is programmed
2445
 *
2446
 * output parameters
2447
 *
2448
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2449
 */
2450
int dwt_otpwriteandverify(uint32_t value, uint16_t address)
2451
{
2452
    int prog_ok = DWT_SUCCESS;
2453
    int retry = 0;
2454
    // Firstly set the system clock to crystal
2455
    _dwt_enableclocks(FORCE_SYS_XTI); //set system clock to XTI
2456
2457
    //
2458
    //!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!
2459
    //Set the supply to 3.7V
2460
    //
2461
2462
    _dwt_otpsetmrregs(1); // Set mode for programming
2463
2464
    // For each value to program - the readback/check is done couple of times to verify it has programmed successfully
2465
    while(1)
2466
    {
2467
        _dwt_otpprogword32(value, address);
2468
2469
        if(_dwt_otpread(address) == value)
2470
        {
2471
            break;
2472
        }
2473
        retry++;
2474
        if(retry==5)
2475
        {
2476
            break;
2477
        }
2478
    }
2479
2480
    // Even if the above does not exit before retry reaches 5, the programming has probably been successful
2481
2482
    _dwt_otpsetmrregs(4); // Set mode for reading
2483
2484
    if(_dwt_otpread(address) != value) // If this does not pass please check voltage supply on VDDIO
2485
    {
2486
        prog_ok = DWT_ERROR;
2487
    }
2488
2489
    _dwt_otpsetmrregs(0); // Setting OTP mode register for low RM read - resetting the device would be alternative
2490
2491
    return prog_ok;
2492
}
2493
2494
/*! ------------------------------------------------------------------------------------------------------------------
2495
 * @fn _dwt_aonconfigupload()
2496
 *
2497
 * @brief This function uploads always on (AON) configuration, as set in the AON_CFG0_OFFSET register.
2498
 *
2499
 * input parameters
2500
 *
2501
 * output parameters
2502
 *
2503
 * no return value
2504
 */
2505
void _dwt_aonconfigupload(void)
2506
{
2507
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_UPL_CFG);
2508
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00); // Clear the register
2509
}
2510
2511
/*! ------------------------------------------------------------------------------------------------------------------
2512
 * @fn _dwt_aonarrayupload()
2513
 *
2514
 * @brief This function uploads always on (AON) data array and configuration. Thus if this function is used, then _dwt_aonconfigupload
2515
 * is not necessary. The DW1000 will go so SLEEP straight after this if the DWT_SLP_EN has been set.
2516
 *
2517
 * input parameters
2518
 *
2519
 * output parameters
2520
 *
2521
 * no return value
2522
 */
2523
void _dwt_aonarrayupload(void)
2524
{
2525
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00); // Clear the register
2526
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_SAVE);
2527
}
2528
2529
/*! ------------------------------------------------------------------------------------------------------------------
2530
 * @fn dwt_entersleep()
2531
 *
2532
 * @brief This function puts the device into deep sleep or sleep. dwt_configuresleep() should be called first
2533
 * to configure the sleep and on-wake/wake-up parameters
2534
 *
2535
 * input parameters
2536
 *
2537
 * output parameters
2538
 *
2539
 * no return value
2540
 */
2541
void dwt_entersleep(void)
2542
{
2543
    // Copy config to AON - upload the new configuration
2544
    _dwt_aonarrayupload();
2545
}
2546
2547
/*! ------------------------------------------------------------------------------------------------------------------
2548
 * @fn dwt_configuresleepcnt()
2549
 *
2550
 * @brief sets the sleep counter to new value, this function programs the high 16-bits of the 28-bit counter
2551
 *
2552
 * NOTE: this function needs to be run before dwt_configuresleep, also the SPI frequency has to be < 3MHz
2553
 *
2554
 * input parameters
2555
 * @param sleepcnt - this it value of the sleep counter to program
2556
 *
2557
 * output parameters
2558
 *
2559
 * no return value
2560
 */
2561
void dwt_configuresleepcnt(uint16_t sleepcnt)
2562
{
2563
    // Force system clock to crystal
2564
    _dwt_enableclocks(FORCE_SYS_XTI);
2565
2566
    // Reset sleep configuration to make sure we don't accidentally go to sleep
2567
    dwt_write8bitoffsetreg(AON_ID, AON_CFG0_OFFSET, 0x00); // NB: this write change the default LPCLKDIVA value which is not used anyway.
2568
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, 0x00);
2569
2570
    // Disable the sleep counter
2571
    _dwt_aonconfigupload();
2572
2573
    // Set new value
2574
    dwt_write16bitoffsetreg(AON_ID, AON_CFG0_OFFSET + AON_CFG0_SLEEP_TIM_OFFSET, sleepcnt);
2575
    _dwt_aonconfigupload();
2576
2577
    // Enable the sleep counter
2578
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, AON_CFG1_SLEEP_CEN);
2579
    _dwt_aonconfigupload();
2580
2581
    // Put system PLL back on
2582
    _dwt_enableclocks(ENABLE_ALL_SEQ);
2583
}
2584
2585
2586
/*! ------------------------------------------------------------------------------------------------------------------
2587
 * @fn dwt_calibratesleepcnt()
2588
 *
2589
 * @brief calibrates the local oscillator as its frequency can vary between 7 and 13kHz depending on temp and voltage
2590
 *
2591
 * NOTE: this function needs to be run before dwt_configuresleepcnt, so that we know what the counter units are
2592
 *
2593
 * input parameters
2594
 *
2595
 * output parameters
2596
 *
2597
 * returns the number of XTAL/2 cycles per low-power oscillator cycle. LP OSC frequency = 19.2 MHz/return value
2598
 */
2599
uint16_t dwt_calibratesleepcnt(void)
2600
{
2601
    uint16_t result;
2602
2603
    // Enable calibration of the sleep counter
2604
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, AON_CFG1_LPOSC_CAL);
2605
    _dwt_aonconfigupload();
2606
2607
    // Disable calibration of the sleep counter
2608
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, 0x00);
2609
    _dwt_aonconfigupload();
2610
2611
    // Force system clock to crystal
2612
    _dwt_enableclocks(FORCE_SYS_XTI);
2613
2614
    deca_sleep(1);
2615
2616
    // Read the number of XTAL/2 cycles one LP oscillator cycle took.
2617
    // Set up address - Read upper byte first
2618
    dwt_write8bitoffsetreg(AON_ID, AON_ADDR_OFFSET, AON_ADDR_LPOSC_CAL_1);
2619
2620
    // Enable manual override
2621
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB);
2622
2623
    // Read confirm data that was written
2624
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB | AON_CTRL_DCA_READ);
2625
2626
    // Read back byte from AON
2627
    result = dwt_read8bitoffsetreg(AON_ID, AON_RDAT_OFFSET);
2628
    result <<= 8;
2629
2630
    // Set up address - Read lower byte
2631
    dwt_write8bitoffsetreg(AON_ID, AON_ADDR_OFFSET, AON_ADDR_LPOSC_CAL_0);
2632
2633
    // Enable manual override
2634
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB);
2635
2636
    // Read confirm data that was written
2637
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB | AON_CTRL_DCA_READ);
2638
2639
    // Read back byte from AON
2640
    result |= dwt_read8bitoffsetreg(AON_ID, AON_RDAT_OFFSET);
2641
2642
    // Disable manual override
2643
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00);
2644
2645
    // Put system PLL back on
2646
    _dwt_enableclocks(ENABLE_ALL_SEQ);
2647
2648
    // Returns the number of XTAL/2 cycles per one LP OSC cycle
2649
    // This can be converted into LP OSC frequency by 19.2 MHz/result
2650
    return result;
2651
}
2652
2653
/*! ------------------------------------------------------------------------------------------------------------------
2654
 * @fn dwt_configuresleep()
2655
 *
2656
 * @brief configures the device for both DEEP_SLEEP and SLEEP modes, and on-wake mode
2657
 * i.e. before entering the sleep, the device should be programmed for TX or RX, then upon "waking up" the TX/RX settings
2658
 * will be preserved and the device can immediately perform the desired action TX/RX
2659
 *
2660
 * NOTE: e.g. Tag operation - after deep sleep, the device needs to just load the TX buffer and send the frame
2661
 *
2662
 *
2663
 *      mode: the array and LDE code (OTP/ROM) and LDO tune, and set sleep persist
2664
 *      DWT_PRESRV_SLEEP 0x0100 - preserve sleep
2665
 *      DWT_LOADOPSET    0x0080 - load operating parameter set on wakeup
2666
 *      DWT_CONFIG       0x0040 - download the AON array into the HIF (configuration download)
2667
 *      DWT_LOADEUI      0x0008
2668
 *      DWT_GOTORX       0x0002
2669
 *      DWT_TANDV        0x0001
2670
 *
2671
 *      wake: wake up parameters
2672
 *      DWT_XTAL_EN      0x10 - keep XTAL running during sleep
2673
 *      DWT_WAKE_SLPCNT  0x8 - wake up after sleep count
2674
 *      DWT_WAKE_CS      0x4 - wake up on chip select
2675
 *      DWT_WAKE_WK      0x2 - wake up on WAKEUP PIN
2676
 *      DWT_SLP_EN       0x1 - enable sleep/deep sleep functionality
2677
 *
2678
 * input parameters
2679
 * @param mode - config on-wake parameters
2680
 * @param wake - config wake up parameters
2681
 *
2682
 * output parameters
2683
 *
2684
 * no return value
2685
 */
2686
void dwt_configuresleep(uint16_t mode, uint8_t wake)
2687
{
2688
    // Add predefined sleep settings before writing the mode
2689
    mode |= pdw1000local->sleep_mode;
2690
    dwt_write16bitoffsetreg(AON_ID, AON_WCFG_OFFSET, mode);
2691
2692
    dwt_write8bitoffsetreg(AON_ID, AON_CFG0_OFFSET, wake);
2693
}
2694
2695
/*! ------------------------------------------------------------------------------------------------------------------
2696
 * @fn dwt_entersleepaftertx(int enable)
2697
 *
2698
 * @brief sets the auto TX to sleep bit. This means that after a frame
2699
 * transmission the device will enter deep sleep mode. The dwt_configuresleep() function
2700
 * needs to be called before this to configure the on-wake settings
2701
 *
2702
 * NOTE: the IRQ line has to be low/inactive (i.e. no pending events)
2703
 *
2704
 * input parameters
2705
 * @param enable - 1 to configure the device to enter deep sleep after TX, 0 - disables the configuration
2706
 *
2707
 * output parameters
2708
 *
2709
 * no return value
2710
 */
2711
void dwt_entersleepaftertx(int enable)
2712
{
2713
    uint32_t reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET);
2714
    // Set the auto TX -> sleep bit
2715
    if(enable)
2716
    {
2717
        reg |= PMSC_CTRL1_ATXSLP;
2718
    }
2719
    else
2720
    {
2721
        reg &= ~(PMSC_CTRL1_ATXSLP);
2722
    }
2723
    dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, reg);
2724
}
2725
2726
2727
/*! ------------------------------------------------------------------------------------------------------------------
2728
 * @fn dwt_spicswakeup()
2729
 *
2730
 * @brief wake up the device from sleep mode using the SPI read,
2731
 * the device will wake up on chip select line going low if the line is held low for at least 500us.
2732
 * To define the length depending on the time one wants to hold
2733
 * the chip select line low, use the following formula:
2734
 *
2735
 *      length (bytes) = time (s) * byte_rate (Hz)
2736
 *
2737
 * where fastest byte_rate is spi_rate (Hz) / 8 if the SPI is sending the bytes back-to-back.
2738
 * To save time and power, a system designer could determine byte_rate value more precisely.
2739
 *
2740
 * NOTE: Alternatively the device can be waken up with WAKE_UP pin if configured for that operation
2741
 *
2742
 * input parameters
2743
 * @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
2744
 * @param length - this is the length of the dummy buffer
2745
 *
2746
 * output parameters
2747
 *
2748
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2749
 */
2750
int dwt_spicswakeup(uint8_t *buff, uint16_t length)
2751
{
2752
    if(dwt_readdevid() != DWT_DEVICE_ID) // Device was in deep sleep (the first read fails)
2753
    {
2754
        // Need to keep chip select line low for at least 500us
2755
        dwt_readfromdevice(0x0, 0x0, length, buff); // Do a long read to wake up the chip (hold the chip select low)
2756
2757
        // Need 5ms for XTAL to start and stabilise (could wait for PLL lock IRQ status bit !!!)
2758
        // NOTE: Polling of the STATUS register is not possible unless frequency is < 3MHz
2759
        deca_sleep(5);
2760
    }
2761
    else
2762
    {
2763
        return DWT_SUCCESS;
2764
    }
2765
    // DEBUG - check if still in sleep mode
2766
    if(dwt_readdevid() != DWT_DEVICE_ID)
2767
    {
2768
        return DWT_ERROR;
2769
    }
2770
2771
    return DWT_SUCCESS;
2772
}
2773
2774
/*! ------------------------------------------------------------------------------------------------------------------
2775
 * @fn _dwt_configlde()
2776
 *
2777
 * @brief configure LDE algorithm parameters
2778
 *
2779
 * input parameters
2780
 * @param prf   -   this is the PRF index (0 or 1) 0 corresponds to 16 and 1 to 64 PRF
2781
 *
2782
 * output parameters
2783
 *
2784
 * no return value
2785
 */
2786
void _dwt_configlde(int prfIndex)
2787
{
2788
    dwt_write8bitoffsetreg(LDE_IF_ID, LDE_CFG1_OFFSET, LDE_PARAM1); // 8-bit configuration register
2789
2790
    if(prfIndex)
2791
    {
2792
        dwt_write16bitoffsetreg( LDE_IF_ID, LDE_CFG2_OFFSET, (uint16_t) LDE_PARAM3_64); // 16-bit LDE configuration tuning register
2793
    }
2794
    else
2795
    {
2796
        dwt_write16bitoffsetreg( LDE_IF_ID, LDE_CFG2_OFFSET, (uint16_t) LDE_PARAM3_16);
2797
    }
2798
}
2799
2800
2801
/*! ------------------------------------------------------------------------------------------------------------------
2802
 * @fn _dwt_loaducodefromrom()
2803
 *
2804
 * @brief  load ucode from OTP MEMORY or ROM
2805
 *
2806
 * input parameters
2807
 *
2808
 * output parameters
2809
 *
2810
 * no return value
2811
 */
2812
void _dwt_loaducodefromrom(void)
2813
{
2814
    // Set up clocks
2815
    _dwt_enableclocks(FORCE_LDE);
2816
2817
    // Kick off the LDE load
2818
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_CTRL, OTP_CTRL_LDELOAD); // Set load LDE kick bit
2819
2820
    deca_sleep(1); // Allow time for code to upload (should take up to 120 us)
2821
2822
    // Default clocks (ENABLE_ALL_SEQ)
2823
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
2824
}
2825
2826
/*! ------------------------------------------------------------------------------------------------------------------
2827
 * @fn dwt_loadopsettabfromotp()
2828
 *
2829
 * @brief This is used to select which Operational Parameter Set table to load from OTP memory
2830
 *
2831
 * input parameters
2832
 * @param ops_sel - Operational Parameter Set table to load:
2833
 *                  DWT_OPSET_64LEN = 0x0 - load the operational parameter set table for 64 length preamble configuration
2834
 *                  DWT_OPSET_TIGHT = 0x1 - load the operational parameter set table for tight xtal offsets (<1ppm)
2835
 *                  DWT_OPSET_DEFLT = 0x2 - load the default operational parameter set table (this is loaded from reset)
2836
 *
2837
 * output parameters
2838
 *
2839
 * no return value
2840
 */
2841
void dwt_loadopsettabfromotp(uint8_t ops_sel)
2842
{
2843
    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
2844
2845
    // Set up clocks
2846
    _dwt_enableclocks(FORCE_LDE);
2847
2848
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_SF, reg);
2849
2850
    // Default clocks (ENABLE_ALL_SEQ)
2851
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
2852
2853
}
2854
2855
/*! ------------------------------------------------------------------------------------------------------------------
2856
 * @fn dwt_setsmarttxpower()
2857
 *
2858
 * @brief This call enables or disables the smart TX power feature.
2859
 *
2860
 * input parameters
2861
 * @param enable - this enables or disables the TX smart power (1 = enable, 0 = disable)
2862
 *
2863
 * output parameters
2864
 *
2865
 * no return value
2866
 */
2867
void dwt_setsmarttxpower(int enable)
2868
{
2869
    // Config system register
2870
    pdw1000local->sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
2871
2872
    // Disable smart power configuration
2873
    if(enable)
2874
    {
2875
        pdw1000local->sysCFGreg &= ~(SYS_CFG_DIS_STXP) ;
2876
    }
2877
    else
2878
    {
2879
        pdw1000local->sysCFGreg |= SYS_CFG_DIS_STXP ;
2880
    }
2881
2882
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2883
}
2884
2885
2886
/*! ------------------------------------------------------------------------------------------------------------------
2887
 * @fn dwt_enableautoack()
2888
 *
2889
 * @brief This call enables the auto-ACK feature. If the responseDelayTime (parameter) is 0, the ACK will be sent a.s.a.p.
2890
 * otherwise it will be sent with a programmed delay (in symbols), max is 255.
2891
 * NOTE: needs to have frame filtering enabled as well
2892
 *
2893
 * input parameters
2894
 * @param responseDelayTime - if non-zero the ACK is sent after this delay, max is 255.
2895
 *
2896
 * output parameters
2897
 *
2898
 * no return value
2899
 */
2900
void dwt_enableautoack(uint8_t responseDelayTime)
2901
{
2902
    // Set auto ACK reply delay
2903
    dwt_write8bitoffsetreg(ACK_RESP_T_ID, ACK_RESP_T_ACK_TIM_OFFSET, responseDelayTime); // In symbols
2904
    // Enable auto ACK
2905
    pdw1000local->sysCFGreg |= SYS_CFG_AUTOACK;
2906
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2907
}
2908
2909
/*! ------------------------------------------------------------------------------------------------------------------
2910
 * @fn dwt_setdblrxbuffmode()
2911
 *
2912
 * @brief This call enables the double receive buffer mode
2913
 *
2914
 * input parameters
2915
 * @param enable - 1 to enable, 0 to disable the double buffer mode
2916
 *
2917
 * output parameters
2918
 *
2919
 * no return value
2920
 */
2921
void dwt_setdblrxbuffmode(int enable)
2922
{
2923
    if(enable)
2924
    {
2925
        // Enable double RX buffer mode
2926
        pdw1000local->sysCFGreg &= ~SYS_CFG_DIS_DRXB;
2927
        pdw1000local->dblbuffon = 1;
2928
    }
2929
    else
2930
    {
2931
        // Disable double RX buffer mode
2932
        pdw1000local->sysCFGreg |= SYS_CFG_DIS_DRXB;
2933
        pdw1000local->dblbuffon = 0;
2934
    }
2935
2936
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2937
}
2938
2939
/*! ------------------------------------------------------------------------------------------------------------------
2940
 * @fn dwt_setrxaftertxdelay()
2941
 *
2942
 * @brief This sets the receiver turn on delay time after a transmission of a frame
2943
 *
2944
 * input parameters
2945
 * @param rxDelayTime - (20 bits) - the delay is in UWB microseconds
2946
 *
2947
 * output parameters
2948
 *
2949
 * no return value
2950
 */
2951
void dwt_setrxaftertxdelay(uint32_t rxDelayTime)
2952
{
2953
    uint32_t val = dwt_read32bitreg(ACK_RESP_T_ID) ; // Read ACK_RESP_T_ID register
2954
2955
    val &= ~(ACK_RESP_T_W4R_TIM_MASK) ; // Clear the timer (19:0)
2956
2957
    val |= (rxDelayTime & ACK_RESP_T_W4R_TIM_MASK) ; // In UWB microseconds (e.g. turn the receiver on 20uus after TX)
2958
2959
    dwt_write32bitreg(ACK_RESP_T_ID, val) ;
2960
}
2961
2962
/*! ------------------------------------------------------------------------------------------------------------------
2963
 * @fn dwt_setcallbacks()
2964
 *
2965
 * @brief This function is used to register the different callbacks called when one of the corresponding event occurs.
2966
 *
2967
 * NOTE: Callbacks can be undefined (set to NULL). In this case, dwt_isr() will process the event as usual but the 'null'
2968
 * callback will not be called.
2969
 *
2970
 * input parameters
2971
 * @param cbTxDone - the pointer to the TX confirmation event callback function
2972
 * @param cbRxOk - the pointer to the RX good frame event callback function
2973
 * @param cbRxTo - the pointer to the RX timeout events callback function
2974
 * @param cbRxErr - the pointer to the RX error events callback function
2975
 *
2976
 * output parameters
2977
 *
2978
 * no return value
2979
 */
2980
void dwt_setcallbacks(dwt_cb_t cbTxDone, dwt_cb_t cbRxOk, dwt_cb_t cbRxTo, dwt_cb_t cbRxErr)
2981
{
2982
    pdw1000local->cbTxDone = cbTxDone;
2983
    pdw1000local->cbRxOk = cbRxOk;
2984
    pdw1000local->cbRxTo = cbRxTo;
2985
    pdw1000local->cbRxErr = cbRxErr;
2986
}
2987
2988
/*! ------------------------------------------------------------------------------------------------------------------
2989
 * @fn dwt_checkirq()
2990
 *
2991
 * @brief This function checks if the IRQ line is active - this is used instead of interrupt handler
2992
 *
2993
 * input parameters
2994
 *
2995
 * output parameters
2996
 *
2997
 * return value is 1 if the IRQS bit is set and 0 otherwise
2998
 */
2999
uint8_t dwt_checkirq(void)
3000
{
3001
    return (dwt_read8bitoffsetreg(SYS_STATUS_ID, SYS_STATUS_OFFSET) & SYS_STATUS_IRQS); // Reading the lower byte only is enough for this operation
3002
}
3003
3004
/*! ------------------------------------------------------------------------------------------------------------------
3005
 * @fn dwt_isr()
3006
 *
3007
 * @brief This is the DW1000's general Interrupt Service Routine. It will process/report the following events:
3008
 *          - RXFCG (through cbRxOk callback)
3009
 *          - TXFRS (through cbTxDone callback)
3010
 *          - RXRFTO/RXPTO (through cbRxTo callback)
3011
 *          - RXPHE/RXFCE/RXRFSL/RXSFDTO/AFFREJ/LDEERR (through cbRxTo cbRxErr)
3012
 *        For all events, corresponding interrupts are cleared and necessary resets are performed. In addition, in the RXFCG case,
3013
 *        received frame information and frame control are read before calling the callback. If double buffering is activated, it
3014
 *        will also toggle between reception buffers once the reception callback processing has ended.
3015
 *
3016
 *        /!\ This version of the ISR supports double buffering but does not support automatic RX re-enabling!
3017
 *
3018
 * NOTE:  In PC based system using (Cheetah or ARM) USB to SPI converter there can be no interrupts, however we still need something
3019
 *        to take the place of it and operate in a polled way. In an embedded system this function should be configured to be triggered
3020
 *        on any of the interrupts described above.
3021

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

4411
    0xDECA0130                               // DW1000 - MP
4412

4413
   ===============================================================================================
4414
*/
4415
4416
/****************************************************************************************************************************************************
4417
 *
4418
 * Declaration of platform-dependent lower level functions.
4419
 *
4420
 ****************************************************************************************************************************************************/
4421
4422
/*
4423
 * DW1000 Hardware dependent functions: SPI, EXTI
4424
 */
4425
4426
/*! ------------------------------------------------------------------------------------------------------------------
4427
 * Function: writetospi()
4428
 *
4429
 * Low level abstract function for DW1000 to write to the SPI
4430
 * Takes two separate byte buffers for write header and write data
4431
 * returns 0 for success, or -1 for error
4432
 */
4433
#pragma GCC optimize ("O3")
4434
int writetospi(uint16_t headerLength,
4435
               const        uint8_t *headerBuffer,
4436
               uint32_t bodyLength,
4437
               const        uint8_t *bodyBuffer)
4438
{
4439
4440
    port_SPIx_clear_chip_select();
4441
4442
    uint8_t buffer[bodyLength + 3];
4443
    memcpy(buffer, headerBuffer, headerLength); //copy data to buffer
4444
    memcpy(&buffer[headerLength], bodyBuffer, bodyLength); //copy data to buffer
4445
4446
    apalSPITransmit(&MODULE_HAL_SPI_UWB,
4447
                    buffer,
4448
                    bodyLength + headerLength); // send header and data
4449
4450
    port_SPIx_set_chip_select();
4451
4452
    return 0;
4453
} // end writetospi()
4454
4455
4456
4457
/*! ------------------------------------------------------------------------------------------------------------------
4458
 * Function: readfromspi()
4459
 *
4460
 * Low level abstract function for DW1000 to read from the SPI
4461
 * Takes two separate byte buffers for write header and read data
4462
 * returns the offset into read buffer where first byte of read data may be found,
4463
 * or returns -1 if there was an error
4464
 */
4465
#pragma GCC optimize ("O3")
4466
int readfromspi(uint16_t headerLength,
4467
                const uint8_t *headerBuffer,
4468
                uint32_t readlength,
4469
                uint8_t *readBuffer)
4470
{
4471
4472
    apalSPITransmitAndReceive(&MODULE_HAL_SPI_UWB,
4473
                              headerBuffer,
4474
                              readBuffer,
4475
                              headerLength,
4476
                              readlength);
4477
4478
    return 0;
4479
} // end readfromspi()
4480
4481
/****************************************************************************//**
4482
 *
4483
 *         alld_dw1000.c                                        IRQ section
4484
 *
4485
 *******************************************************************************/
4486
4487
4488
/*! ------------------------------------------------------------------------------------------------------------------
4489
 * Function: decamutexon()
4490
 *
4491
 * Description: This function should disable interrupts. This is called at the start of a critical section
4492
 * It returns the irq state before disable, this value is used to re-enable in decamutexoff call
4493
 *
4494
 * Note: The body of this function is platform specific
4495
 *
4496
 * input parameters:        
4497
 *
4498
 * output parameters
4499
 *
4500
 * returns the state of the DW1000 interrupt
4501
 */
4502
decaIrqStatus_t decamutexon(void)           
4503
{
4504
    decaIrqStatus_t s = port_GetEXT_IRQStatus();
4505
4506
    if(s) {
4507
        port_DisableEXT_IRQ(); //disable the external interrupt line
4508
    }
4509
    return s ;   // return state before disable, value is used to re-enable in decamutexoff call
4510
}
4511
4512
/*! ------------------------------------------------------------------------------------------------------------------
4513
 * Function: decamutexoff()
4514
 *
4515
 * Description: This function should re-enable interrupts, or at least restore their state as returned(&saved) by decamutexon 
4516
 * This is called at the end of a critical section
4517
 *
4518
 * Note: The body of this function is platform specific
4519
 *
4520
 * input parameters:        
4521
 * @param s - the state of the DW1000 interrupt as returned by decamutexon
4522
 *
4523
 * output parameters
4524
 *
4525
 * returns the state of the DW1000 interrupt
4526
 */
4527
void decamutexoff(decaIrqStatus_t s)
4528
{
4529
//    (void) s;
4530
    if(s) { //need to check the port state as we can't use level sensitive interrupt on the STM ARM
4531
      port_EnableEXT_IRQ();
4532
    }
4533
//    return;
4534
}
4535
4536
4537
/*! Wrapper function to be used by decadriver. Declared in deca_device_api.h 
4538
 *
4539
 */
4540
4541
void deca_sleep(unsigned int time_ms)
4542
{
4543
    aosThdMSleep(time_ms);
4544
}
4545
4546
void Sleep(unsigned int time_ms)
4547
{
4548
    aosThdMSleep(time_ms);
4549
}
4550
4551
4552
void port_set_dw1000_slowrate(){ // replaced with setHighSpeed_SPI(bool speedValue) implemented in module.c
4553
    return;
4554
}
4555
4556
void port_set_dw1000_fastrate(){ // replaced with setHighSpeed_SPI(bool speedValue) implemented in module.c
4557
    return;
4558
}
4559
4560
void port_wakeup_dw1000_fast(){ // NOT SUPPORTED
4561
    return;
4562
}
4563
4564
uint32_t portGetTickCnt(){
4565
    return chVTGetSystemTimeX();
4566
}
4567
4568
//inline uint32_t portGetTickCnt(){
4569
//    return (uint32_t) chVTGetSystemTimeX();
4570
//}
4571
4572
4573
void port_DisableEXT_IRQ(void){   
4574
   nvicDisableVector(DW1000_EXTI_IRQn);
4575
4576
}
4577
4578
void port_EnableEXT_IRQ(void){    
4579
    nvicEnableVector(DW1000_EXTI_IRQn, STM32_IRQ_EXTI10_15_PRIORITY);
4580
}
4581
4582
4583
ITStatus port_GetEXT_IRQStatus(void){
4584
  ITStatus bitstatus = RESET;
4585
  //  uint32_t enablestatus = 0;
4586
4587
  if(NVIC_GetActive(DW1000_EXTI_IRQn)|| NVIC_GetPendingIRQ(DW1000_EXTI_IRQn)){
4588
    //  if(NVIC_GetPendingIRQ(EXTI15_10_IRQn)){ //if the interrupt is pending (background )
4589
    bitstatus = SET; //Interrupt is active or panding
4590
  }
4591
  else {
4592
    bitstatus = RESET; //Currently there is no interrupt IRQ
4593
  }
4594
4595
  return bitstatus;
4596
}
4597
4598
4599
4600
#endif /* defined(AMIROLLD_CFG_DW1000) && (AMIROLLD_CFG_DW1000 == 1) */