Statistics
| Branch: | Tag: | Revision:

amiro-lld / source / DW1000 / v1 / alld_dw1000_v1.c @ 26dead12

History | View | Annotate | Download (151.037 KB)

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

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

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

15
You should have received a copy of the GNU Lesser General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18

    
19
/*! ------------------------------------------------------------------------------------------------------------------
20
 * @file    deca_device.c
21
 * @brief   Decawave device configuration and control functions
22
 *
23
 * @attention
24
 *
25
 * Copyright 2013 (c) Decawave Ltd, Dublin, Ireland.
26
 *
27
 * All rights reserved.
28
 *
29
 */
30

    
31
#include <alld_DW1000.h>
32
#if (defined(AMIROLLD_CFG_DW1000) && (AMIROLLD_CFG_DW1000 == 1)) || defined(__DOXYGEN__)
33

    
34
#include <v1/alld_dw1000_regs_v1.h>
35
#include <assert.h>
36
#include <string.h>
37
#include <stdlib.h>
38
#include <math.h>
39

    
40

    
41
// HW dependent implementation (see bottom of file)
42
static int writetospi(uint16_t headerLength,
43
               const        uint8_t *headerBuffer,
44
               uint32_t bodyLength,
45
               const        uint8_t *bodyBuffer);
46

    
47
static int readfromspi(uint16_t headerLength,
48
                const uint8_t *headerBuffer,
49
                uint32_t readlength,
50
                uint8_t *readBuffer);
51

    
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
typedef struct {
71
    uint32_t lo32;
72
    uint16_t target[NUM_PRF];
73
} agc_cfg_struct ;
74

    
75
extern const agc_cfg_struct agc_config ;
76

    
77
//SFD threshold settings for 110k, 850k, 6.8Mb standard and non-standard
78
extern const uint16_t sftsh[NUM_BR][NUM_SFD];
79

    
80
extern const uint16_t dtune1[NUM_PRF];
81

    
82
#define XMLPARAMS_VERSION   (1.17f)
83

    
84
extern const uint32_t fs_pll_cfg[NUM_CH];
85
extern const uint8_t fs_pll_tune[NUM_CH];
86
extern const uint8_t rx_config[NUM_BW];
87
extern const uint32_t tx_config[NUM_CH];
88
extern const uint8_t dwnsSFDlen[NUM_BR]; //length of SFD for each of the bitrates
89
extern const uint32_t digital_bb_config[NUM_PRF][NUM_PACS];
90
//extern const uint8_t chan_idx[NUM_CH_SUPPORTED]; // move to header file
91
extern const double txpwr_compensation[NUM_CH];
92

    
93
#define PEAK_MULTPLIER  (0x60) //3 -> (0x3 * 32) & 0x00E0
94
#define N_STD_FACTOR    (13)
95
#define LDE_PARAM1      (PEAK_MULTPLIER | N_STD_FACTOR)
96

    
97
#define LDE_PARAM3_16 (0x1607)
98
#define LDE_PARAM3_64 (0x0607)
99

    
100
#define MIXER_GAIN_STEP (0.5)
101
#define DA_ATTN_STEP    (2.5)
102

    
103
// #define DWT_API_ERROR_CHECK     // define so API checks config input parameters
104

    
105
//-----------------------------------------
106
// map the channel number to the index in the configuration arrays below
107
// 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
108
const uint8_t chan_idx[NUM_CH_SUPPORTED] = {0, 0, 1, 2, 3, 4, 0, 5};
109

    
110
//-----------------------------------------
111
const uint32_t tx_config[NUM_CH] =
112
{
113
    RF_TXCTRL_CH1,
114
    RF_TXCTRL_CH2,
115
    RF_TXCTRL_CH3,
116
    RF_TXCTRL_CH4,
117
    RF_TXCTRL_CH5,
118
    RF_TXCTRL_CH7,
119
};
120

    
121
//Frequency Synthesiser - PLL configuration
122
const uint32_t fs_pll_cfg[NUM_CH] =
123
{
124
    FS_PLLCFG_CH1,
125
    FS_PLLCFG_CH2,
126
    FS_PLLCFG_CH3,
127
    FS_PLLCFG_CH4,
128
    FS_PLLCFG_CH5,
129
    FS_PLLCFG_CH7
130
};
131

    
132
//Frequency Synthesiser - PLL tuning
133
const uint8_t fs_pll_tune[NUM_CH] =
134
{
135
    FS_PLLTUNE_CH1,
136
    FS_PLLTUNE_CH2,
137
    FS_PLLTUNE_CH3,
138
    FS_PLLTUNE_CH4,
139
    FS_PLLTUNE_CH5,
140
    FS_PLLTUNE_CH7
141
};
142

    
143
//bandwidth configuration
144
const uint8_t rx_config[NUM_BW] =
145
{
146
    RF_RXCTRLH_NBW,
147
    RF_RXCTRLH_WBW
148
};
149

    
150

    
151
const agc_cfg_struct agc_config =
152
{
153
    AGC_TUNE2_VAL,
154
    { AGC_TUNE1_16M , AGC_TUNE1_64M }  //adc target
155
};
156

    
157
//DW non-standard SFD length for 110k, 850k and 6.81M
158
const uint8_t dwnsSFDlen[NUM_BR] =
159
{
160
    DW_NS_SFD_LEN_110K,
161
    DW_NS_SFD_LEN_850K,
162
    DW_NS_SFD_LEN_6M8
163
};
164

    
165
// SFD Threshold
166
const uint16_t sftsh[NUM_BR][NUM_SFD] =
167
{
168
    {
169
        DRX_TUNE0b_110K_STD,
170
        DRX_TUNE0b_110K_NSTD
171
    },
172
    {
173
        DRX_TUNE0b_850K_STD,
174
        DRX_TUNE0b_850K_NSTD
175
    },
176
    {
177
        DRX_TUNE0b_6M8_STD,
178
        DRX_TUNE0b_6M8_NSTD
179
    }
180
};
181

    
182
const uint16_t dtune1[NUM_PRF] =
183
{
184
    DRX_TUNE1a_PRF16,
185
    DRX_TUNE1a_PRF64
186
};
187

    
188
const uint32_t digital_bb_config[NUM_PRF][NUM_PACS] =
189
{
190
    {
191
        DRX_TUNE2_PRF16_PAC8,
192
        DRX_TUNE2_PRF16_PAC16,
193
        DRX_TUNE2_PRF16_PAC32,
194
        DRX_TUNE2_PRF16_PAC64
195
    },
196
    {
197
        DRX_TUNE2_PRF64_PAC8,
198
        DRX_TUNE2_PRF64_PAC16,
199
        DRX_TUNE2_PRF64_PAC32,
200
        DRX_TUNE2_PRF64_PAC64
201
    }
202
};
203

    
204
const uint16_t lde_replicaCoeff[PCODES] =
205
{
206
    0, // No preamble code 0
207
    LDE_REPC_PCODE_1,
208
    LDE_REPC_PCODE_2,
209
    LDE_REPC_PCODE_3,
210
    LDE_REPC_PCODE_4,
211
    LDE_REPC_PCODE_5,
212
    LDE_REPC_PCODE_6,
213
    LDE_REPC_PCODE_7,
214
    LDE_REPC_PCODE_8,
215
    LDE_REPC_PCODE_9,
216
    LDE_REPC_PCODE_10,
217
    LDE_REPC_PCODE_11,
218
    LDE_REPC_PCODE_12,
219
    LDE_REPC_PCODE_13,
220
    LDE_REPC_PCODE_14,
221
    LDE_REPC_PCODE_15,
222
    LDE_REPC_PCODE_16,
223
    LDE_REPC_PCODE_17,
224
    LDE_REPC_PCODE_18,
225
    LDE_REPC_PCODE_19,
226
    LDE_REPC_PCODE_20,
227
    LDE_REPC_PCODE_21,
228
    LDE_REPC_PCODE_22,
229
    LDE_REPC_PCODE_23,
230
    LDE_REPC_PCODE_24
231
};
232

    
233
const double txpwr_compensation[NUM_CH] = {
234
    0.0,
235
    0.035,
236
    0.0,
237
    0.0,
238
    0.065,
239
    0.0
240
};
241

    
242

    
243
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
244
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
245

    
246
//---------------------------------------------------------------------------------------------------------------------------
247
// Range Bias Correction TABLES of range values in integer units of 25 CM, for 8-bit unsigned storage, MUST END IN 255 !!!!!!
248
//---------------------------------------------------------------------------------------------------------------------------
249

    
250
// offsets to nearest centimeter for index 0, all rest are +1 cm per value
251

    
252
#define CM_OFFSET_16M_NB    (-23)   // for normal band channels at 16 MHz PRF
253
#define CM_OFFSET_16M_WB    (-28)   // for wider  band channels at 16 MHz PRF
254
#define CM_OFFSET_64M_NB    (-17)   // for normal band channels at 64 MHz PRF
255
#define CM_OFFSET_64M_WB    (-30)   // for wider  band channels at 64 MHz PRF
256

    
257

    
258
//---------------------------------------------------------------------------------------------------------------------------
259
// range25cm16PRFnb: Range Bias Correction table for narrow band channels at 16 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
260
//---------------------------------------------------------------------------------------------------------------------------
261

    
262
const uint8_t range25cm16PRFnb[4][NUM_16M_OFFSET] =
263
{
264
    // ch 1 - range25cm16PRFnb
265
    {
266
           1,
267
           3,
268
           4,
269
           5,
270
           7,
271
           9,
272
          11,
273
          12,
274
          13,
275
          15,
276
          18,
277
          20,
278
          23,
279
          25,
280
          28,
281
          30,
282
          33,
283
          36,
284
          40,
285
          43,
286
          47,
287
          50,
288
          54,
289
          58,
290
          63,
291
          66,
292
          71,
293
          76,
294
          82,
295
          89,
296
          98,
297
         109,
298
         127,
299
         155,
300
         222,
301
         255,
302
         255
303
    },
304

    
305
    // ch 2 - range25cm16PRFnb
306
    {
307
           1,
308
           2,
309
           4,
310
           5,
311
           6,
312
           8,
313
           9,
314
          10,
315
          12,
316
          13,
317
          15,
318
          18,
319
          20,
320
          22,
321
          24,
322
          27,
323
          29,
324
          32,
325
          35,
326
          38,
327
          41,
328
          44,
329
          47,
330
          51,
331
          55,
332
          58,
333
          62,
334
          66,
335
          71,
336
          78,
337
          85,
338
          96,
339
         111,
340
         135,
341
         194,
342
         240,
343
         255
344
    },
345

    
346
    // ch 3 - range25cm16PRFnb
347
    {
348
           1,
349
           2,
350
           3,
351
           4,
352
           5,
353
           7,
354
           8,
355
           9,
356
          10,
357
          12,
358
          14,
359
          16,
360
          18,
361
          20,
362
          22,
363
          24,
364
          26,
365
          28,
366
          31,
367
          33,
368
          36,
369
          39,
370
          42,
371
          45,
372
          49,
373
          52,
374
          55,
375
          59,
376
          63,
377
          69,
378
          76,
379
          85,
380
          98,
381
         120,
382
         173,
383
         213,
384
         255
385
    },
386

    
387
    // ch 5 - range25cm16PRFnb
388
    {
389
           1,
390
           1,
391
           2,
392
           3,
393
           4,
394
           5,
395
           6,
396
           6,
397
           7,
398
           8,
399
           9,
400
          11,
401
          12,
402
          14,
403
          15,
404
          16,
405
          18,
406
          20,
407
          21,
408
          23,
409
          25,
410
          27,
411
          29,
412
          31,
413
          34,
414
          36,
415
          38,
416
          41,
417
          44,
418
          48,
419
          53,
420
          59,
421
          68,
422
          83,
423
         120,
424
         148,
425
         255
426
    }
427
}; // end range25cm16PRFnb
428

    
429

    
430
//---------------------------------------------------------------------------------------------------------------------------
431
// range25cm16PRFwb: Range Bias Correction table for wide band channels at 16 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
432
//---------------------------------------------------------------------------------------------------------------------------
433

    
434
const uint8_t range25cm16PRFwb[2][NUM_16M_OFFSETWB] =
435
{
436
    // ch 4 - range25cm16PRFwb
437
    {
438
           7,
439
           7,
440
           8,
441
           9,
442
           9,
443
          10,
444
          11,
445
          11,
446
          12,
447
          13,
448
          14,
449
          15,
450
          16,
451
          17,
452
          18,
453
          19,
454
          20,
455
          21,
456
          22,
457
          23,
458
          24,
459
          26,
460
          27,
461
          28,
462
          30,
463
          31,
464
          32,
465
          34,
466
          36,
467
          38,
468
          40,
469
          42,
470
          44,
471
          46,
472
          48,
473
          50,
474
          52,
475
          55,
476
          57,
477
          59,
478
          61,
479
          63,
480
          66,
481
          68,
482
          71,
483
          74,
484
          78,
485
          81,
486
          85,
487
          89,
488
          94,
489
          99,
490
         104,
491
         110,
492
         116,
493
         123,
494
         130,
495
         139,
496
         150,
497
         164,
498
         182,
499
         207,
500
         238,
501
         255,
502
         255,
503
         255,
504
         255,
505
         255
506
    },
507

    
508
    // ch 7 - range25cm16PRFwb
509
    {
510
           4,
511
           5,
512
           5,
513
           5,
514
           6,
515
           6,
516
           7,
517
           7,
518
           7,
519
           8,
520
           9,
521
           9,
522
          10,
523
          10,
524
          11,
525
          11,
526
          12,
527
          13,
528
          13,
529
          14,
530
          15,
531
          16,
532
          17,
533
          17,
534
          18,
535
          19,
536
          20,
537
          21,
538
          22,
539
          23,
540
          25,
541
          26,
542
          27,
543
          29,
544
          30,
545
          31,
546
          32,
547
          34,
548
          35,
549
          36,
550
          38,
551
          39,
552
          40,
553
          42,
554
          44,
555
          46,
556
          48,
557
          50,
558
          52,
559
          55,
560
          58,
561
          61,
562
          64,
563
          68,
564
          72,
565
          75,
566
          80,
567
          85,
568
          92,
569
         101,
570
         112,
571
         127,
572
         147,
573
         168,
574
         182,
575
         194,
576
         205,
577
         255
578
    }
579
}; // end range25cm16PRFwb
580

    
581
//---------------------------------------------------------------------------------------------------------------------------
582
// range25cm64PRFnb: Range Bias Correction table for narrow band channels at 64 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
583
//---------------------------------------------------------------------------------------------------------------------------
584

    
585
const uint8_t range25cm64PRFnb[4][NUM_64M_OFFSET] =
586
{
587
    // ch 1 - range25cm64PRFnb
588
    {
589
           1,
590
           2,
591
           2,
592
           3,
593
           4,
594
           5,
595
           7,
596
          10,
597
          13,
598
          16,
599
          19,
600
          22,
601
          24,
602
          27,
603
          30,
604
          32,
605
          35,
606
          38,
607
          43,
608
          48,
609
          56,
610
          78,
611
         101,
612
         120,
613
         157,
614
         255
615
    },
616

    
617
    // ch 2 - range25cm64PRFnb
618
    {
619
           1,
620
           2,
621
           2,
622
           3,
623
           4,
624
           4,
625
           6,
626
           9,
627
          12,
628
          14,
629
          17,
630
          19,
631
          21,
632
          24,
633
          26,
634
          28,
635
          31,
636
          33,
637
          37,
638
          42,
639
          49,
640
          68,
641
          89,
642
         105,
643
         138,
644
         255
645
    },
646

    
647
    // ch 3 - range25cm64PRFnb
648
    {
649
           1,
650
           1,
651
           2,
652
           3,
653
           3,
654
           4,
655
           5,
656
           8,
657
          10,
658
          13,
659
          15,
660
          17,
661
          19,
662
          21,
663
          23,
664
          25,
665
          27,
666
          30,
667
          33,
668
          37,
669
          44,
670
          60,
671
          79,
672
          93,
673
         122,
674
         255
675
    },
676

    
677
    // ch 5 - range25cm64PRFnb
678
    {
679
           1,
680
           1,
681
           1,
682
           2,
683
           2,
684
           3,
685
           4,
686
           6,
687
           7,
688
           9,
689
          10,
690
          12,
691
          13,
692
          15,
693
          16,
694
          17,
695
          19,
696
          21,
697
          23,
698
          26,
699
          30,
700
          42,
701
          55,
702
          65,
703
          85,
704
         255
705
    }
706
}; // end range25cm64PRFnb
707

    
708
//---------------------------------------------------------------------------------------------------------------------------
709
// range25cm64PRFwb: Range Bias Correction table for wide band channels at 64 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
710
//---------------------------------------------------------------------------------------------------------------------------
711

    
712
const uint8_t range25cm64PRFwb[2][NUM_64M_OFFSETWB] =
713
{
714
    // ch 4 - range25cm64PRFwb
715
    {
716
           7,
717
           8,
718
           8,
719
           9,
720
           9,
721
          10,
722
          11,
723
          12,
724
          13,
725
          13,
726
          14,
727
          15,
728
          16,
729
          16,
730
          17,
731
          18,
732
          19,
733
          19,
734
          20,
735
          21,
736
          22,
737
          24,
738
          25,
739
          27,
740
          28,
741
          29,
742
          30,
743
          32,
744
          33,
745
          34,
746
          35,
747
          37,
748
          39,
749
          41,
750
          43,
751
          45,
752
          48,
753
          50,
754
          53,
755
          56,
756
          60,
757
          64,
758
          68,
759
          74,
760
          81,
761
          89,
762
          98,
763
         109,
764
         122,
765
         136,
766
         146,
767
         154,
768
         162,
769
         178,
770
         220,
771
         249,
772
         255,
773
         255,
774
         255
775
    },
776

    
777
    // ch 7 - range25cm64PRFwb
778
    {
779
           4,
780
           5,
781
           5,
782
           5,
783
           6,
784
           6,
785
           7,
786
           7,
787
           8,
788
           8,
789
           9,
790
           9,
791
          10,
792
          10,
793
          10,
794
          11,
795
          11,
796
          12,
797
          13,
798
          13,
799
          14,
800
          15,
801
          16,
802
          16,
803
          17,
804
          18,
805
          19,
806
          19,
807
          20,
808
          21,
809
          22,
810
          23,
811
          24,
812
          25,
813
          26,
814
          28,
815
          29,
816
          31,
817
          33,
818
          35,
819
          37,
820
          39,
821
          42,
822
          46,
823
          50,
824
          54,
825
          60,
826
          67,
827
          75,
828
          83,
829
          90,
830
          95,
831
         100,
832
         110,
833
         135,
834
         153,
835
         172,
836
         192,
837
         255
838
    }
839
}; // end range25cm64PRFwb
840

    
841

    
842
/*! ------------------------------------------------------------------------------------------------------------------
843
 * Function: dwt_getrangebias()
844
 *
845
 * Description: This function is used to return the range bias correction need for TWR with DW1000 units.
846
 *
847
 * input parameters:        
848
 * @param chan  - specifies the operating channel (e.g. 1, 2, 3, 4, 5, 6 or 7) 
849
 * @param range - the calculated distance before correction
850
 * @param prf        - this is the PRF e.g. DWT_PRF_16M or DWT_PRF_64M
851
 *
852
 * output parameters
853
 *
854
 * returns correction needed in meters
855
 */
