Statistics
| Branch: | Tag: | Revision:

amiro-lld / source / DW1000 / v0 / alld_DW100_v0.c @ 26dead12

History | View | Annotate | Download (150.762 KB)

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

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

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

4415
    0xDECA0130                               // DW1000 - MP
4416

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