856
double dwt_getrangebias(uint8_t chan, float range, uint8_t prf)
857
{
858
    //first get the lookup index that corresponds to given range for a particular channel at 16M PRF
859
    int i = 0 ;
860
    int chanIdx ;
861
    int cmoffseti ;                                 // integer number of CM offset
862

    
863
    double mOffset ;                                // final offset result in metres
864

    
865
    // NB: note we may get some small negitive values e.g. up to -50 cm.
866

    
867
    int rangeint25cm = (int) ((double)range * 4.00) ;       // convert range to integer number of 25cm values.
868

    
869
    if (rangeint25cm > 255) rangeint25cm = 255 ;    // make sure it matches largest value in table (all tables end in 255 !!!!)
870

    
871
    if (prf == DWT_PRF_16M)
872
    {
873
        switch(chan)
874
        {
875
            case 4:
876
            case 7:
877
            {
878
                chanIdx = chan_idxwb[chan];
879
                while (rangeint25cm > range25cm16PRFwb[chanIdx][i]) i++ ;       // find index in table corresponding to range
880
                cmoffseti = i + CM_OFFSET_16M_WB ;                              // nearest centimeter correction
881
            }
882
            break;
883
            default:
884
            {
885
                chanIdx = chan_idxnb[chan];
886
                while (rangeint25cm > range25cm16PRFnb[chanIdx][i]) i++ ;       // find index in table corresponding to range
887
                cmoffseti = i + CM_OFFSET_16M_NB ;                              // nearest centimeter correction
888
            }
889
        }//end of switch
890
    }
891
    else // 64M PRF
892
    {
893
        switch(chan)
894
        {
895
            case 4:
896
            case 7:
897
            {
898
                chanIdx = chan_idxwb[chan];
899
                while (rangeint25cm > range25cm64PRFwb[chanIdx][i]) i++ ;       // find index in table corresponding to range
900
                cmoffseti = i + CM_OFFSET_64M_WB ;                              // nearest centimeter correction
901
            }
902
            break;
903
            default:
904
            {
905
                chanIdx = chan_idxnb[chan];
906
                while (rangeint25cm > range25cm64PRFnb[chanIdx][i]) i++ ;       // find index in table corresponding to range
907
                cmoffseti = i + CM_OFFSET_64M_NB ;                              // nearest centimeter correction
908
            }
909
        }//end of switch
910
    } // end else
911

    
912

    
913
    mOffset = (double) cmoffseti ;                                       // offset result in centimmetres
914

    
915
    mOffset *= 0.01 ;                                                   // convert to metres
916

    
917
    return (mOffset) ;
918
}
919

    
920
// -------------------------------------------------------------------------------------------------------------------
921
//
922
// Internal functions for controlling and configuring the device
923
//
924
// -------------------------------------------------------------------------------------------------------------------
925

    
926
// Enable and Configure specified clocks
927
void _dwt_enableclocks(int clocks) ;
928
// Configure the ucode (FP algorithm) parameters
929
void _dwt_configlde(int prf);
930
// Load ucode from OTP/ROM
931
void _dwt_loaducodefromrom(void);
932
// Read non-volatile memory
933
uint32_t _dwt_otpread(uint32_t address);
934
// Program the non-volatile memory
935
int32_t _dwt_otpprogword32(uint32_t data, uint16_t address);
936
// Upload the device configuration into always on memory
937
void _dwt_aonarrayupload(void);
938
// -------------------------------------------------------------------------------------------------------------------
939

    
940
/*!
941
 * Static data for DW1000 DecaWave Transceiver control
942
 */
943

    
944
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
945
static dwt_local_data_t *pdw1000local = dw1000local ; // Static local data structure pointer
946

    
947

    
948
/*! ------------------------------------------------------------------------------------------------------------------
949
 * @fn dwt_setdevicedataptr()
950
 *
951
 * @brief This function sets the local data structure pointer to point to the structure in the local array as given by the index.
952
 *
953
 * input parameters
954
 * @param index    - selects the array object to point to. Must be within the array bounds, i.e. < DWT_NUM_DW_DEV
955
 *
956
 * output parameters
957
 *
958
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
959
 */
960
int dwt_setdevicedataptr(unsigned int index)
961
{
962
    // Check the index is within the array bounds
963
    if (DWT_NUM_DW_DEV > index) // return error if index outside the array bounds
964
    {
965
        return DWT_ERROR ;
966
    }
967

    
968
    pdw1000local = &dw1000local[index];
969

    
970
    return DWT_SUCCESS ;
971
}
972

    
973
/*! ------------------------------------------------------------------------------------------------------------------
974
 * @fn dwt_initialise()
975
 *
976
 * @brief This function initiates communications with the DW1000 transceiver
977
 * and reads its DEV_ID register (address 0x00) to verify the IC is one supported
978
 * by this software (e.g. DW1000 32-bit device ID value is 0xDECA0130).  Then it
979
 * does any initial once only device configurations needed for use and initialises
980
 * as necessary any static data items belonging to this low-level driver.
981
 *
982
 * NOTES:
983
 * 1.this function needs to be run before dwt_configuresleep, also the SPI frequency has to be < 3MHz
984
 * 2.it also reads and applies LDO tune and crystal trim values from OTP memory
985
 *
986
 * input parameters
987
 * @param config    -   specifies what configuration to load
988
 *                  DWT_LOADUCODE     0x1 - load the LDE microcode from ROM - enabled accurate RX timestamp
989
 *                  DWT_LOADNONE      0x0 - do not load any values from OTP memory
990
 *
991
 * output parameters
992
 *
993
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
994
 */
995
// OTP addresses definitions
996
#define LDOTUNE_ADDRESS (0x04)
997
#define PARTID_ADDRESS (0x06)
998
#define LOTID_ADDRESS  (0x07)
999
#define VBAT_ADDRESS   (0x08)
1000
#define VTEMP_ADDRESS  (0x09)
1001
#define XTRIM_ADDRESS  (0x1E)
1002

    
1003
int dwt_initialise(const uint16_t config, DW1000Driver* drv)
1004
{
1005
    uint16_t otp_addr = 0;
1006
    uint32_t ldo_tune = 0;
1007

    
1008
    pdw1000local->dblbuffon = 0; // Double buffer mode off by default
1009
    pdw1000local->wait4resp = 0;
1010
    pdw1000local->sleep_mode = 0;
1011

    
1012
    pdw1000local->cbTxDone = NULL;
1013
    pdw1000local->cbRxOk = NULL;
1014
    pdw1000local->cbRxTo = NULL;
1015
    pdw1000local->cbRxErr = NULL;
1016

    
1017
    pdw1000local->driver = drv;
1018

    
1019
    // Read and validate device ID return -1 if not recognised
1020
    if (DWT_DEVICE_ID != dwt_readdevid()) // MP IC ONLY (i.e. DW1000) FOR THIS CODE
1021
    {
1022
        return DWT_ERROR ;
1023
    }
1024

    
1025
    // Make sure the device is completely reset before starting initialisation
1026
    dwt_softreset();
1027

    
1028
    _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
1029

    
1030
    // Configure the CPLL lock detect
1031
    dwt_write8bitoffsetreg(EXT_SYNC_ID, EC_CTRL_OFFSET, EC_CTRL_PLLLCK);
1032

    
1033
    // Read OTP revision number
1034
    otp_addr = _dwt_otpread(XTRIM_ADDRESS) & 0xffff;        // Read 32 bit value, XTAL trim val is in low octet-0 (5 bits)
1035
    pdw1000local->otprev = (otp_addr >> 8) & 0xff;            // OTP revision is next byte
1036

    
1037
    // Load LDO tune from OTP and kick it if there is a value actually programmed.
1038
    ldo_tune = _dwt_otpread(LDOTUNE_ADDRESS);
1039
    if((ldo_tune & 0xFF) != 0)
1040
    {
1041
        // Kick LDO tune
1042
        dwt_write8bitoffsetreg(OTP_IF_ID, OTP_SF, OTP_SF_LDO_KICK); // Set load LDE kick bit
1043
        pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDO; // LDO tune must be kicked at wake-up
1044
    }
1045

    
1046
    // Load Part and Lot ID from OTP
1047
    pdw1000local->partID = _dwt_otpread(PARTID_ADDRESS);
1048
    pdw1000local->lotID = _dwt_otpread(LOTID_ADDRESS);
1049

    
1050
    // 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
1051
    pdw1000local->init_xtrim = otp_addr & 0x1F;
1052
    if (!pdw1000local->init_xtrim) // A value of 0 means that the crystal has not been trimmed
1053
    {
1054
        pdw1000local->init_xtrim = FS_XTALT_MIDRANGE ; // Set to mid-range if no calibration value inside
1055
    }
1056
    // Configure XTAL trim
1057
    dwt_setxtaltrim(pdw1000local->init_xtrim);
1058

    
1059
    // Load leading edge detect code
1060
    if(config & DWT_LOADUCODE)
1061
    {
1062
        _dwt_loaducodefromrom();
1063
        pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDE; // microcode must be loaded at wake-up
1064
    }
1065
    else // Should disable the LDERUN enable bit in 0x36, 0x4
1066
    {
1067
        uint16_t rega = dwt_read16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1) ;
1068
        rega &= 0xFDFF ; // Clear LDERUN bit
1069
        dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1, rega) ;
1070
    }
1071

    
1072
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
1073

    
1074
    // The 3 bits in AON CFG1 register must be cleared to ensure proper operation of the DW1000 in DEEPSLEEP mode.
1075
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, 0x00);
1076

    
1077
    // Read system register / store local copy
1078
    pdw1000local->sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
1079

    
1080
    return DWT_SUCCESS ;
1081

    
1082
} // end dwt_initialise()
1083

    
1084
/*! ------------------------------------------------------------------------------------------------------------------
1085
 * @fn dwt_otprevision()
1086
 *
1087
 * @brief This is used to return the read OTP revision
1088
 *
1089
 * NOTE: dwt_initialise() must be called prior to this function so that it can return a relevant value.
1090
 *
1091
 * input parameters
1092
 *
1093
 * output parameters
1094
 *
1095
 * returns the read OTP revision value
1096
 */
1097
uint8_t dwt_otprevision(void)
1098
{
1099
    return pdw1000local->otprev ;
1100
}
1101

    
1102
/*! ------------------------------------------------------------------------------------------------------------------
1103
 * @fn dwt_setfinegraintxseq()
1104
 *
1105
 * @brief This function enables/disables the fine grain TX sequencing (enabled by default).
1106
 *
1107
 * input parameters
1108
 * @param enable - 1 to enable fine grain TX sequencing, 0 to disable it.
1109
 *
1110
 * output parameters none
1111
 *
1112
 * no return value
1113
 */
1114
void dwt_setfinegraintxseq(int enable)
1115
{
1116
    if (enable)
1117
    {
1118
        dwt_write16bitoffsetreg(PMSC_ID, PMSC_TXFINESEQ_OFFSET, PMSC_TXFINESEQ_ENABLE);
1119
    }
1120
    else
1121
    {
1122
        dwt_write16bitoffsetreg(PMSC_ID, PMSC_TXFINESEQ_OFFSET, PMSC_TXFINESEQ_DISABLE);
1123
    }
1124
}
1125

    
1126
/*! ------------------------------------------------------------------------------------------------------------------
1127
 * @fn dwt_setlnapamode()
1128
 *
1129
 * @brief This is used to enable GPIO for external LNA or PA functionality - HW dependent, consult the DW1000 User Manual.
1130
 *        This can also be used for debug as enabling TX and RX GPIOs is quite handy to monitor DW1000's activity.
1131
 *
1132
 * NOTE: Enabling PA functionality requires that fine grain TX sequencing is deactivated. This can be done using
1133
 *       dwt_setfinegraintxseq().
1134
 *
1135
 * input parameters
1136
 * @param lna - 1 to enable LNA functionality, 0 to disable it
1137
 * @param pa - 1 to enable PA functionality, 0 to disable it
1138
 *
1139
 * output parameters
1140
 *
1141
 * no return value
1142
 */
1143
void dwt_setlnapamode(int lna, int pa)
1144
{
1145
    uint32_t gpio_mode = dwt_read32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET);
1146
    gpio_mode &= ~(GPIO_MSGP4_MASK | GPIO_MSGP5_MASK | GPIO_MSGP6_MASK);
1147
    if (lna)
1148
    {
1149
        gpio_mode |= GPIO_PIN6_EXTRXE;
1150
    }
1151
    if (pa)
1152
    {
1153
        gpio_mode |= (GPIO_PIN5_EXTTXE | GPIO_PIN4_EXTPA);
1154
    }
1155
    dwt_write32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET, gpio_mode);
1156
}
1157

    
1158
/*! ------------------------------------------------------------------------------------------------------------------
1159
 * @fn dwt_setgpiodirection()
1160
 *
1161
 * @brief This is used to set GPIO direction as an input (1) or output (0)
1162
 *
1163
 * input parameters
1164
 * @param gpioNum    -   this is the GPIO to configure - see GxM0... GxM8 in the deca_regs.h file
1165
 * @param direction  -   this sets the GPIO direction - see GxP0... GxP8 in the deca_regs.h file
1166
 *
1167
 * output parameters
1168
 *
1169
 * no return value
1170
 */
1171
void dwt_setgpiodirection(uint32_t gpioNum, uint32_t direction)
1172
{
1173
    uint8_t buf[GPIO_DIR_LEN];
1174
    uint32_t command = direction | gpioNum;
1175

    
1176
    buf[0] = command & 0xff;
1177
    buf[1] = (command >> 8) & 0xff;
1178
    buf[2] = (command >> 16) & 0xff;
1179

    
1180
    dwt_writetodevice(GPIO_CTRL_ID, GPIO_DIR_OFFSET, GPIO_DIR_LEN, buf);
1181
}
1182

    
1183
/*! ------------------------------------------------------------------------------------------------------------------
1184
 * @fn dwt_setgpiovalue()
1185
 *
1186
 * @brief This is used to set GPIO value as (1) or (0) only applies if the GPIO is configured as output
1187
 *
1188
 * input parameters
1189
 * @param gpioNum    -   this is the GPIO to configure - see GxM0... GxM8 in the deca_regs.h file
1190
 * @param value  -   this sets the GPIO value - see GDP0... GDP8 in the deca_regs.h file
1191
 *
1192
 * output parameters
1193
 *
1194
 * no return value
1195
 */
1196
void dwt_setgpiovalue(uint32_t gpioNum, uint32_t value)
1197
{
1198
    uint8_t buf[GPIO_DOUT_LEN];
1199
    uint32_t command = value | gpioNum;
1200

    
1201
    buf[0] = command & 0xff;
1202
    buf[1] = (command >> 8) & 0xff;
1203
    buf[2] = (command >> 16) & 0xff;
1204

    
1205
    dwt_writetodevice(GPIO_CTRL_ID, GPIO_DOUT_OFFSET, GPIO_DOUT_LEN, buf);
1206
}
1207

    
1208
/*! ------------------------------------------------------------------------------------------------------------------
1209
 * @fn dwt_getpartid()
1210
 *
1211
 * @brief This is used to return the read part ID of the device
1212
 *
1213
 * NOTE: dwt_initialise() must be called prior to this function so that it can return a relevant value.
1214
 *
1215
 * input parameters
1216
 *
1217
 * output parameters
1218
 *
1219
 * returns the 32 bit part ID value as programmed in the factory
1220
 */
1221
uint32_t dwt_getpartid(void)
1222
{
1223
    return pdw1000local->partID;
1224
}
1225

    
1226
/*! ------------------------------------------------------------------------------------------------------------------
1227
 * @fn dwt_getlotid()
1228
 *
1229
 * @brief This is used to return the read lot ID of the device
1230
 *
1231
 * NOTE: dwt_initialise() must be called prior to this function so that it can return a relevant value.
1232
 *
1233
 * input parameters
1234
 *
1235
 * output parameters
1236
 *
1237
 * returns the 32 bit lot ID value as programmed in the factory
1238
 */
1239
uint32_t dwt_getlotid(void)
1240
{
1241
    return pdw1000local->lotID;
1242
}
1243

    
1244
/*! ------------------------------------------------------------------------------------------------------------------
1245
 * @fn dwt_readdevid()
1246
 *
1247
 * @brief This is used to return the read device type and revision information of the DW1000 device (MP part is 0xDECA0130)
1248
 *
1249
 * input parameters
1250
 *
1251
 * output parameters
1252
 *
1253
 * returns the read value which for DW1000 is 0xDECA0130
1254
 */
1255
uint32_t dwt_readdevid(void)
1256
{
1257
    return dwt_read32bitoffsetreg(DEV_ID_ID,0);
1258
}
1259

    
1260
/*! ------------------------------------------------------------------------------------------------------------------
1261
 * @fn dwt_configuretxrf()
1262
 *
1263
 * @brief This function provides the API for the configuration of the TX spectrum
1264
 * including the power and pulse generator delay. The input is a pointer to the data structure
1265
 * of type dwt_txconfig_t that holds all the configurable items.
1266
 *
1267
 * input parameters
1268
 * @param config    -   pointer to the txrf configuration structure, which contains the tx rf config data
1269
 *
1270
 * output parameters
1271
 *
1272
 * no return value
1273
 */
1274
void dwt_configuretxrf(dwt_txconfig_t* config)
1275
{
1276

    
1277
    // Configure RF TX PG_DELAY
1278
    dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGDELAY_OFFSET, config->PGdly);
1279

    
1280
    // Configure TX power
1281
    dwt_write32bitreg(TX_POWER_ID, config->power);
1282

    
1283
}
1284

    
1285
/*! ------------------------------------------------------------------------------------------------------------------
1286
 * @fn dwt_configure()
1287
 *
1288
 * @brief This function provides the main API for the configuration of the
1289
 * DW1000 and this low-level driver.  The input is a pointer to the data structure
1290
 * of type dwt_config_t that holds all the configurable items.
1291
 * The dwt_config_t structure shows which ones are supported
1292
 *
1293
 * input parameters
1294
 * @param config    -   pointer to the configuration structure, which contains the device configuration data.
1295
 *
1296
 * output parameters
1297
 *
1298
 * no return value
1299
 */
1300
void dwt_configure(dwt_config_t *config)
1301
{
1302
    uint8_t nsSfd_result  = 0;
1303
    uint8_t useDWnsSFD = 0;
1304
    uint8_t chan = config->chan ;
1305
    uint32_t regval ;
1306
    uint16_t reg16 = lde_replicaCoeff[config->rxCode];
1307
    uint8_t prfIndex = config->prf - DWT_PRF_16M;
1308
    uint8_t bw = ((chan == 4) || (chan == 7)) ? 1 : 0 ; // Select wide or narrow band
1309

    
1310
#ifdef DWT_API_ERROR_CHECK
1311
    assert(config->dataRate <= DWT_BR_6M8);
1312
    assert(config->rxPAC <= DWT_PAC64);
1313
    assert((chan >= 1) && (chan <= 7) && (chan != 6));
1314
    assert(((config->prf == DWT_PRF_64M) && (config->txCode >= 9) && (config->txCode <= 24))
1315
           || ((config->prf == DWT_PRF_16M) && (config->txCode >= 1) && (config->txCode <= 8)));
1316
    assert(((config->prf == DWT_PRF_64M) && (config->rxCode >= 9) && (config->rxCode <= 24))
1317
           || ((config->prf == DWT_PRF_16M) && (config->rxCode >= 1) && (config->rxCode <= 8)));
1318
    assert((config->txPreambLength == DWT_PLEN_64) || (config->txPreambLength == DWT_PLEN_128) || (config->txPreambLength == DWT_PLEN_256)
1319
           || (config->txPreambLength == DWT_PLEN_512) || (config->txPreambLength == DWT_PLEN_1024) || (config->txPreambLength == DWT_PLEN_1536)
1320
           || (config->txPreambLength == DWT_PLEN_2048) || (config->txPreambLength == DWT_PLEN_4096));
1321
    assert((config->phrMode == DWT_PHRMODE_STD) || (config->phrMode == DWT_PHRMODE_EXT));
1322
#endif
1323

    
1324
    // For 110 kbps we need a special setup
1325
    if(DWT_BR_110K == config->dataRate)
1326
    {
1327
        pdw1000local->sysCFGreg |= SYS_CFG_RXM110K ;
1328
        reg16 >>= 3; // lde_replicaCoeff must be divided by 8
1329
    }
1330
    else
1331
    {
1332
        pdw1000local->sysCFGreg &= (~SYS_CFG_RXM110K) ;
1333
    }
1334

    
1335
    pdw1000local->longFrames = config->phrMode ;
1336

    
1337
    pdw1000local->sysCFGreg &= ~SYS_CFG_PHR_MODE_11;
1338
    pdw1000local->sysCFGreg |= (SYS_CFG_PHR_MODE_11 & (uint32_t)(config->phrMode << SYS_CFG_PHR_MODE_SHFT));
1339

    
1340
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
1341
    // Set the lde_replicaCoeff
1342
    dwt_write16bitoffsetreg(LDE_IF_ID, LDE_REPC_OFFSET, reg16) ;
1343

    
1344
    _dwt_configlde(prfIndex);
1345

    
1346
    // Configure PLL2/RF PLL block CFG/TUNE (for a given channel)
1347
    dwt_write32bitoffsetreg(FS_CTRL_ID, FS_PLLCFG_OFFSET, fs_pll_cfg[chan_idx[chan]]);
1348
    dwt_write8bitoffsetreg(FS_CTRL_ID, FS_PLLTUNE_OFFSET, fs_pll_tune[chan_idx[chan]]);
1349

    
1350
    // Configure RF RX blocks (for specified channel/bandwidth)
1351
    dwt_write8bitoffsetreg(RF_CONF_ID, RF_RXCTRLH_OFFSET, rx_config[bw]);
1352

    
1353
    // Configure RF TX blocks (for specified channel and PRF)
1354
    // Configure RF TX control
1355
    dwt_write32bitoffsetreg(RF_CONF_ID, RF_TXCTRL_OFFSET, tx_config[chan_idx[chan]]);
1356

    
1357
    // Configure the baseband parameters (for specified PRF, bit rate, PAC, and SFD settings)
1358
    // DTUNE0
1359
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE0b_OFFSET, sftsh[config->dataRate][config->nsSFD]);
1360

    
1361
    // DTUNE1
1362
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1a_OFFSET, dtune1[prfIndex]);
1363

    
1364
    if(config->dataRate == DWT_BR_110K)
1365
    {
1366
        dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_110K);
1367
    }
1368
    else
1369
    {
1370
        if(config->txPreambLength == DWT_PLEN_64)
1371
        {
1372
            dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_6M8_PRE64);
1373
            dwt_write8bitoffsetreg(DRX_CONF_ID, DRX_TUNE4H_OFFSET, DRX_TUNE4H_PRE64);
1374
        }
1375
        else
1376
        {
1377
            dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_850K_6M8);
1378
            dwt_write8bitoffsetreg(DRX_CONF_ID, DRX_TUNE4H_OFFSET, DRX_TUNE4H_PRE128PLUS);
1379
        }
1380
    }
1381

    
1382
    // DTUNE2
1383
    dwt_write32bitoffsetreg(DRX_CONF_ID, DRX_TUNE2_OFFSET, digital_bb_config[prfIndex][config->rxPAC]);
1384

    
1385
    // DTUNE3 (SFD timeout)
1386
    // Don't allow 0 - SFD timeout will always be enabled
1387
    if(config->sfdTO == 0)
1388
    {
1389
        config->sfdTO = DWT_SFDTOC_DEF;
1390
    }
1391
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_SFDTOC_OFFSET, config->sfdTO);
1392

    
1393
    // Configure AGC parameters
1394
    dwt_write32bitoffsetreg( AGC_CFG_STS_ID, 0xC, agc_config.lo32);
1395
    dwt_write16bitoffsetreg( AGC_CFG_STS_ID, 0x4, agc_config.target[prfIndex]);
1396

    
1397
    // Set (non-standard) user SFD for improved performance,
1398
    if(config->nsSFD)
1399
    {
1400
        // Write non standard (DW) SFD length
1401
        dwt_write8bitoffsetreg(USR_SFD_ID, 0x00, dwnsSFDlen[config->dataRate]);
1402
        nsSfd_result = 3 ;
1403
        useDWnsSFD = 1 ;
1404
    }
1405
    regval =  (CHAN_CTRL_TX_CHAN_MASK & (uint32_t)(chan << CHAN_CTRL_TX_CHAN_SHIFT)) | // Transmit Channel
1406
              (CHAN_CTRL_RX_CHAN_MASK & (uint32_t)(chan << CHAN_CTRL_RX_CHAN_SHIFT)) | // Receive Channel
1407
              (CHAN_CTRL_RXFPRF_MASK & (uint32_t)(config->prf << CHAN_CTRL_RXFPRF_SHIFT)) | // RX PRF
1408
              ((CHAN_CTRL_TNSSFD|CHAN_CTRL_RNSSFD) & (uint32_t)(nsSfd_result << CHAN_CTRL_TNSSFD_SHIFT)) | // nsSFD enable RX&TX
1409
              (CHAN_CTRL_DWSFD & (uint32_t)(useDWnsSFD << CHAN_CTRL_DWSFD_SHIFT)) | // Use DW nsSFD
1410
              (CHAN_CTRL_TX_PCOD_MASK & (uint32_t)(config->txCode << CHAN_CTRL_TX_PCOD_SHIFT)) | // TX Preamble Code
1411
              (CHAN_CTRL_RX_PCOD_MASK & (uint32_t)(config->rxCode << CHAN_CTRL_RX_PCOD_SHIFT)) ; // RX Preamble Code
1412

    
1413
    dwt_write32bitreg(CHAN_CTRL_ID,regval) ;
1414

    
1415
    // Set up TX Preamble Size, PRF and Data Rate
1416
    pdw1000local->txFCTRL = (uint32_t)(((config->txPreambLength | config->prf) << TX_FCTRL_TXPRF_SHFT) | (config->dataRate << TX_FCTRL_TXBR_SHFT));
1417
    dwt_write32bitreg(TX_FCTRL_ID, pdw1000local->txFCTRL);
1418

    
1419
    // 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
1420
    // SYS_CTRL write below works around this issue, by simultaneously initiating and aborting a transmission, which correctly initialises the SFD
1421
    // after its configuration or reconfiguration.
1422
    // 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).
1423
    dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, SYS_CTRL_TXSTRT | SYS_CTRL_TRXOFF); // Request TX start and TRX off at the same time
1424
} // end dwt_configure()
1425

    
1426
/*! ------------------------------------------------------------------------------------------------------------------
1427
 * @fn dwt_setrxantennadelay()
1428
 *
1429
 * @brief This API function writes the antenna delay (in time units) to RX registers
1430
 *
1431
 * input parameters:
1432
 * @param rxDelay - this is the total (RX) antenna delay value, which
1433
 *                          will be programmed into the RX register
1434
 *
1435
 * output parameters
1436
 *
1437
 * no return value
1438
 */
1439
void dwt_setrxantennadelay(uint16_t rxDelay)
1440
{
1441
    // Set the RX antenna delay for auto TX timestamp adjustment
1442
    dwt_write16bitoffsetreg(LDE_IF_ID, LDE_RXANTD_OFFSET, rxDelay);
1443
}
1444

    
1445
/*! ------------------------------------------------------------------------------------------------------------------
1446
 * @fn dwt_settxantennadelay()
1447
 *
1448
 * @brief This API function writes the antenna delay (in time units) to TX registers
1449
 *
1450
 * input parameters:
1451
 * @param txDelay - this is the total (TX) antenna delay value, which
1452
 *                          will be programmed into the TX delay register
1453
 *
1454
 * output parameters
1455
 *
1456
 * no return value
1457
 */
1458
void dwt_settxantennadelay(uint16_t txDelay)
1459
{
1460
    // Set the TX antenna delay for auto TX timestamp adjustment
1461
    dwt_write16bitoffsetreg(TX_ANTD_ID, TX_ANTD_OFFSET, txDelay);
1462
}
1463

    
1464
/*! ------------------------------------------------------------------------------------------------------------------
1465
 * @fn dwt_writetxdata()
1466
 *
1467
 * @brief This API function writes the supplied TX data into the DW1000's
1468
 * TX buffer.  The input parameters are the data length in bytes and a pointer
1469
 * to those data bytes.
1470
 *
1471
 * input parameters
1472
 * @param txFrameLength  - This is the total frame length, including the two byte CRC.
1473
 *                         Note: this is the length of TX message (including the 2 byte CRC) - max is 1023
1474
 *                         standard PHR mode allows up to 127 bytes
1475
 *                         if > 127 is programmed, DWT_PHRMODE_EXT needs to be set in the phrMode configuration
1476
 *                         see dwt_configure function
1477
 * @param txFrameBytes   - Pointer to the user’s buffer containing the data to send.
1478
 * @param txBufferOffset - This specifies an offset in the DW1000’s TX Buffer at which to start writing data.
1479
 *
1480
 * output parameters
1481
 *
1482
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
1483
 */
1484
int dwt_writetxdata(uint16_t txFrameLength, uint8_t *txFrameBytes, uint16_t txBufferOffset)
1485
{
1486
#ifdef DWT_API_ERROR_CHECK
1487
    assert(txFrameLength >= 2);
1488
    assert((pdw1000local->longFrames && (txFrameLength <= 1023)) || (txFrameLength <= 127));
1489
    assert((txBufferOffset + txFrameLength) <= 1024);
1490
#endif
1491

    
1492
    if ((txBufferOffset + txFrameLength) <= 1024)
1493
    {
1494
        // Write the data to the IC TX buffer, (-2 bytes for auto generated CRC)
1495
        dwt_writetodevice( TX_BUFFER_ID, txBufferOffset, txFrameLength-2, txFrameBytes);
1496
        return DWT_SUCCESS;
1497
    }
1498
    else
1499
    {
1500
        return DWT_ERROR;
1501
    }
1502
} // end dwt_writetxdata()
1503

    
1504
/*! ------------------------------------------------------------------------------------------------------------------
1505
 * @fn dwt_writetxfctrl()
1506
 *
1507
 * @brief This API function configures the TX frame control register before the transmission of a frame
1508
 *
1509
 * input parameters:
1510
 * @param txFrameLength - this is the length of TX message (including the 2 byte CRC) - max is 1023
1511
 *                              NOTE: standard PHR mode allows up to 127 bytes
1512
 *                              if > 127 is programmed, DWT_PHRMODE_EXT needs to be set in the phrMode configuration
1513
 *                              see dwt_configure function
1514
 * @param txBufferOffset - the offset in the tx buffer to start writing the data
1515
 * @param ranging - 1 if this is a ranging frame, else 0
1516
 *
1517
 * output parameters
1518
 *
1519
 * no return value
1520
 */
1521
void dwt_writetxfctrl(uint16_t txFrameLength, uint16_t txBufferOffset, int ranging)
1522
{
1523

    
1524
#ifdef DWT_API_ERROR_CHECK
1525
    assert((pdw1000local->longFrames && (txFrameLength <= 1023)) || (txFrameLength <= 127));
1526
#endif
1527

    
1528
    // Write the frame length to the TX frame control register
1529
    // pdw1000local->txFCTRL has kept configured bit rate information
1530
    uint32_t reg32 = pdw1000local->txFCTRL | txFrameLength | (uint16_t)(txBufferOffset << TX_FCTRL_TXBOFFS_SHFT) | (uint16_t)(ranging << TX_FCTRL_TR_SHFT);
1531
    dwt_write32bitreg(TX_FCTRL_ID, reg32);
1532
} // end dwt_writetxfctrl()
1533

    
1534

    
1535
/*! ------------------------------------------------------------------------------------------------------------------
1536
 * @fn dwt_readrxdata()
1537
 *
1538
 * @brief This is used to read the data from the RX buffer, from an offset location give by offset parameter
1539
 *
1540
 * input parameters
1541
 * @param buffer - the buffer into which the data will be read
1542
 * @param length - the length of data to read (in bytes)
1543
 * @param rxBufferOffset - the offset in the rx buffer from which to read the data
1544
 *
1545
 * output parameters
1546
 *
1547
 * no return value
1548
 */
1549
void dwt_readrxdata(uint8_t *buffer, uint16_t length, uint16_t rxBufferOffset)
1550
{
1551
    dwt_readfromdevice(RX_BUFFER_ID,rxBufferOffset,length,buffer) ;
1552
}
1553

    
1554
/*! ------------------------------------------------------------------------------------------------------------------
1555
 * @fn dwt_readaccdata()
1556
 *
1557
 * @brief This is used to read the data from the Accumulator buffer, from an offset location give by offset parameter
1558
 *
1559
 * NOTE: Because of an internal memory access delay when reading the accumulator the first octet output is a dummy octet
1560
 *       that should be discarded. This is true no matter what sub-index the read begins at.
1561
 *
1562
 * input parameters
1563
 * @param buffer - the buffer into which the data will be read
1564
 * @param length - the length of data to read (in bytes)
1565
 * @param accOffset - the offset in the acc buffer from which to read the data
1566
 *
1567
 * output parameters
1568
 *
1569
 * no return value
1570
 */
1571
void dwt_readaccdata(uint8_t *buffer, uint16_t len, uint16_t accOffset)
1572
{
1573
    // Force on the ACC clocks if we are sequenced
1574
    _dwt_enableclocks(READ_ACC_ON);
1575

    
1576
    dwt_readfromdevice(ACC_MEM_ID,accOffset,len,buffer) ;
1577

    
1578
    _dwt_enableclocks(READ_ACC_OFF); // Revert clocks back
1579
}
1580

    
1581
/*! ------------------------------------------------------------------------------------------------------------------
1582
 * @fn dwt_readdiagnostics()
1583
 *
1584
 * @brief this function reads the RX signal quality diagnostic data
1585
 *
1586
 * input parameters
1587
 * @param diagnostics - diagnostic structure pointer, this will contain the diagnostic data read from the DW1000
1588
 *
1589
 * output parameters
1590
 *
1591
 * no return value
1592
 */
1593
void dwt_readdiagnostics(dwt_rxdiag_t *diagnostics)
1594
{
1595
    // Read the HW FP index
1596
    diagnostics->firstPath = dwt_read16bitoffsetreg(RX_TIME_ID, RX_TIME_FP_INDEX_OFFSET);
1597

    
1598
    // LDE diagnostic data
1599
    diagnostics->maxNoise = dwt_read16bitoffsetreg(LDE_IF_ID, LDE_THRESH_OFFSET);
1600

    
1601
    // Read all 8 bytes in one SPI transaction
1602
    dwt_readfromdevice(RX_FQUAL_ID, 0x0, 8, (uint8_t*)&diagnostics->stdNoise);
1603

    
1604
    diagnostics->firstPathAmp1 = dwt_read16bitoffsetreg(RX_TIME_ID, RX_TIME_FP_AMPL1_OFFSET);
1605

    
1606
    diagnostics->rxPreamCount = (dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXPACC_MASK) >> RX_FINFO_RXPACC_SHIFT  ;
1607
}
1608

    
1609
/*! ------------------------------------------------------------------------------------------------------------------
1610
 * @fn dwt_readtxtimestamp()
1611
 *
1612
 * @brief This is used to read the TX timestamp (adjusted with the programmed antenna delay)
1613
 *
1614
 * input parameters
1615
 * @param timestamp - a pointer to a 5-byte buffer which will store the read TX timestamp time
1616
 *
1617
 * output parameters - the timestamp buffer will contain the value after the function call
1618
 *
1619
 * no return value
1620
 */
1621
void dwt_readtxtimestamp(uint8_t * timestamp)
1622
{
1623
    dwt_readfromdevice(TX_TIME_ID, TX_TIME_TX_STAMP_OFFSET, TX_TIME_TX_STAMP_LEN, timestamp) ; // Read bytes directly into buffer
1624
}
1625

    
1626
/*! ------------------------------------------------------------------------------------------------------------------
1627
 * @fn dwt_readtxtimestamphi32()
1628
 *
1629
 * @brief This is used to read the high 32-bits of the TX timestamp (adjusted with the programmed antenna delay)
1630
 *
1631
 * input parameters
1632
 *
1633
 * output parameters
1634
 *
1635
 * returns high 32-bits of TX timestamp
1636
 */
1637
uint32_t dwt_readtxtimestamphi32(void)
1638
{
1639
    return dwt_read32bitoffsetreg(TX_TIME_ID, 1); // Offset is 1 to get the 4 upper bytes out of 5
1640
}
1641

    
1642
/*! ------------------------------------------------------------------------------------------------------------------
1643
 * @fn dwt_readtxtimestamplo32()
1644
 *
1645
 * @brief This is used to read the low 32-bits of the TX timestamp (adjusted with the programmed antenna delay)
1646
 *
1647
 * input parameters
1648
 *
1649
 * output parameters
1650
 *
1651
 * returns low 32-bits of TX timestamp
1652
 */
1653
uint32_t dwt_readtxtimestamplo32(void)
1654
{
1655
    return dwt_read32bitreg(TX_TIME_ID); // Read TX TIME as a 32-bit register to get the 4 lower bytes out of 5
1656
}
1657

    
1658
/*! ------------------------------------------------------------------------------------------------------------------
1659
 * @fn dwt_readrxtimestamp()
1660
 *
1661
 * @brief This is used to read the RX timestamp (adjusted time of arrival)
1662
 *
1663
 * input parameters
1664
 * @param timestamp - a pointer to a 5-byte buffer which will store the read RX timestamp time
1665
 *
1666
 * output parameters - the timestamp buffer will contain the value after the function call
1667
 *
1668
 * no return value
1669
 */
1670
void dwt_readrxtimestamp(uint8_t * timestamp)
1671
{
1672
    dwt_readfromdevice(RX_TIME_ID, RX_TIME_RX_STAMP_OFFSET, RX_TIME_RX_STAMP_LEN, timestamp) ; // Get the adjusted time of arrival
1673
}
1674

    
1675
/*! ------------------------------------------------------------------------------------------------------------------
1676
 * @fn dwt_readrxtimestamphi32()
1677
 *
1678
 * @brief This is used to read the high 32-bits of the RX timestamp (adjusted with the programmed antenna delay)
1679
 *
1680
 * input parameters
1681
 *
1682
 * output parameters
1683
 *
1684
 * returns high 32-bits of RX timestamp
1685
 */
1686
uint32_t dwt_readrxtimestamphi32(void)
1687
{
1688
    return dwt_read32bitoffsetreg(RX_TIME_ID, 1); // Offset is 1 to get the 4 upper bytes out of 5
1689
}
1690

    
1691
/*! ------------------------------------------------------------------------------------------------------------------
1692
 * @fn dwt_readrxtimestamplo32()
1693
 *
1694
 * @brief This is used to read the low 32-bits of the RX timestamp (adjusted with the programmed antenna delay)
1695
 *
1696
 * input parameters
1697
 *
1698
 * output parameters
1699
 *
1700
 * returns low 32-bits of RX timestamp
1701
 */
1702
uint32_t dwt_readrxtimestamplo32(void)
1703
{
1704
    return dwt_read32bitreg(RX_TIME_ID); // Read RX TIME as a 32-bit register to get the 4 lower bytes out of 5
1705
}
1706

    
1707
/*! ------------------------------------------------------------------------------------------------------------------
1708
 * @fn dwt_readsystimestamphi32()
1709
 *
1710
 * @brief This is used to read the high 32-bits of the system time
1711
 *
1712
 * input parameters
1713
 *
1714
 * output parameters
1715
 *
1716
 * returns high 32-bits of system time timestamp
1717
 */
1718
uint32_t dwt_readsystimestamphi32(void)
1719
{
1720
    return dwt_read32bitoffsetreg(SYS_TIME_ID, 1); // Offset is 1 to get the 4 upper bytes out of 5
1721
}
1722

    
1723
/*! ------------------------------------------------------------------------------------------------------------------
1724
 * @fn dwt_readsystime()
1725
 *
1726
 * @brief This is used to read the system time
1727
 *
1728
 * input parameters
1729
 * @param timestamp - a pointer to a 5-byte buffer which will store the read system time
1730
 *
1731
 * output parameters
1732
 * @param timestamp - the timestamp buffer will contain the value after the function call
1733
 *
1734
 * no return value
1735
 */
1736
void dwt_readsystime(uint8_t * timestamp)
1737
{
1738
    dwt_readfromdevice(SYS_TIME_ID, SYS_TIME_OFFSET, SYS_TIME_LEN, timestamp) ;
1739
}
1740

    
1741
/*! ------------------------------------------------------------------------------------------------------------------
1742
 * @fn dwt_writetodevice()
1743
 *
1744
 * @brief  this function is used to write to the DW1000 device registers
1745
 * Notes:
1746
 *        1. Firstly we create a header (the first byte is a header byte)
1747
 *        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
1748
 *        b. set bit-7 (or with 0x80) for write operation
1749
 *        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
1750
 *
1751
 *        2. Write the header followed by the data bytes to the DW1000 device
1752
 *
1753
 *
1754
 * input parameters:
1755
 * @param recordNumber  - ID of register file or buffer being accessed
1756
 * @param index         - byte index into register file or buffer being accessed
1757
 * @param length        - number of bytes being written
1758
 * @param buffer        - pointer to buffer containing the 'length' bytes to be written
1759
 *
1760
 * output parameters
1761
 *
1762
 * no return value
1763
 */
1764
void dwt_writetodevice
1765
(
1766
    uint16_t      recordNumber,
1767
    uint16_t      index,
1768
    uint32_t      length,
1769
    const uint8_t *buffer
1770
)
1771
{
1772
    uint8_t header[3] ; // Buffer to compose header in
1773
    int   cnt = 0; // Counter for length of header
1774
#ifdef DWT_API_ERROR_CHECK
1775
    assert(recordNumber <= 0x3F); // Record number is limited to 6-bits.
1776
#endif
1777

    
1778
    // Write message header selecting WRITE operation and addresses as appropriate (this is one to three bytes long)
1779
    if (index == 0) // For index of 0, no sub-index is required
1780
    {
1781
        header[cnt++] = 0x80 | (uint8_t)recordNumber ; // Bit-7 is WRITE operation, bit-6 zero=NO sub-addressing, bits 5-0 is reg file id
1782
    }
1783
    else
1784
    {
1785
#ifdef DWT_API_ERROR_CHECK
1786
        assert((index <= 0x7FFF) && ((index + length) <= 0x7FFF)); // Index and sub-addressable area are limited to 15-bits.
1787
#endif
1788
        header[cnt++] = 0xC0 | (uint8_t)recordNumber ; // Bit-7 is WRITE operation, bit-6 one=sub-address follows, bits 5-0 is reg file id
1789

    
1790
        if (index <= 127) // For non-zero index < 127, just a single sub-index byte is required
1791
        {
1792
            header[cnt++] = (uint8_t)index ; // Bit-7 zero means no extension, bits 6-0 is index.
1793
        }
1794
        else
1795
        {
1796
            header[cnt++] = 0x80 | (uint8_t)(index) ; // Bit-7 one means extended index, bits 6-0 is low seven bits of index.
1797
            header[cnt++] =  (uint8_t) (index >> 7) ; // 8-bit value = high eight bits of index.
1798
        }
1799
    }
1800

    
1801
    // Write it to the SPI
1802
    writetospi((uint16_t)cnt,header,length,buffer);
1803
} // end dwt_writetodevice()
1804

    
1805
/*! ------------------------------------------------------------------------------------------------------------------
1806
 * @fn dwt_readfromdevice()
1807
 *
1808
 * @brief  this function is used to read from the DW1000 device registers
1809
 * Notes:
1810
 *        1. Firstly we create a header (the first byte is a header byte)
1811
 *        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
1812
 *        b. set bit-7 (or with 0x80) for write operation
1813
 *        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
1814
 *
1815
 *        2. Write the header followed by the data bytes to the DW1000 device
1816
 *        3. Store the read data in the input buffer
1817
 *
1818
 * input parameters:
1819
 * @param recordNumber  - ID of register file or buffer being accessed
1820
 * @param index         - byte index into register file or buffer being accessed
1821
 * @param length        - number of bytes being read
1822
 * @param buffer        - pointer to buffer in which to return the read data.
1823
 *
1824
 * output parameters
1825
 *
1826
 * no return value
1827
 */
1828
void dwt_readfromdevice
1829
(
1830
    uint16_t  recordNumber,
1831
    uint16_t  index,
1832
    uint32_t  length,
1833
    uint8_t   *buffer
1834
)
1835
{
1836
    uint8_t header[3] ; // Buffer to compose header in
1837
    int   cnt = 0; // Counter for length of header
1838
#ifdef DWT_API_ERROR_CHECK
1839
    assert(recordNumber <= 0x3F); // Record number is limited to 6-bits.
1840
#endif
1841

    
1842
    // Write message header selecting READ operation and addresses as appropriate (this is one to three bytes long)
1843
    if (index == 0) // For index of 0, no sub-index is required
1844
    {
1845
        header[cnt++] = (uint8_t) recordNumber ; // Bit-7 zero is READ operation, bit-6 zero=NO sub-addressing, bits 5-0 is reg file id
1846
    }
1847
    else
1848
    {
1849
#ifdef DWT_API_ERROR_CHECK
1850
        assert((index <= 0x7FFF) && ((index + length) <= 0x7FFF)); // Index and sub-addressable area are limited to 15-bits.
1851
#endif
1852
        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
1853

    
1854
        if (index <= 127) // For non-zero index < 127, just a single sub-index byte is required
1855
        {
1856
            header[cnt++] = (uint8_t) index ; // Bit-7 zero means no extension, bits 6-0 is index.
1857
        }
1858
        else
1859
        {
1860
            header[cnt++] = 0x80 | (uint8_t)(index) ; // Bit-7 one means extended index, bits 6-0 is low seven bits of index.
1861
            header[cnt++] =  (uint8_t) (index >> 7) ; // 8-bit value = high eight bits of index.
1862
        }
1863
    }
1864

    
1865
    // Do the read from the SPI
1866
    readfromspi((uint16_t)cnt, header, length, buffer);
1867
} // end dwt_readfromdevice()
1868

    
1869

    
1870

    
1871
/*! ------------------------------------------------------------------------------------------------------------------
1872
 * @fn dwt_read32bitoffsetreg()
1873
 *
1874
 * @brief  this function is used to read 32-bit value from the DW1000 device registers
1875
 *
1876
 * input parameters:
1877
 * @param regFileID - ID of register file or buffer being accessed
1878
 * @param regOffset - the index into register file or buffer being accessed
1879
 *
1880
 * output parameters
1881
 *
1882
 * returns 32 bit register value
1883
 */
1884
uint32_t dwt_read32bitoffsetreg(int regFileID,int regOffset)
1885
{
1886
    uint32_t  regval = 0 ;
1887
    int     j ;
1888
    uint8_t   buffer[4] ;
1889

    
1890
    dwt_readfromdevice((uint16_t)regFileID, (uint16_t)regOffset,4,buffer); // Read 4 bytes (32-bits) register into buffer
1891

    
1892
    for (j = 3 ; j >= 0 ; j --)
1893
    {
1894
        regval = (regval << 8) + buffer[j] ;
1895
    }
1896
    return regval ;
1897

    
1898
} // end dwt_read32bitoffsetreg()
1899

    
1900
/*! ------------------------------------------------------------------------------------------------------------------
1901
 * @fn dwt_read16bitoffsetreg()
1902
 *
1903
 * @brief  this function is used to read 16-bit value from the DW1000 device registers
1904
 *
1905
 * input parameters:
1906
 * @param regFileID - ID of register file or buffer being accessed
1907
 * @param regOffset - the index into register file or buffer being accessed
1908
 *
1909
 * output parameters
1910
 *
1911
 * returns 16 bit register value
1912
 */
1913
uint16_t dwt_read16bitoffsetreg(int regFileID,int regOffset)
1914
{
1915
    uint16_t  regval = 0 ;
1916
    uint8_t   buffer[2] ;
1917

    
1918
    dwt_readfromdevice((uint16_t)regFileID, (uint16_t)regOffset,2,buffer); // Read 2 bytes (16-bits) register into buffer
1919

    
1920
    regval = (uint16_t)((buffer[1] << 8) + buffer[0] );
1921
    return regval ;
1922

    
1923
} // end dwt_read16bitoffsetreg()
1924

    
1925
/*! ------------------------------------------------------------------------------------------------------------------
1926
 * @fn dwt_read8bitoffsetreg()
1927
 *
1928
 * @brief  this function is used to read an 8-bit value from the DW1000 device registers
1929
 *
1930
 * input parameters:
1931
 * @param regFileID - ID of register file or buffer being accessed
1932
 * @param regOffset - the index into register file or buffer being accessed
1933
 *
1934
 * output parameters
1935
 *
1936
 * returns 8-bit register value
1937
 */
1938
uint8_t dwt_read8bitoffsetreg(int regFileID, int regOffset)
1939
{
1940
    uint8_t regval;
1941

    
1942
    dwt_readfromdevice((uint16_t)regFileID, (uint16_t)regOffset, 1, &regval);
1943

    
1944
    return regval ;
1945
}
1946

    
1947
/*! ------------------------------------------------------------------------------------------------------------------
1948
 * @fn dwt_write8bitoffsetreg()
1949
 *
1950
 * @brief  this function is used to write an 8-bit value to the DW1000 device registers
1951
 *
1952
 * input parameters:
1953
 * @param regFileID - ID of register file or buffer being accessed
1954
 * @param regOffset - the index into register file or buffer being accessed
1955
 * @param regval    - the value to write
1956
 *
1957
 * output parameters
1958
 *
1959
 * no return value
1960
 */
1961
void dwt_write8bitoffsetreg(int regFileID, int regOffset, uint8_t regval)
1962
{
1963
    dwt_writetodevice((uint16_t)regFileID, (uint16_t)regOffset, 1, &regval);
1964
}
1965

    
1966
/*! ------------------------------------------------------------------------------------------------------------------
1967
 * @fn dwt_write16bitoffsetreg()
1968
 *
1969
 * @brief  this function is used to write 16-bit value to the DW1000 device registers
1970
 *
1971
 * input parameters:
1972
 * @param regFileID - ID of register file or buffer being accessed
1973
 * @param regOffset - the index into register file or buffer being accessed
1974
 * @param regval    - the value to write
1975
 *
1976
 * output parameters
1977
 *
1978
 * no return value
1979
 */
1980
void dwt_write16bitoffsetreg(int regFileID,int regOffset,uint16_t regval)
1981
{
1982
    uint8_t   buffer[2] ;
1983

    
1984
    buffer[0] = regval & 0xFF;
1985
    buffer[1] = regval >> 8 ;
1986

    
1987
    dwt_writetodevice((uint16_t)regFileID, (uint16_t)regOffset,2,buffer);
1988
} // end dwt_write16bitoffsetreg()
1989

    
1990
/*! ------------------------------------------------------------------------------------------------------------------
1991
 * @fn dwt_write32bitoffsetreg()
1992
 *
1993
 * @brief  this function is used to write 32-bit value to the DW1000 device registers
1994
 *
1995
 * input parameters:
1996
 * @param regFileID - ID of register file or buffer being accessed
1997
 * @param regOffset - the index into register file or buffer being accessed
1998
 * @param regval    - the value to write
1999
 *
2000
 * output parameters
2001
 *
2002
 * no return value
2003
 */
2004
void dwt_write32bitoffsetreg(int regFileID,int regOffset,uint32_t regval)
2005
{
2006
    int     j ;
2007
    uint8_t   buffer[4] ;
2008

    
2009
    for ( j = 0 ; j < 4 ; j++ )
2010
    {
2011
        buffer[j] = regval & 0xff ;
2012
        regval >>= 8 ;
2013
    }
2014

    
2015
    dwt_writetodevice((uint16_t)regFileID,(uint16_t)regOffset,4,buffer);
2016
} // end dwt_write32bitoffsetreg()
2017

    
2018
/*! ------------------------------------------------------------------------------------------------------------------
2019
 * @fn dwt_enableframefilter()
2020
 *
2021
 * @brief This is used to enable the frame filtering - (the default option is to
2022
 * accept any data and ACK frames with correct destination address
2023
 *
2024
 * input parameters
2025
 * @param - bitmask - enables/disables the frame filtering options according to
2026
 *      DWT_FF_NOTYPE_EN        0x000   no frame types allowed
2027
 *      DWT_FF_COORD_EN         0x002   behave as coordinator (can receive frames with no destination address (PAN ID has to match))
2028
 *      DWT_FF_BEACON_EN        0x004   beacon frames allowed
2029
 *      DWT_FF_DATA_EN          0x008   data frames allowed
2030
 *      DWT_FF_ACK_EN           0x010   ack frames allowed
2031
 *      DWT_FF_MAC_EN           0x020   mac control frames allowed
2032
 *      DWT_FF_RSVD_EN          0x040   reserved frame types allowed
2033
 *
2034
 * output parameters
2035
 *
2036
 * no return value
2037
 */
2038
void dwt_enableframefilter(uint16_t enable)
2039
{
2040
    uint32_t sysconfig = SYS_CFG_MASK & dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
2041

    
2042
    if(enable)
2043
    {
2044
        // Enable frame filtering and configure frame types
2045
        sysconfig &= ~(SYS_CFG_FF_ALL_EN); // Clear all
2046
        sysconfig |= (enable & SYS_CFG_FF_ALL_EN) | SYS_CFG_FFE;
2047
    }
2048
    else
2049
    {
2050
        sysconfig &= ~(SYS_CFG_FFE);
2051
    }
2052

    
2053
    pdw1000local->sysCFGreg = sysconfig ;
2054
    dwt_write32bitreg(SYS_CFG_ID,sysconfig) ;
2055
}
2056

    
2057
/*! ------------------------------------------------------------------------------------------------------------------
2058
 * @fn dwt_setpanid()
2059
 *
2060
 * @brief This is used to set the PAN ID
2061
 *
2062
 * input parameters
2063
 * @param panID - this is the PAN ID
2064
 *
2065
 * output parameters
2066
 *
2067
 * no return value
2068
 */
2069
void dwt_setpanid(uint16_t panID)
2070
{
2071
    // PAN ID is high 16 bits of register
2072
    dwt_write16bitoffsetreg(PANADR_ID, PANADR_PAN_ID_OFFSET, panID);
2073
}
2074

    
2075
/*! ------------------------------------------------------------------------------------------------------------------
2076
 * @fn dwt_setaddress16()
2077
 *
2078
 * @brief This is used to set 16-bit (short) address
2079
 *
2080
 * input parameters
2081
 * @param shortAddress - this sets the 16 bit short address
2082
 *
2083
 * output parameters
2084
 *
2085
 * no return value
2086
 */
2087
void dwt_setaddress16(uint16_t shortAddress)
2088
{
2089
    // Short address into low 16 bits
2090
    dwt_write16bitoffsetreg(PANADR_ID, PANADR_SHORT_ADDR_OFFSET, shortAddress);
2091
}
2092

    
2093
/*! ------------------------------------------------------------------------------------------------------------------
2094
 * @fn dwt_seteui()
2095
 *
2096
 * @brief This is used to set the EUI 64-bit (long) address
2097
 *
2098
 * input parameters
2099
 * @param eui64 - this is the pointer to a buffer that contains the 64bit address
2100
 *
2101
 * output parameters
2102
 *
2103
 * no return value
2104
 */
2105
void dwt_seteui(uint8_t *eui64)
2106
{
2107
    dwt_writetodevice(EUI_64_ID, EUI_64_OFFSET, EUI_64_LEN, eui64);
2108
}
2109

    
2110
/*! ------------------------------------------------------------------------------------------------------------------
2111
 * @fn dwt_geteui()
2112
 *
2113
 * @brief This is used to get the EUI 64-bit from the DW1000
2114
 *
2115
 * input parameters
2116
 * @param eui64 - this is the pointer to a buffer that will contain the read 64-bit EUI value
2117
 *
2118
 * output parameters
2119
 *
2120
 * no return value
2121
 */
2122
void dwt_geteui(uint8_t *eui64)
2123
{
2124
    dwt_readfromdevice(EUI_64_ID, EUI_64_OFFSET, EUI_64_LEN, eui64);
2125
}
2126

    
2127
/*! ------------------------------------------------------------------------------------------------------------------
2128
 * @fn dwt_otpread()
2129
 *
2130
 * @brief This is used to read the OTP data from given address into provided array
2131
 *
2132
 * input parameters
2133
 * @param address - this is the OTP address to read from
2134
 * @param array - this is the pointer to the array into which to read the data
2135
 * @param length - this is the number of 32 bit words to read (array needs to be at least this length)
2136
 *
2137
 * output parameters
2138
 *
2139
 * no return value
2140
 */
2141
void dwt_otpread(uint32_t address, uint32_t *array, uint8_t length)
2142
{
2143
    int i;
2144

    
2145
    _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
2146

    
2147
    for(i=0; i<length; i++)
2148
    {
2149
        array[i] = _dwt_otpread(address + (uint32_t)i) ;
2150
    }
2151

    
2152
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Restore system clock to PLL
2153

    
2154
    return ;
2155
}
2156

    
2157
/*! ------------------------------------------------------------------------------------------------------------------
2158
 * @fn _dwt_otpread()
2159
 *
2160
 * @brief function to read the OTP memory. Ensure that MR,MRa,MRb are reset to 0.
2161
 *
2162
 * input parameters
2163
 * @param address - address to read at
2164
 *
2165
 * output parameters
2166
 *
2167
 * returns the 32bit of read data
2168
 */
2169
uint32_t _dwt_otpread(uint32_t address)
2170
{
2171
    uint32_t ret_data;
2172

    
2173
    // Write the address
2174
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_ADDR, (uint16_t)address);
2175

    
2176
    // Perform OTP Read - Manual read mode has to be set
2177
    dwt_write8bitoffsetreg(OTP_IF_ID, OTP_CTRL, OTP_CTRL_OTPREAD | OTP_CTRL_OTPRDEN);
2178
    dwt_write8bitoffsetreg(OTP_IF_ID, OTP_CTRL, 0x00); // OTPREAD is self clearing but OTPRDEN is not
2179

    
2180
    // Read read data, available 40ns after rising edge of OTP_READ
2181
    ret_data = dwt_read32bitoffsetreg(OTP_IF_ID, OTP_RDAT);
2182

    
2183
    // Return the 32bit of read data
2184
    return ret_data;
2185
}
2186

    
2187
/*! ------------------------------------------------------------------------------------------------------------------
2188
 * @fn _dwt_otpsetmrregs()
2189
 *
2190
 * @brief Configure the MR registers for initial programming (enable charge pump).
2191
 * Read margin is used to stress the read back from the
2192
 * programmed bit. In normal operation this is relaxed.
2193
 *
2194
 * input parameters
2195
 * @param mode - "0" : Reset all to 0x0:           MRA=0x0000, MRB=0x0000, MR=0x0000
2196
 *               "1" : Set for inital programming: MRA=0x9220, MRB=0x000E, MR=0x1024
2197
 *               "2" : Set for soak programming:   MRA=0x9220, MRB=0x0003, MR=0x1824
2198
 *               "3" : High Vpp:                   MRA=0x9220, MRB=0x004E, MR=0x1824
2199
 *               "4" : Low Read Margin:            MRA=0x0000, MRB=0x0003, MR=0x0000
2200
 *               "5" : Array Clean:                MRA=0x0049, MRB=0x0003, MR=0x0024
2201
 *               "4" : Very Low Read Margin:       MRA=0x0000, MRB=0x0003, MR=0x0000
2202
 *
2203
 * output parameters
2204
 *
2205
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2206
 */
2207
int32_t _dwt_otpsetmrregs(int mode)
2208
{
2209
    uint8_t rd_buf[4];
2210
    uint8_t wr_buf[4];
2211
    uint32_t mra=0,mrb=0,mr=0;
2212

    
2213
    // PROGRAMME MRA
2214
    // Set MRA, MODE_SEL
2215
    wr_buf[0] = 0x03;
2216
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL+1,1,wr_buf);
2217

    
2218
    // Load data
2219
    switch(mode&0x0f) {
2220
    case 0x0 :
2221
        mr =0x0000;
2222
        mra=0x0000;
2223
        mrb=0x0000;
2224
        break;
2225
    case 0x1 :
2226
        mr =0x1024;
2227
        mra=0x9220; // Enable CPP mon
2228
        mrb=0x000e;
2229
        break;
2230
    case 0x2 :
2231
        mr =0x1824;
2232
        mra=0x9220;
2233
        mrb=0x0003;
2234
        break;
2235
    case 0x3 :
2236
        mr =0x1824;
2237
        mra=0x9220;
2238
        mrb=0x004e;
2239
        break;
2240
    case 0x4 :
2241
        mr =0x0000;
2242
        mra=0x0000;
2243
        mrb=0x0003;
2244
        break;
2245
    case 0x5 :
2246
        mr =0x0024;
2247
        mra=0x0000;
2248
        mrb=0x0003;
2249
        break;
2250
    default :
2251
        return DWT_ERROR;
2252
    }
2253

    
2254
    wr_buf[0] = mra & 0x00ff;
2255
    wr_buf[1] = (mra & 0xff00)>>8;
2256
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2257

    
2258

    
2259
    // Set WRITE_MR
2260
    wr_buf[0] = 0x08;
2261
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2262

    
2263
    // Wait?
2264

    
2265
    // Set Clear Mode sel
2266
    wr_buf[0] = 0x02;
2267
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2268

    
2269
    // Set AUX update, write MR
2270
    wr_buf[0] = 0x88;
2271
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2272
    // Clear write MR
2273
    wr_buf[0] = 0x80;
2274
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2275
    // Clear AUX update
2276
    wr_buf[0] = 0x00;
2277
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2278

    
2279
    ///////////////////////////////////////////
2280
    // PROGRAM MRB
2281
    // Set SLOW, MRB, MODE_SEL
2282
    wr_buf[0] = 0x05;
2283
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2284

    
2285
    wr_buf[0] = mrb & 0x00ff;
2286
    wr_buf[1] = (mrb & 0xff00)>>8;
2287
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2288

    
2289
    // Set WRITE_MR
2290
    wr_buf[0] = 0x08;
2291
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2292

    
2293
    // Wait?
2294

    
2295
    // Set Clear Mode sel
2296
    wr_buf[0] = 0x04;
2297
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2298

    
2299
    // Set AUX update, write MR
2300
    wr_buf[0] = 0x88;
2301
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2302
    // Clear write MR
2303
    wr_buf[0] = 0x80;
2304
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2305
    // Clear AUX update
2306
    wr_buf[0] = 0x00;
2307
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2308

    
2309
    ///////////////////////////////////////////
2310
    // PROGRAM MR
2311
    // Set SLOW, MODE_SEL
2312
    wr_buf[0] = 0x01;
2313
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2314
    // Load data
2315

    
2316
    wr_buf[0] = mr & 0x00ff;
2317
    wr_buf[1] = (mr & 0xff00)>>8;
2318
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2319

    
2320
    // Set WRITE_MR
2321
    wr_buf[0] = 0x08;
2322
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2323

    
2324
    // Wait?
2325
    deca_sleep(10);
2326
    // Set Clear Mode sel
2327
    wr_buf[0] = 0x00;
2328
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2329

    
2330
    // Read confirm mode writes.
2331
    // Set man override, MRA_SEL
2332
    wr_buf[0] = OTP_CTRL_OTPRDEN;
2333
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2334
    wr_buf[0] = 0x02;
2335
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2336
    // MRB_SEL
2337
    wr_buf[0] = 0x04;
2338
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2339
    deca_sleep(100);
2340

    
2341
    // Clear mode sel
2342
    wr_buf[0] = 0x00;
2343
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2344
    // Clear MAN_OVERRIDE
2345
    wr_buf[0] = 0x00;
2346
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2347

    
2348
    deca_sleep(10);
2349

    
2350
    if (((mode&0x0f) == 0x1)||((mode&0x0f) == 0x2))
2351
    {
2352
        // Read status register
2353
        dwt_readfromdevice(OTP_IF_ID, OTP_STAT,1,rd_buf);
2354
    }
2355

    
2356
    return DWT_SUCCESS;
2357
}
2358

    
2359
/*! ------------------------------------------------------------------------------------------------------------------
2360
 * @fn _dwt_otpprogword32()
2361
 *
2362
 * @brief function to program the OTP memory. Ensure that MR,MRa,MRb are reset to 0.
2363
 * VNM Charge pump needs to be enabled (see _dwt_otpsetmrregs)
2364
 * Note the address is only 11 bits long.
2365
 *
2366
 * input parameters
2367
 * @param address - address to read at
2368
 *
2369
 * output parameters
2370
 *
2371
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2372
 */
2373
int32_t _dwt_otpprogword32(uint32_t data, uint16_t address)
2374
{
2375
    uint8_t rd_buf[1];
2376
    uint8_t wr_buf[4];
2377
    uint8_t otp_done;
2378

    
2379
    // Read status register
2380
    dwt_readfromdevice(OTP_IF_ID, OTP_STAT, 1, rd_buf);
2381

    
2382
    if((rd_buf[0] & 0x02) != 0x02)
2383
    {
2384
        return DWT_ERROR;
2385
    }
2386

    
2387
    // Write the data
2388
    wr_buf[3] = (data>>24) & 0xff;
2389
    wr_buf[2] = (data>>16) & 0xff;
2390
    wr_buf[1] = (data>>8) & 0xff;
2391
    wr_buf[0] = data & 0xff;
2392
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT, 4, wr_buf);
2393

    
2394
    // Write the address [10:0]
2395
    wr_buf[1] = (address>>8) & 0x07;
2396
    wr_buf[0] = address & 0xff;
2397
    dwt_writetodevice(OTP_IF_ID, OTP_ADDR, 2, wr_buf);
2398

    
2399
    // Enable Sequenced programming
2400
    wr_buf[0] = OTP_CTRL_OTPPROG;
2401
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL, 1, wr_buf);
2402
    wr_buf[0] = 0x00; // And clear
2403
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL, 1, wr_buf);
2404

    
2405
    // WAIT for status to flag PRGM OK..
2406
    otp_done = 0;
2407
    while(otp_done == 0)
2408
    {
2409
        deca_sleep(1);
2410
        dwt_readfromdevice(OTP_IF_ID, OTP_STAT, 1, rd_buf);
2411

    
2412
        if((rd_buf[0] & 0x01) == 0x01)
2413
        {
2414
            otp_done = 1;
2415
        }
2416
    }
2417

    
2418
    return DWT_SUCCESS;
2419
}
2420

    
2421
/*! ------------------------------------------------------------------------------------------------------------------
2422
 * @fn dwt_otpwriteandverify()
2423
 *
2424
 * @brief This is used to program 32-bit value into the DW1000 OTP memory.
2425
 *
2426
 * input parameters
2427
 * @param value - this is the 32-bit value to be programmed into OTP
2428
 * @param address - this is the 16-bit OTP address into which the 32-bit value is programmed
2429
 *
2430
 * output parameters
2431
 *
2432
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2433
 */
2434
int dwt_otpwriteandverify(uint32_t value, uint16_t address)
2435
{
2436
    int prog_ok = DWT_SUCCESS;
2437
    int retry = 0;
2438
    // Firstly set the system clock to crystal
2439
    _dwt_enableclocks(FORCE_SYS_XTI); //set system clock to XTI
2440

    
2441
    //
2442
    //!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!
2443
    //Set the supply to 3.7V
2444
    //
2445

    
2446
    _dwt_otpsetmrregs(1); // Set mode for programming
2447

    
2448
    // For each value to program - the readback/check is done couple of times to verify it has programmed successfully
2449
    while(1)
2450
    {
2451
        _dwt_otpprogword32(value, address);
2452

    
2453
        if(_dwt_otpread(address) == value)
2454
        {
2455
            break;
2456
        }
2457
        retry++;
2458
        if(retry==5)
2459
        {
2460
            break;
2461
        }
2462
    }
2463

    
2464
    // Even if the above does not exit before retry reaches 5, the programming has probably been successful
2465

    
2466
    _dwt_otpsetmrregs(4); // Set mode for reading
2467

    
2468
    if(_dwt_otpread(address) != value) // If this does not pass please check voltage supply on VDDIO
2469
    {
2470
        prog_ok = DWT_ERROR;
2471
    }
2472

    
2473
    _dwt_otpsetmrregs(0); // Setting OTP mode register for low RM read - resetting the device would be alternative
2474

    
2475
    return prog_ok;
2476
}
2477

    
2478
/*! ------------------------------------------------------------------------------------------------------------------
2479
 * @fn _dwt_aonconfigupload()
2480
 *
2481
 * @brief This function uploads always on (AON) configuration, as set in the AON_CFG0_OFFSET register.
2482
 *
2483
 * input parameters
2484
 *
2485
 * output parameters
2486
 *
2487
 * no return value
2488
 */
2489
void _dwt_aonconfigupload(void)
2490
{
2491
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_UPL_CFG);
2492
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00); // Clear the register
2493
}
2494

    
2495
/*! ------------------------------------------------------------------------------------------------------------------
2496
 * @fn _dwt_aonarrayupload()
2497
 *
2498
 * @brief This function uploads always on (AON) data array and configuration. Thus if this function is used, then _dwt_aonconfigupload
2499
 * is not necessary. The DW1000 will go so SLEEP straight after this if the DWT_SLP_EN has been set.
2500
 *
2501
 * input parameters
2502
 *
2503
 * output parameters
2504
 *
2505
 * no return value
2506
 */
2507
void _dwt_aonarrayupload(void)
2508
{
2509
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00); // Clear the register
2510
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_SAVE);
2511
}
2512

    
2513
/*! ------------------------------------------------------------------------------------------------------------------
2514
 * @fn dwt_entersleep()
2515
 *
2516
 * @brief This function puts the device into deep sleep or sleep. dwt_configuresleep() should be called first
2517
 * to configure the sleep and on-wake/wake-up parameters
2518
 *
2519
 * input parameters
2520
 *
2521
 * output parameters
2522
 *
2523
 * no return value
2524
 */
2525
void dwt_entersleep(void)
2526
{
2527
    // Copy config to AON - upload the new configuration
2528
    _dwt_aonarrayupload();
2529
}
2530

    
2531
/*! ------------------------------------------------------------------------------------------------------------------
2532
 * @fn dwt_configuresleepcnt()
2533
 *
2534
 * @brief sets the sleep counter to new value, this function programs the high 16-bits of the 28-bit counter
2535
 *
2536
 * NOTE: this function needs to be run before dwt_configuresleep, also the SPI frequency has to be < 3MHz
2537
 *
2538
 * input parameters
2539
 * @param sleepcnt - this it value of the sleep counter to program
2540
 *
2541
 * output parameters
2542
 *
2543
 * no return value
2544
 */
2545
void dwt_configuresleepcnt(uint16_t sleepcnt)
2546
{
2547
    // Force system clock to crystal
2548
    _dwt_enableclocks(FORCE_SYS_XTI);
2549

    
2550
    // Reset sleep configuration to make sure we don't accidentally go to sleep
2551
    dwt_write8bitoffsetreg(AON_ID, AON_CFG0_OFFSET, 0x00); // NB: this write change the default LPCLKDIVA value which is not used anyway.
2552
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, 0x00);
2553

    
2554
    // Disable the sleep counter
2555
    _dwt_aonconfigupload();
2556

    
2557
    // Set new value
2558
    dwt_write16bitoffsetreg(AON_ID, AON_CFG0_OFFSET + AON_CFG0_SLEEP_TIM_OFFSET, sleepcnt);
2559
    _dwt_aonconfigupload();
2560

    
2561
    // Enable the sleep counter
2562
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, AON_CFG1_SLEEP_CEN);
2563
    _dwt_aonconfigupload();
2564

    
2565
    // Put system PLL back on
2566
    _dwt_enableclocks(ENABLE_ALL_SEQ);
2567
}
2568

    
2569

    
2570
/*! ------------------------------------------------------------------------------------------------------------------
2571
 * @fn dwt_calibratesleepcnt()
2572
 *
2573
 * @brief calibrates the local oscillator as its frequency can vary between 7 and 13kHz depending on temp and voltage
2574
 *
2575
 * NOTE: this function needs to be run before dwt_configuresleepcnt, so that we know what the counter units are
2576
 *
2577
 * input parameters
2578
 *
2579
 * output parameters
2580
 *
2581
 * returns the number of XTAL/2 cycles per low-power oscillator cycle. LP OSC frequency = 19.2 MHz/return value
2582
 */
2583
uint16_t dwt_calibratesleepcnt(void)
2584
{
2585
    uint16_t result;
2586

    
2587
    // Enable calibration of the sleep counter
2588
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, AON_CFG1_LPOSC_CAL);
2589
    _dwt_aonconfigupload();
2590

    
2591
    // Disable calibration of the sleep counter
2592
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, 0x00);
2593
    _dwt_aonconfigupload();
2594

    
2595
    // Force system clock to crystal
2596
    _dwt_enableclocks(FORCE_SYS_XTI);
2597

    
2598
    deca_sleep(1);
2599

    
2600
    // Read the number of XTAL/2 cycles one LP oscillator cycle took.
2601
    // Set up address - Read upper byte first
2602
    dwt_write8bitoffsetreg(AON_ID, AON_ADDR_OFFSET, AON_ADDR_LPOSC_CAL_1);
2603

    
2604
    // Enable manual override
2605
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB);
2606

    
2607
    // Read confirm data that was written
2608
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB | AON_CTRL_DCA_READ);
2609

    
2610
    // Read back byte from AON
2611
    result = dwt_read8bitoffsetreg(AON_ID, AON_RDAT_OFFSET);
2612
    result <<= 8;
2613

    
2614
    // Set up address - Read lower byte
2615
    dwt_write8bitoffsetreg(AON_ID, AON_ADDR_OFFSET, AON_ADDR_LPOSC_CAL_0);
2616

    
2617
    // Enable manual override
2618
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB);
2619

    
2620
    // Read confirm data that was written
2621
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB | AON_CTRL_DCA_READ);
2622

    
2623
    // Read back byte from AON
2624
    result |= dwt_read8bitoffsetreg(AON_ID, AON_RDAT_OFFSET);
2625

    
2626
    // Disable manual override
2627
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00);
2628

    
2629
    // Put system PLL back on
2630
    _dwt_enableclocks(ENABLE_ALL_SEQ);
2631

    
2632
    // Returns the number of XTAL/2 cycles per one LP OSC cycle
2633
    // This can be converted into LP OSC frequency by 19.2 MHz/result
2634
    return result;
2635
}
2636

    
2637
/*! ------------------------------------------------------------------------------------------------------------------
2638
 * @fn dwt_configuresleep()
2639
 *
2640
 * @brief configures the device for both DEEP_SLEEP and SLEEP modes, and on-wake mode
2641
 * i.e. before entering the sleep, the device should be programmed for TX or RX, then upon "waking up" the TX/RX settings
2642
 * will be preserved and the device can immediately perform the desired action TX/RX
2643
 *
2644
 * NOTE: e.g. Tag operation - after deep sleep, the device needs to just load the TX buffer and send the frame
2645
 *
2646
 *
2647
 *      mode: the array and LDE code (OTP/ROM) and LDO tune, and set sleep persist
2648
 *      DWT_PRESRV_SLEEP 0x0100 - preserve sleep
2649
 *      DWT_LOADOPSET    0x0080 - load operating parameter set on wakeup
2650
 *      DWT_CONFIG       0x0040 - download the AON array into the HIF (configuration download)
2651
 *      DWT_LOADEUI      0x0008
2652
 *      DWT_GOTORX       0x0002
2653
 *      DWT_TANDV        0x0001
2654
 *
2655
 *      wake: wake up parameters
2656
 *      DWT_XTAL_EN      0x10 - keep XTAL running during sleep
2657
 *      DWT_WAKE_SLPCNT  0x8 - wake up after sleep count
2658
 *      DWT_WAKE_CS      0x4 - wake up on chip select
2659
 *      DWT_WAKE_WK      0x2 - wake up on WAKEUP PIN
2660
 *      DWT_SLP_EN       0x1 - enable sleep/deep sleep functionality
2661
 *
2662
 * input parameters
2663
 * @param mode - config on-wake parameters
2664
 * @param wake - config wake up parameters
2665
 *
2666
 * output parameters
2667
 *
2668
 * no return value
2669
 */
2670
void dwt_configuresleep(uint16_t mode, uint8_t wake)
2671
{
2672
    // Add predefined sleep settings before writing the mode
2673
    mode |= pdw1000local->sleep_mode;
2674
    dwt_write16bitoffsetreg(AON_ID, AON_WCFG_OFFSET, mode);
2675

    
2676
    dwt_write8bitoffsetreg(AON_ID, AON_CFG0_OFFSET, wake);
2677
}
2678

    
2679
/*! ------------------------------------------------------------------------------------------------------------------
2680
 * @fn dwt_entersleepaftertx(int enable)
2681
 *
2682
 * @brief sets the auto TX to sleep bit. This means that after a frame
2683
 * transmission the device will enter deep sleep mode. The dwt_configuresleep() function
2684
 * needs to be called before this to configure the on-wake settings
2685
 *
2686
 * NOTE: the IRQ line has to be low/inactive (i.e. no pending events)
2687
 *
2688
 * input parameters
2689
 * @param enable - 1 to configure the device to enter deep sleep after TX, 0 - disables the configuration
2690
 *
2691
 * output parameters
2692
 *
2693
 * no return value
2694
 */
2695
void dwt_entersleepaftertx(int enable)
2696
{
2697
    uint32_t reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET);
2698
    // Set the auto TX -> sleep bit
2699
    if(enable)
2700
    {
2701
        reg |= PMSC_CTRL1_ATXSLP;
2702
    }
2703
    else
2704
    {
2705
        reg &= ~(PMSC_CTRL1_ATXSLP);
2706
    }
2707
    dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, reg);
2708
}
2709

    
2710

    
2711
/*! ------------------------------------------------------------------------------------------------------------------
2712
 * @fn dwt_spicswakeup()
2713
 *
2714
 * @brief wake up the device from sleep mode using the SPI read,
2715
 * the device will wake up on chip select line going low if the line is held low for at least 500us.
2716
 * To define the length depending on the time one wants to hold
2717
 * the chip select line low, use the following formula:
2718
 *
2719
 *      length (bytes) = time (s) * byte_rate (Hz)
2720
 *
2721
 * where fastest byte_rate is spi_rate (Hz) / 8 if the SPI is sending the bytes back-to-back.
2722
 * To save time and power, a system designer could determine byte_rate value more precisely.
2723
 *
2724
 * NOTE: Alternatively the device can be waken up with WAKE_UP pin if configured for that operation
2725
 *
2726
 * input parameters
2727
 * @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
2728
 * @param length - this is the length of the dummy buffer
2729
 *
2730
 * output parameters
2731
 *
2732
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2733
 */
2734
int dwt_spicswakeup(uint8_t *buff, uint16_t length)
2735
{
2736
    if(dwt_readdevid() != DWT_DEVICE_ID) // Device was in deep sleep (the first read fails)
2737
    {
2738
        // Need to keep chip select line low for at least 500us
2739
        dwt_readfromdevice(0x0, 0x0, length, buff); // Do a long read to wake up the chip (hold the chip select low)
2740

    
2741
        // Need 5ms for XTAL to start and stabilise (could wait for PLL lock IRQ status bit !!!)
2742
        // NOTE: Polling of the STATUS register is not possible unless frequency is < 3MHz
2743
        deca_sleep(5);
2744
    }
2745
    else
2746
    {
2747
        return DWT_SUCCESS;
2748
    }
2749
    // DEBUG - check if still in sleep mode
2750
    if(dwt_readdevid() != DWT_DEVICE_ID)
2751
    {
2752
        return DWT_ERROR;
2753
    }
2754

    
2755
    return DWT_SUCCESS;
2756
}
2757

    
2758
/*! ------------------------------------------------------------------------------------------------------------------
2759
 * @fn _dwt_configlde()
2760
 *
2761
 * @brief configure LDE algorithm parameters
2762
 *
2763
 * input parameters
2764
 * @param prf   -   this is the PRF index (0 or 1) 0 corresponds to 16 and 1 to 64 PRF
2765
 *
2766
 * output parameters
2767
 *
2768
 * no return value
2769
 */
2770
void _dwt_configlde(int prfIndex)
2771
{
2772
    dwt_write8bitoffsetreg(LDE_IF_ID, LDE_CFG1_OFFSET, LDE_PARAM1); // 8-bit configuration register
2773

    
2774
    if(prfIndex)
2775
    {
2776
        dwt_write16bitoffsetreg( LDE_IF_ID, LDE_CFG2_OFFSET, (uint16_t) LDE_PARAM3_64); // 16-bit LDE configuration tuning register
2777
    }
2778
    else
2779
    {
2780
        dwt_write16bitoffsetreg( LDE_IF_ID, LDE_CFG2_OFFSET, (uint16_t) LDE_PARAM3_16);
2781
    }
2782
}
2783

    
2784

    
2785
/*! ------------------------------------------------------------------------------------------------------------------
2786
 * @fn _dwt_loaducodefromrom()
2787
 *
2788
 * @brief  load ucode from OTP MEMORY or ROM
2789
 *
2790
 * input parameters
2791
 *
2792
 * output parameters
2793
 *
2794
 * no return value
2795
 */
2796
void _dwt_loaducodefromrom(void)
2797
{
2798
    // Set up clocks
2799
    _dwt_enableclocks(FORCE_LDE);
2800

    
2801
    // Kick off the LDE load
2802
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_CTRL, OTP_CTRL_LDELOAD); // Set load LDE kick bit
2803

    
2804
    deca_sleep(1); // Allow time for code to upload (should take up to 120 us)
2805

    
2806
    // Default clocks (ENABLE_ALL_SEQ)
2807
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
2808
}
2809

    
2810
/*! ------------------------------------------------------------------------------------------------------------------
2811
 * @fn dwt_loadopsettabfromotp()
2812
 *
2813
 * @brief This is used to select which Operational Parameter Set table to load from OTP memory
2814
 *
2815
 * input parameters
2816
 * @param ops_sel - Operational Parameter Set table to load:
2817
 *                  DWT_OPSET_64LEN = 0x0 - load the operational parameter set table for 64 length preamble configuration
2818
 *                  DWT_OPSET_TIGHT = 0x1 - load the operational parameter set table for tight xtal offsets (<1ppm)
2819
 *                  DWT_OPSET_DEFLT = 0x2 - load the default operational parameter set table (this is loaded from reset)
2820
 *
2821
 * output parameters
2822
 *
2823
 * no return value
2824
 */
2825
void dwt_loadopsettabfromotp(uint8_t ops_sel)
2826
{
2827
    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
2828

    
2829
    // Set up clocks
2830
    _dwt_enableclocks(FORCE_LDE);
2831

    
2832
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_SF, reg);
2833

    
2834
    // Default clocks (ENABLE_ALL_SEQ)
2835
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
2836

    
2837
}
2838

    
2839
/*! ------------------------------------------------------------------------------------------------------------------
2840
 * @fn dwt_setsmarttxpower()
2841
 *
2842
 * @brief This call enables or disables the smart TX power feature.
2843
 *
2844
 * input parameters
2845
 * @param enable - this enables or disables the TX smart power (1 = enable, 0 = disable)
2846
 *
2847
 * output parameters
2848
 *
2849
 * no return value
2850
 */
2851
void dwt_setsmarttxpower(int enable)
2852
{
2853
    // Config system register
2854
    pdw1000local->sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
2855

    
2856
    // Disable smart power configuration
2857
    if(enable)
2858
    {
2859
        pdw1000local->sysCFGreg &= ~(SYS_CFG_DIS_STXP) ;
2860
    }
2861
    else
2862
    {
2863
        pdw1000local->sysCFGreg |= SYS_CFG_DIS_STXP ;
2864
    }
2865

    
2866
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2867
}
2868

    
2869

    
2870
/*! ------------------------------------------------------------------------------------------------------------------
2871
 * @fn dwt_enableautoack()
2872
 *
2873
 * @brief This call enables the auto-ACK feature. If the responseDelayTime (parameter) is 0, the ACK will be sent a.s.a.p.
2874
 * otherwise it will be sent with a programmed delay (in symbols), max is 255.
2875
 * NOTE: needs to have frame filtering enabled as well
2876
 *
2877
 * input parameters
2878
 * @param responseDelayTime - if non-zero the ACK is sent after this delay, max is 255.
2879
 *
2880
 * output parameters
2881
 *
2882
 * no return value
2883
 */
2884
void dwt_enableautoack(uint8_t responseDelayTime)
2885
{
2886
    // Set auto ACK reply delay
2887
    dwt_write8bitoffsetreg(ACK_RESP_T_ID, ACK_RESP_T_ACK_TIM_OFFSET, responseDelayTime); // In symbols
2888
    // Enable auto ACK
2889
    pdw1000local->sysCFGreg |= SYS_CFG_AUTOACK;
2890
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2891
}
2892

    
2893
/*! ------------------------------------------------------------------------------------------------------------------
2894
 * @fn dwt_setdblrxbuffmode()
2895
 *
2896
 * @brief This call enables the double receive buffer mode
2897
 *
2898
 * input parameters
2899
 * @param enable - 1 to enable, 0 to disable the double buffer mode
2900
 *
2901
 * output parameters
2902
 *
2903
 * no return value
2904
 */
2905
void dwt_setdblrxbuffmode(int enable)
2906
{
2907
    if(enable)
2908
    {
2909
        // Enable double RX buffer mode
2910
        pdw1000local->sysCFGreg &= ~SYS_CFG_DIS_DRXB;
2911
        pdw1000local->dblbuffon = 1;
2912
    }
2913
    else
2914
    {
2915
        // Disable double RX buffer mode
2916
        pdw1000local->sysCFGreg |= SYS_CFG_DIS_DRXB;
2917
        pdw1000local->dblbuffon = 0;
2918
    }
2919

    
2920
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2921
}
2922

    
2923
/*! ------------------------------------------------------------------------------------------------------------------
2924
 * @fn dwt_setrxaftertxdelay()
2925
 *
2926
 * @brief This sets the receiver turn on delay time after a transmission of a frame
2927
 *
2928
 * input parameters
2929
 * @param rxDelayTime - (20 bits) - the delay is in UWB microseconds
2930
 *
2931
 * output parameters
2932
 *
2933
 * no return value
2934
 */
2935
void dwt_setrxaftertxdelay(uint32_t rxDelayTime)
2936
{
2937
    uint32_t val = dwt_read32bitreg(ACK_RESP_T_ID) ; // Read ACK_RESP_T_ID register
2938

    
2939
    val &= ~(ACK_RESP_T_W4R_TIM_MASK) ; // Clear the timer (19:0)
2940

    
2941
    val |= (rxDelayTime & ACK_RESP_T_W4R_TIM_MASK) ; // In UWB microseconds (e.g. turn the receiver on 20uus after TX)
2942

    
2943
    dwt_write32bitreg(ACK_RESP_T_ID, val) ;
2944
}
2945

    
2946
/*! ------------------------------------------------------------------------------------------------------------------
2947
 * @fn dwt_setcallbacks()
2948
 *
2949
 * @brief This function is used to register the different callbacks called when one of the corresponding event occurs.
2950
 *
2951
 * NOTE: Callbacks can be undefined (set to NULL). In this case, dwt_isr() will process the event as usual but the 'null'
2952
 * callback will not be called.
2953
 *
2954
 * input parameters
2955
 * @param cbTxDone - the pointer to the TX confirmation event callback function
2956
 * @param cbRxOk - the pointer to the RX good frame event callback function
2957
 * @param cbRxTo - the pointer to the RX timeout events callback function
2958
 * @param cbRxErr - the pointer to the RX error events callback function
2959
 *
2960
 * output parameters
2961
 *
2962
 * no return value
2963
 */
2964
void dwt_setcallbacks(dwt_cb_t cbTxDone, dwt_cb_t cbRxOk, dwt_cb_t cbRxTo, dwt_cb_t cbRxErr)
2965
{
2966
    pdw1000local->cbTxDone = cbTxDone;
2967
    pdw1000local->cbRxOk = cbRxOk;
2968
    pdw1000local->cbRxTo = cbRxTo;
2969
    pdw1000local->cbRxErr = cbRxErr;
2970
}
2971

    
2972
/*! ------------------------------------------------------------------------------------------------------------------
2973
 * @fn dwt_checkirq()
2974
 *
2975
 * @brief This function checks if the IRQ line is active - this is used instead of interrupt handler
2976
 *
2977
 * input parameters
2978
 *
2979
 * output parameters
2980
 *
2981
 * return value is 1 if the IRQS bit is set and 0 otherwise
2982
 */
2983
uint8_t dwt_checkirq(void)
2984
{
2985
    return (dwt_read8bitoffsetreg(SYS_STATUS_ID, SYS_STATUS_OFFSET) & SYS_STATUS_IRQS); // Reading the lower byte only is enough for this operation
2986
}
2987

    
2988
/*! ------------------------------------------------------------------------------------------------------------------
2989
 * @fn dwt_isr()
2990
 *
2991
 * @brief This is the DW1000's general Interrupt Service Routine. It will process/report the following events:
2992
 *          - RXFCG (through cbRxOk callback)
2993
 *          - TXFRS (through cbTxDone callback)
2994
 *          - RXRFTO/RXPTO (through cbRxTo callback)
2995
 *          - RXPHE/RXFCE/RXRFSL/RXSFDTO/AFFREJ/LDEERR (through cbRxTo cbRxErr)
2996
 *        For all events, corresponding interrupts are cleared and necessary resets are performed. In addition, in the RXFCG case,
2997
 *        received frame information and frame control are read before calling the callback. If double buffering is activated, it
2998
 *        will also toggle between reception buffers once the reception callback processing has ended.
2999
 *
3000
 *        /!\ This version of the ISR supports double buffering but does not support automatic RX re-enabling!
3001
 *
3002
 * NOTE:  In PC based system using (Cheetah or ARM) USB to SPI converter there can be no interrupts, however we still need something
3003
 *        to take the place of it and operate in a polled way. In an embedded system this function should be configured to be triggered
3004
 *        on any of the interrupts described above.
3005

3006
 * input parameters
3007
 *
3008
 * output parameters
3009
 *
3010
 * no return value
3011
 */
3012
void dwt_isr(void)
3013
{
3014
    uint32_t status = pdw1000local->cbData.status = dwt_read32bitreg(SYS_STATUS_ID); // Read status register low 32bits
3015

    
3016
    // Handle RX good frame event