Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (150.762 KB)

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

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

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

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

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

    
31
#include <alld_DW1000.h>
32

    
33
#if (defined(AMIROLLD_CFG_DW1000) && (AMIROLLD_CFG_DW1000 == 0)) || defined(__DOXYGEN__)
34

    
35
#include <aos_thread.h>
36
#include <assert.h>
37
#include <string.h>
38
#include <stdlib.h>
39
#include <math.h>
40

    
41

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

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

    
53
// Defines for enable_clocks function
54
#define FORCE_SYS_XTI  0
55
#define ENABLE_ALL_SEQ 1
56
#define FORCE_SYS_PLL  2
57
#define READ_ACC_ON    7
58
#define READ_ACC_OFF   8
59
#define FORCE_OTP_ON   11
60
#define FORCE_OTP_OFF  12
61
#define FORCE_TX_PLL   13
62
#define FORCE_LDE      14
63

    
64
// Defines for ACK request bitmask in DATA and MAC COMMAND frame control (first byte) - Used to detect AAT bit wrongly set.
65
#define FCTRL_ACK_REQ_MASK 0x20
66
// Frame control maximum length in bytes.
67
#define FCTRL_LEN_MAX 2
68

    
69

    
70
#define NUM_BR 3
71
#define NUM_PRF 2
72
#define NUM_PACS 4
73
#define NUM_BW 2            //2 bandwidths are supported
74
#define NUM_SFD 2           //supported number of SFDs - standard = 0, non-standard = 1
75
#define NUM_CH 6            //supported channels are 1, 2, 3, 4, 5, 7
76
#define NUM_CH_SUPPORTED 8  //supported channels are '0', 1, 2, 3, 4, 5, '6', 7
77
#define PCODES 25           //supported preamble codes
78

    
79

    
80
typedef struct {
81
    uint32_t lo32;
82
    uint16_t target[NUM_PRF];
83
} agc_cfg_struct ;
84

    
85
extern const agc_cfg_struct agc_config ;
86

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

    
90
extern const uint16_t dtune1[NUM_PRF];
91

    
92
#define XMLPARAMS_VERSION   (1.17f)
93

    
94
extern const uint32_t fs_pll_cfg[NUM_CH];
95
extern const uint8_t fs_pll_tune[NUM_CH];
96
extern const uint8_t rx_config[NUM_BW];
97
extern const uint32_t tx_config[NUM_CH];
98
extern const uint8_t dwnsSFDlen[NUM_BR]; //length of SFD for each of the bitrates
99
extern const uint32_t digital_bb_config[NUM_PRF][NUM_PACS];
100
extern const uint8_t chan_idx[NUM_CH_SUPPORTED];
101
extern const double txpwr_compensation[NUM_CH];
102

    
103
#define PEAK_MULTPLIER  (0x60) //3 -> (0x3 * 32) & 0x00E0
104
#define N_STD_FACTOR    (13)
105
#define LDE_PARAM1      (PEAK_MULTPLIER | N_STD_FACTOR)
106

    
107
#define LDE_PARAM3_16 (0x1607)
108
#define LDE_PARAM3_64 (0x0607)
109

    
110
#define MIXER_GAIN_STEP (0.5)
111
#define DA_ATTN_STEP    (2.5)
112

    
113
// #define DWT_API_ERROR_CHECK     // define so API checks config input parameters
114

    
115
//-----------------------------------------
116
// map the channel number to the index in the configuration arrays below
117
// 0th element is chan 1, 1st is chan 2, 2nd is chan 3, 3rd is chan 4, 4th is chan 5, 5th is chan 7
118
const uint8_t chan_idx[NUM_CH_SUPPORTED] = {0, 0, 1, 2, 3, 4, 0, 5};
119

    
120
//-----------------------------------------
121
const uint32_t tx_config[NUM_CH] =
122
{
123
    RF_TXCTRL_CH1,
124
    RF_TXCTRL_CH2,
125
    RF_TXCTRL_CH3,
126
    RF_TXCTRL_CH4,
127
    RF_TXCTRL_CH5,
128
    RF_TXCTRL_CH7,
129
};
130

    
131
//Frequency Synthesiser - PLL configuration
132
const uint32_t fs_pll_cfg[NUM_CH] =
133
{
134
    FS_PLLCFG_CH1,
135
    FS_PLLCFG_CH2,
136
    FS_PLLCFG_CH3,
137
    FS_PLLCFG_CH4,
138
    FS_PLLCFG_CH5,
139
    FS_PLLCFG_CH7
140
};
141

    
142
//Frequency Synthesiser - PLL tuning
143
const uint8_t fs_pll_tune[NUM_CH] =
144
{
145
    FS_PLLTUNE_CH1,
146
    FS_PLLTUNE_CH2,
147
    FS_PLLTUNE_CH3,
148
    FS_PLLTUNE_CH4,
149
    FS_PLLTUNE_CH5,
150
    FS_PLLTUNE_CH7
151
};
152

    
153
//bandwidth configuration
154
const uint8_t rx_config[NUM_BW] =
155
{
156
    RF_RXCTRLH_NBW,
157
    RF_RXCTRLH_WBW
158
};
159

    
160

    
161
const agc_cfg_struct agc_config =
162
{
163
    AGC_TUNE2_VAL,
164
    { AGC_TUNE1_16M , AGC_TUNE1_64M }  //adc target
165
};
166

    
167
//DW non-standard SFD length for 110k, 850k and 6.81M
168
const uint8_t dwnsSFDlen[NUM_BR] =
169
{
170
    DW_NS_SFD_LEN_110K,
171
    DW_NS_SFD_LEN_850K,
172
    DW_NS_SFD_LEN_6M8
173
};
174

    
175
// SFD Threshold
176
const uint16_t sftsh[NUM_BR][NUM_SFD] =
177
{
178
    {
179
        DRX_TUNE0b_110K_STD,
180
        DRX_TUNE0b_110K_NSTD
181
    },
182
    {
183
        DRX_TUNE0b_850K_STD,
184
        DRX_TUNE0b_850K_NSTD
185
    },
186
    {
187
        DRX_TUNE0b_6M8_STD,
188
        DRX_TUNE0b_6M8_NSTD
189
    }
190
};
191

    
192
const uint16_t dtune1[NUM_PRF] =
193
{
194
    DRX_TUNE1a_PRF16,
195
    DRX_TUNE1a_PRF64
196
};
197

    
198
const uint32_t digital_bb_config[NUM_PRF][NUM_PACS] =
199
{
200
    {
201
        DRX_TUNE2_PRF16_PAC8,
202
        DRX_TUNE2_PRF16_PAC16,
203
        DRX_TUNE2_PRF16_PAC32,
204
        DRX_TUNE2_PRF16_PAC64
205
    },
206
    {
207
        DRX_TUNE2_PRF64_PAC8,
208
        DRX_TUNE2_PRF64_PAC16,
209
        DRX_TUNE2_PRF64_PAC32,
210
        DRX_TUNE2_PRF64_PAC64
211
    }
212
};
213

    
214
const uint16_t lde_replicaCoeff[PCODES] =
215
{
216
    0, // No preamble code 0
217
    LDE_REPC_PCODE_1,
218
    LDE_REPC_PCODE_2,
219
    LDE_REPC_PCODE_3,
220
    LDE_REPC_PCODE_4,
221
    LDE_REPC_PCODE_5,
222
    LDE_REPC_PCODE_6,
223
    LDE_REPC_PCODE_7,
224
    LDE_REPC_PCODE_8,
225
    LDE_REPC_PCODE_9,
226
    LDE_REPC_PCODE_10,
227
    LDE_REPC_PCODE_11,
228
    LDE_REPC_PCODE_12,
229
    LDE_REPC_PCODE_13,
230
    LDE_REPC_PCODE_14,
231
    LDE_REPC_PCODE_15,
232
    LDE_REPC_PCODE_16,
233
    LDE_REPC_PCODE_17,
234
    LDE_REPC_PCODE_18,
235
    LDE_REPC_PCODE_19,
236
    LDE_REPC_PCODE_20,
237
    LDE_REPC_PCODE_21,
238
    LDE_REPC_PCODE_22,
239
    LDE_REPC_PCODE_23,
240
    LDE_REPC_PCODE_24
241
};
242

    
243
const double txpwr_compensation[NUM_CH] = {
244
    0.0,
245
    0.035,
246
    0.0,
247
    0.0,
248
    0.065,
249
    0.0
250
};
251

    
252

    
253
#define NUM_16M_OFFSET  (37)
254
#define NUM_16M_OFFSETWB  (68)
255
#define NUM_64M_OFFSET  (26)
256
#define NUM_64M_OFFSETWB  (59)
257

    
258
const uint8_t chan_idxnb[NUM_CH_SUPPORTED] = {0, 0, 1, 2, 0, 3, 0, 0}; //only channels 1,2,3 and 5 are in the narrow band tables
259
const uint8_t chan_idxwb[NUM_CH_SUPPORTED] = {0, 0, 0, 0, 0, 0, 0, 1}; //only channels 4 and 7 are in in the wide band tables
260

    
261
//---------------------------------------------------------------------------------------------------------------------------
262
// Range Bias Correction TABLES of range values in integer units of 25 CM, for 8-bit unsigned storage, MUST END IN 255 !!!!!!
263
//---------------------------------------------------------------------------------------------------------------------------
264

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

    
267
#define CM_OFFSET_16M_NB    (-23)   // for normal band channels at 16 MHz PRF
268
#define CM_OFFSET_16M_WB    (-28)   // for wider  band channels at 16 MHz PRF
269
#define CM_OFFSET_64M_NB    (-17)   // for normal band channels at 64 MHz PRF
270
#define CM_OFFSET_64M_WB    (-30)   // for wider  band channels at 64 MHz PRF
271

    
272

    
273
//---------------------------------------------------------------------------------------------------------------------------
274
// range25cm16PRFnb: Range Bias Correction table for narrow band channels at 16 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
275
//---------------------------------------------------------------------------------------------------------------------------
276

    
277
const uint8_t range25cm16PRFnb[4][NUM_16M_OFFSET] =
278
{
279
    // ch 1 - range25cm16PRFnb
280
    {
281
           1,
282
           3,
283
           4,
284
           5,
285
           7,
286
           9,
287
          11,
288
          12,
289
          13,
290
          15,
291
          18,
292
          20,
293
          23,
294
          25,
295
          28,
296
          30,
297
          33,
298
          36,
299
          40,
300
          43,
301
          47,
302
          50,
303
          54,
304
          58,
305
          63,
306
          66,
307
          71,
308
          76,
309
          82,
310
          89,
311
          98,
312
         109,
313
         127,
314
         155,
315
         222,
316
         255,
317
         255
318
    },
319

    
320
    // ch 2 - range25cm16PRFnb
321
    {
322
           1,
323
           2,
324
           4,
325
           5,
326
           6,
327
           8,
328
           9,
329
          10,
330
          12,
331
          13,
332
          15,
333
          18,
334
          20,
335
          22,
336
          24,
337
          27,
338
          29,
339
          32,
340
          35,
341
          38,
342
          41,
343
          44,
344
          47,
345
          51,
346
          55,
347
          58,
348
          62,
349
          66,
350
          71,
351
          78,
352
          85,
353
          96,
354
         111,
355
         135,
356
         194,
357
         240,
358
         255
359
    },
360

    
361
    // ch 3 - range25cm16PRFnb
362
    {
363
           1,
364
           2,
365
           3,
366
           4,
367
           5,
368
           7,
369
           8,
370
           9,
371
          10,
372
          12,
373
          14,
374
          16,
375
          18,
376
          20,
377
          22,
378
          24,
379
          26,
380
          28,
381
          31,
382
          33,
383
          36,
384
          39,
385
          42,
386
          45,
387
          49,
388
          52,
389
          55,
390
          59,
391
          63,
392
          69,
393
          76,
394
          85,
395
          98,
396
         120,
397
         173,
398
         213,
399
         255
400
    },
401

    
402
    // ch 5 - range25cm16PRFnb
403
    {
404
           1,
405
           1,
406
           2,
407
           3,
408
           4,
409
           5,
410
           6,
411
           6,
412
           7,
413
           8,
414
           9,
415
          11,
416
          12,
417
          14,
418
          15,
419
          16,
420
          18,
421
          20,
422
          21,
423
          23,
424
          25,
425
          27,
426
          29,
427
          31,
428
          34,
429
          36,
430
          38,
431
          41,
432
          44,
433
          48,
434
          53,
435
          59,
436
          68,
437
          83,
438
         120,
439
         148,
440
         255
441
    }
442
}; // end range25cm16PRFnb
443

    
444

    
445
//---------------------------------------------------------------------------------------------------------------------------
446
// range25cm16PRFwb: Range Bias Correction table for wide band channels at 16 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
447
//---------------------------------------------------------------------------------------------------------------------------
448

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

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

    
596
//---------------------------------------------------------------------------------------------------------------------------
597
// range25cm64PRFnb: Range Bias Correction table for narrow band channels at 64 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
598
//---------------------------------------------------------------------------------------------------------------------------
599

    
600
const uint8_t range25cm64PRFnb[4][NUM_64M_OFFSET] =
601
{
602
    // ch 1 - range25cm64PRFnb
603
    {
604
           1,
605
           2,
606
           2,
607
           3,
608
           4,
609
           5,
610
           7,
611
          10,
612
          13,
613
          16,
614
          19,
615
          22,
616
          24,
617
          27,
618
          30,
619
          32,
620
          35,
621
          38,
622
          43,
623
          48,
624
          56,
625
          78,
626
         101,
627
         120,
628
         157,
629
         255
630
    },
631

    
632
    // ch 2 - range25cm64PRFnb
633
    {
634
           1,
635
           2,
636
           2,
637
           3,
638
           4,
639
           4,
640
           6,
641
           9,
642
          12,
643
          14,
644
          17,
645
          19,
646
          21,
647
          24,
648
          26,
649
          28,
650
          31,
651
          33,
652
          37,
653
          42,
654
          49,
655
          68,
656
          89,
657
         105,
658
         138,
659
         255
660
    },
661

    
662
    // ch 3 - range25cm64PRFnb
663
    {
664
           1,
665
           1,
666
           2,
667
           3,
668
           3,
669
           4,
670
           5,
671
           8,
672
          10,
673
          13,
674
          15,
675
          17,
676
          19,
677
          21,
678
          23,
679
          25,
680
          27,
681
          30,
682
          33,
683
          37,
684
          44,
685
          60,
686
          79,
687
          93,
688
         122,
689
         255
690
    },
691

    
692
    // ch 5 - range25cm64PRFnb
693
    {
694
           1,
695
           1,
696
           1,
697
           2,
698
           2,
699
           3,
700
           4,
701
           6,
702
           7,
703
           9,
704
          10,
705
          12,
706
          13,
707
          15,
708
          16,
709
          17,
710
          19,
711
          21,
712
          23,
713
          26,
714
          30,
715
          42,
716
          55,
717
          65,
718
          85,
719
         255
720
    }
721
}; // end range25cm64PRFnb
722

    
723
//---------------------------------------------------------------------------------------------------------------------------
724
// range25cm64PRFwb: Range Bias Correction table for wide band channels at 64 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
725
//---------------------------------------------------------------------------------------------------------------------------
726

    
727
const uint8_t range25cm64PRFwb[2][NUM_64M_OFFSETWB] =
728
{
729
    // ch 4 - range25cm64PRFwb
730
    {
731
           7,
732
           8,
733
           8,
734
           9,
735
           9,
736
          10,
737
          11,
738
          12,
739
          13,
740
          13,
741
          14,
742
          15,
743
          16,
744
          16,
745
          17,
746
          18,
747
          19,
748
          19,
749
          20,
750
          21,
751
          22,
752
          24,
753
          25,
754
          27,
755
          28,
756
          29,
757
          30,
758
          32,
759
          33,
760
          34,
761
          35,
762
          37,
763
          39,
764
          41,
765
          43,
766
          45,
767
          48,
768
          50,
769
          53,
770
          56,
771
          60,
772
          64,
773
          68,
774
          74,
775
          81,
776
          89,
777
          98,
778
         109,
779
         122,
780
         136,
781
         146,
782
         154,
783
         162,
784
         178,
785
         220,
786
         249,
787
         255,
788
         255,
789
         255
790
    },
791

    
792
    // ch 7 - range25cm64PRFwb
793
    {
794
           4,
795
           5,
796
           5,
797
           5,
798
           6,
799
           6,
800
           7,
801
           7,
802
           8,
803
           8,
804
           9,
805
           9,
806
          10,
807
          10,
808
          10,
809
          11,
810
          11,
811
          12,
812
          13,
813
          13,
814
          14,
815
          15,
816
          16,
817
          16,
818
          17,
819
          18,
820
          19,
821
          19,
822
          20,
823
          21,
824
          22,
825
          23,
826
          24,
827
          25,
828
          26,
829
          28,
830
          29,
831
          31,
832
          33,
833
          35,
834
          37,
835
          39,
836
          42,
837
          46,
838
          50,
839
          54,
840
          60,
841
          67,
842
          75,
843
          83,
844
          90,
845
          95,
846
         100,
847
         110,
848
         135,
849
         153,
850
         172,
851
         192,
852
         255
853
    }
854
}; // end range25cm64PRFwb
855

    
856

    
857

    
858

    
859

    
860
/*! ------------------------------------------------------------------------------------------------------------------
861
 * Function: dwt_getrangebias()
862
 *
863
 * Description: This function is used to return the range bias correction need for TWR with DW1000 units.
864
 *
865
 * input parameters:        
866
 * @param chan  - specifies the operating channel (e.g. 1, 2, 3, 4, 5, 6 or 7) 
867
 * @param range - the calculated distance before correction
868
 * @param prf        - this is the PRF e.g. DWT_PRF_16M or DWT_PRF_64M
869
 *
870
 * output parameters
871
 *
872
 * returns correction needed in meters
873
 */
874
double dwt_getrangebias(uint8_t chan, float range, uint8_t prf)
875
{
876
    //first get the lookup index that corresponds to given range for a particular channel at 16M PRF
877
    int i = 0 ;
878
    int chanIdx ;
879
    int cmoffseti ;                                 // integer number of CM offset
880

    
881
    double mOffset ;                                // final offset result in metres
882

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

    
885
    int rangeint25cm = (int) (range * 4.00) ;       // convert range to integer number of 25cm values.
886

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

    
889
    if (prf == DWT_PRF_16M)
890
    {
891
        switch(chan)
892
        {
893
            case 4:
894
            case 7:
895
            {
896
                chanIdx = chan_idxwb[chan];
897
                while (rangeint25cm > range25cm16PRFwb[chanIdx][i]) i++ ;       // find index in table corresponding to range
898
                cmoffseti = i + CM_OFFSET_16M_WB ;                              // nearest centimeter correction
899
            }
900
            break;
901
            default:
902
            {
903
                chanIdx = chan_idxnb[chan];
904
                while (rangeint25cm > range25cm16PRFnb[chanIdx][i]) i++ ;       // find index in table corresponding to range
905
                cmoffseti = i + CM_OFFSET_16M_NB ;                              // nearest centimeter correction
906
            }
907
        }//end of switch
908
    }
909
    else // 64M PRF
910
    {
911
        switch(chan)
912
        {
913
            case 4:
914
            case 7:
915
            {
916
                chanIdx = chan_idxwb[chan];
917
                while (rangeint25cm > range25cm64PRFwb[chanIdx][i]) i++ ;       // find index in table corresponding to range
918
                cmoffseti = i + CM_OFFSET_64M_WB ;                              // nearest centimeter correction
919
            }
920
            break;
921
            default:
922
            {
923
                chanIdx = chan_idxnb[chan];
924
                while (rangeint25cm > range25cm64PRFnb[chanIdx][i]) i++ ;       // find index in table corresponding to range
925
                cmoffseti = i + CM_OFFSET_64M_NB ;                              // nearest centimeter correction
926
            }
927
        }//end of switch
928
    } // end else
929

    
930

    
931
    mOffset = (float) cmoffseti ;                                       // offset result in centimmetres
932

    
933
    mOffset *= 0.01 ;                                                   // convert to metres
934

    
935
    return (mOffset) ;
936
}
937

    
938

    
939

    
940
// -------------------------------------------------------------------------------------------------------------------
941
//
942
// Internal functions for controlling and configuring the device
943
//
944
// -------------------------------------------------------------------------------------------------------------------
945

    
946
// Enable and Configure specified clocks
947
void _dwt_enableclocks(int clocks) ;
948
// Configure the ucode (FP algorithm) parameters
949
void _dwt_configlde(int prf);
950
// Load ucode from OTP/ROM
951
void _dwt_loaducodefromrom(void);
952
// Read non-volatile memory
953
uint32_t _dwt_otpread(uint32_t address);
954
// Program the non-volatile memory
955
uint32_t _dwt_otpprogword32(uint32_t data, uint16_t address);
956
// Upload the device configuration into always on memory
957
void _dwt_aonarrayupload(void);
958
// -------------------------------------------------------------------------------------------------------------------
959

    
960
/*!
961
 * Static data for DW1000 DecaWave Transceiver control
962
 */
963

    
964
static dwt_local_data_t dw1000local[DWT_NUM_DW_DEV] ; // Static local device data, can be an array to support multiple DW1000 testing applications/platforms
965
static dwt_local_data_t *pdw1000local = dw1000local ; // Static local data structure pointer
966

    
967

    
968
/*! ------------------------------------------------------------------------------------------------------------------
969
 * @fn dwt_setdevicedataptr()
970
 *
971
 * @brief This function sets the local data structure pointer to point to the structure in the local array as given by the index.
972
 *
973
 * input parameters
974
 * @param index    - selects the array object to point to. Must be within the array bounds, i.e. < DWT_NUM_DW_DEV
975
 *
976
 * output parameters
977
 *
978
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
979
 */
980
int dwt_setdevicedataptr(unsigned int index)
981
{
982
    // Check the index is within the array bounds
983
    if (DWT_NUM_DW_DEV > index) // return error if index outside the array bounds
984
    {
985
        return DWT_ERROR ;
986
    }
987

    
988
    pdw1000local = &dw1000local[index];
989

    
990
    return DWT_SUCCESS ;
991
}
992

    
993
/*! ------------------------------------------------------------------------------------------------------------------
994
 * @fn dwt_initialise()
995
 *
996
 * @brief This function initiates communications with the DW1000 transceiver
997
 * and reads its DEV_ID register (address 0x00) to verify the IC is one supported
998
 * by this software (e.g. DW1000 32-bit device ID value is 0xDECA0130).  Then it
999
 * does any initial once only device configurations needed for use and initialises
1000
 * as necessary any static data items belonging to this low-level driver.
1001
 *
1002
 * NOTES:
1003
 * 1.this function needs to be run before dwt_configuresleep, also the SPI frequency has to be < 3MHz
1004
 * 2.it also reads and applies LDO tune and crystal trim values from OTP memory
1005
 *
1006
 * input parameters
1007
 * @param config    -   specifies what configuration to load
1008
 *                  DWT_LOADUCODE     0x1 - load the LDE microcode from ROM - enabled accurate RX timestamp
1009
 *                  DWT_LOADNONE      0x0 - do not load any values from OTP memory
1010
 *
1011
 * output parameters
1012
 *
1013
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
1014
 */
1015
// OTP addresses definitions
1016
#define LDOTUNE_ADDRESS (0x04)
1017
#define PARTID_ADDRESS (0x06)
1018
#define LOTID_ADDRESS  (0x07)
1019
#define VBAT_ADDRESS   (0x08)
1020
#define VTEMP_ADDRESS  (0x09)
1021
#define XTRIM_ADDRESS  (0x1E)
1022

    
1023
int dwt_initialise(const uint16_t config, DW1000Driver* drv)
1024
{
1025
    uint16_t otp_addr = 0;
1026
    uint32_t ldo_tune = 0;
1027

    
1028
    pdw1000local->dblbuffon = 0; // Double buffer mode off by default
1029
    pdw1000local->wait4resp = 0;
1030
    pdw1000local->sleep_mode = 0;
1031

    
1032
    pdw1000local->cbTxDone = NULL;
1033
    pdw1000local->cbRxOk = NULL;
1034
    pdw1000local->cbRxTo = NULL;
1035
    pdw1000local->cbRxErr = NULL;
1036

    
1037
    pdw1000local->driver = drv;
1038

    
1039
    // Read and validate device ID return -1 if not recognised
1040
    if (DWT_DEVICE_ID != dwt_readdevid()) // MP IC ONLY (i.e. DW1000) FOR THIS CODE
1041
    {
1042
        return DWT_ERROR ;
1043
    }
1044

    
1045
    // Make sure the device is completely reset before starting initialisation
1046
    dwt_softreset();
1047

    
1048
    _dwt_enableclocks(FORCE_SYS_XTI); // NOTE: set system clock to XTI - this is necessary to make sure the values read by _dwt_otpread are reliable
1049

    
1050
    // Configure the CPLL lock detect
1051
    dwt_write8bitoffsetreg(EXT_SYNC_ID, EC_CTRL_OFFSET, EC_CTRL_PLLLCK);
1052

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

    
1057
    // Load LDO tune from OTP and kick it if there is a value actually programmed.
1058
    ldo_tune = _dwt_otpread(LDOTUNE_ADDRESS);
1059
    if((ldo_tune & 0xFF) != 0)
1060
    {
1061
        // Kick LDO tune
1062
        dwt_write8bitoffsetreg(OTP_IF_ID, OTP_SF, OTP_SF_LDO_KICK); // Set load LDE kick bit
1063
        pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDO; // LDO tune must be kicked at wake-up
1064
    }
1065

    
1066
    // Load Part and Lot ID from OTP
1067
    pdw1000local->partID = _dwt_otpread(PARTID_ADDRESS);
1068
    pdw1000local->lotID = _dwt_otpread(LOTID_ADDRESS);
1069

    
1070
    // XTAL trim value is set in OTP for DW1000 module and EVK/TREK boards but that might not be the case in a custom design
1071
    pdw1000local->init_xtrim = otp_addr & 0x1F;
1072
    if (!pdw1000local->init_xtrim) // A value of 0 means that the crystal has not been trimmed
1073
    {
1074
        pdw1000local->init_xtrim = FS_XTALT_MIDRANGE ; // Set to mid-range if no calibration value inside
1075
    }
1076
    // Configure XTAL trim
1077
    dwt_setxtaltrim(pdw1000local->init_xtrim);
1078

    
1079
    // Load leading edge detect code
1080
    if(config & DWT_LOADUCODE)
1081
    {
1082
        _dwt_loaducodefromrom();
1083
        pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDE; // microcode must be loaded at wake-up
1084
    }
1085
    else // Should disable the LDERUN enable bit in 0x36, 0x4
1086
    {
1087
        uint16_t rega = dwt_read16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1) ;
1088
        rega &= 0xFDFF ; // Clear LDERUN bit
1089
        dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1, rega) ;
1090
    }
1091

    
1092
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
1093

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

    
1097
    // Read system register / store local copy
1098
    pdw1000local->sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
1099

    
1100
    return DWT_SUCCESS ;
1101

    
1102
} // end dwt_initialise()
1103

    
1104
/*! ------------------------------------------------------------------------------------------------------------------
1105
 * @fn dwt_otprevision()
1106
 *
1107
 * @brief This is used to return the read OTP revision
1108
 *
1109
 * NOTE: dwt_initialise() must be called prior to this function so that it can return a relevant value.
1110
 *
1111
 * input parameters
1112
 *
1113
 * output parameters
1114
 *
1115
 * returns the read OTP revision value
1116
 */
1117
uint8_t dwt_otprevision(void)
1118
{
1119
    return pdw1000local->otprev ;
1120
}
1121

    
1122
/*! ------------------------------------------------------------------------------------------------------------------
1123
 * @fn dwt_setfinegraintxseq()
1124
 *
1125
 * @brief This function enables/disables the fine grain TX sequencing (enabled by default).
1126
 *
1127
 * input parameters
1128
 * @param enable - 1 to enable fine grain TX sequencing, 0 to disable it.
1129
 *
1130
 * output parameters none
1131
 *
1132
 * no return value
1133
 */
1134
void dwt_setfinegraintxseq(int enable)
1135
{
1136
    if (enable)
1137
    {
1138
        dwt_write16bitoffsetreg(PMSC_ID, PMSC_TXFINESEQ_OFFSET, PMSC_TXFINESEQ_ENABLE);
1139
    }
1140
    else
1141
    {
1142
        dwt_write16bitoffsetreg(PMSC_ID, PMSC_TXFINESEQ_OFFSET, PMSC_TXFINESEQ_DISABLE);
1143
    }
1144
}
1145

    
1146
/*! ------------------------------------------------------------------------------------------------------------------
1147
 * @fn dwt_setlnapamode()
1148
 *
1149
 * @brief This is used to enable GPIO for external LNA or PA functionality - HW dependent, consult the DW1000 User Manual.
1150
 *        This can also be used for debug as enabling TX and RX GPIOs is quite handy to monitor DW1000's activity.
1151
 *
1152
 * NOTE: Enabling PA functionality requires that fine grain TX sequencing is deactivated. This can be done using
1153
 *       dwt_setfinegraintxseq().
1154
 *
1155
 * input parameters
1156
 * @param lna - 1 to enable LNA functionality, 0 to disable it
1157
 * @param pa - 1 to enable PA functionality, 0 to disable it
1158
 *
1159
 * output parameters
1160
 *
1161
 * no return value
1162
 */
1163
void dwt_setlnapamode(int lna, int pa)
1164
{
1165
    uint32_t gpio_mode = dwt_read32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET);
1166
    gpio_mode &= ~(GPIO_MSGP4_MASK | GPIO_MSGP5_MASK | GPIO_MSGP6_MASK);
1167
    if (lna)
1168
    {
1169
        gpio_mode |= GPIO_PIN6_EXTRXE;
1170
    }
1171
    if (pa)
1172
    {
1173
        gpio_mode |= (GPIO_PIN5_EXTTXE | GPIO_PIN4_EXTPA);
1174
    }
1175
    dwt_write32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET, gpio_mode);
1176
}
1177

    
1178
/*! ------------------------------------------------------------------------------------------------------------------
1179
 * @fn dwt_setgpiodirection()
1180
 *
1181
 * @brief This is used to set GPIO direction as an input (1) or output (0)
1182
 *
1183
 * input parameters
1184
 * @param gpioNum    -   this is the GPIO to configure - see GxM0... GxM8 in the deca_regs.h file
1185
 * @param direction  -   this sets the GPIO direction - see GxP0... GxP8 in the deca_regs.h file
1186
 *
1187
 * output parameters
1188
 *
1189
 * no return value
1190
 */
1191
void dwt_setgpiodirection(uint32_t gpioNum, uint32_t direction)
1192
{
1193
    uint8_t buf[GPIO_DIR_LEN];
1194
    uint32_t command = direction | gpioNum;
1195

    
1196
    buf[0] = command & 0xff;
1197
    buf[1] = (command >> 8) & 0xff;
1198
    buf[2] = (command >> 16) & 0xff;
1199

    
1200
    dwt_writetodevice(GPIO_CTRL_ID, GPIO_DIR_OFFSET, GPIO_DIR_LEN, buf);
1201
}
1202

    
1203
/*! ------------------------------------------------------------------------------------------------------------------
1204
 * @fn dwt_setgpiovalue()
1205
 *
1206
 * @brief This is used to set GPIO value as (1) or (0) only applies if the GPIO is configured as output
1207
 *
1208
 * input parameters
1209
 * @param gpioNum    -   this is the GPIO to configure - see GxM0... GxM8 in the deca_regs.h file
1210
 * @param value  -   this sets the GPIO value - see GDP0... GDP8 in the deca_regs.h file
1211
 *
1212
 * output parameters
1213
 *
1214
 * no return value
1215
 */
1216
void dwt_setgpiovalue(uint32_t gpioNum, uint32_t value)
1217
{
1218
    uint8_t buf[GPIO_DOUT_LEN];
1219
    uint32_t command = value | gpioNum;
1220

    
1221
    buf[0] = command & 0xff;
1222
    buf[1] = (command >> 8) & 0xff;
1223
    buf[2] = (command >> 16) & 0xff;
1224

    
1225
    dwt_writetodevice(GPIO_CTRL_ID, GPIO_DOUT_OFFSET, GPIO_DOUT_LEN, buf);
1226
}
1227

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

    
1246
/*! ------------------------------------------------------------------------------------------------------------------
1247
 * @fn dwt_getlotid()
1248
 *
1249
 * @brief This is used to return the read lot ID of the device
1250
 *
1251
 * NOTE: dwt_initialise() must be called prior to this function so that it can return a relevant value.
1252
 *
1253
 * input parameters
1254
 *
1255
 * output parameters
1256
 *
1257
 * returns the 32 bit lot ID value as programmed in the factory
1258
 */
1259
uint32_t dwt_getlotid(void)
1260
{
1261
    return pdw1000local->lotID;
1262
}
1263

    
1264
/*! ------------------------------------------------------------------------------------------------------------------
1265
 * @fn dwt_readdevid()
1266
 *
1267
 * @brief This is used to return the read device type and revision information of the DW1000 device (MP part is 0xDECA0130)
1268
 *
1269
 * input parameters
1270
 *
1271
 * output parameters
1272
 *
1273
 * returns the read value which for DW1000 is 0xDECA0130
1274
 */
1275
uint32_t dwt_readdevid(void)
1276
{
1277
    return dwt_read32bitoffsetreg(DEV_ID_ID,0);
1278
}
1279

    
1280
/*! ------------------------------------------------------------------------------------------------------------------
1281
 * @fn dwt_configuretxrf()
1282
 *
1283
 * @brief This function provides the API for the configuration of the TX spectrum
1284
 * including the power and pulse generator delay. The input is a pointer to the data structure
1285
 * of type dwt_txconfig_t that holds all the configurable items.
1286
 *
1287
 * input parameters
1288
 * @param config    -   pointer to the txrf configuration structure, which contains the tx rf config data
1289
 *
1290
 * output parameters
1291
 *
1292
 * no return value
1293
 */
1294
void dwt_configuretxrf(dwt_txconfig_t* config)
1295
{
1296

    
1297
    // Configure RF TX PG_DELAY
1298
    dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGDELAY_OFFSET, config->PGdly);
1299

    
1300
    // Configure TX power
1301
    dwt_write32bitreg(TX_POWER_ID, config->power);
1302

    
1303
}
1304

    
1305
/*! ------------------------------------------------------------------------------------------------------------------
1306
 * @fn dwt_configure()
1307
 *
1308
 * @brief This function provides the main API for the configuration of the
1309
 * DW1000 and this low-level driver.  The input is a pointer to the data structure
1310
 * of type dwt_config_t that holds all the configurable items.
1311
 * The dwt_config_t structure shows which ones are supported
1312
 *
1313
 * input parameters
1314
 * @param config    -   pointer to the configuration structure, which contains the device configuration data.
1315
 *
1316
 * output parameters
1317
 *
1318
 * no return value
1319
 */
1320
void dwt_configure(dwt_config_t *config)
1321
{
1322
    uint8_t nsSfd_result  = 0;
1323
    uint8_t useDWnsSFD = 0;
1324
    uint8_t chan = config->chan ;
1325
    uint32_t regval ;
1326
    uint16_t reg16 = lde_replicaCoeff[config->rxCode];
1327
    uint8_t prfIndex = config->prf - DWT_PRF_16M;
1328
    uint8_t bw = ((chan == 4) || (chan == 7)) ? 1 : 0 ; // Select wide or narrow band
1329

    
1330
#ifdef DWT_API_ERROR_CHECK
1331
    assert(config->dataRate <= DWT_BR_6M8);
1332
    assert(config->rxPAC <= DWT_PAC64);
1333
    assert((chan >= 1) && (chan <= 7) && (chan != 6));
1334
    assert(((config->prf == DWT_PRF_64M) && (config->txCode >= 9) && (config->txCode <= 24))
1335
           || ((config->prf == DWT_PRF_16M) && (config->txCode >= 1) && (config->txCode <= 8)));
1336
    assert(((config->prf == DWT_PRF_64M) && (config->rxCode >= 9) && (config->rxCode <= 24))
1337
           || ((config->prf == DWT_PRF_16M) && (config->rxCode >= 1) && (config->rxCode <= 8)));
1338
    assert((config->txPreambLength == DWT_PLEN_64) || (config->txPreambLength == DWT_PLEN_128) || (config->txPreambLength == DWT_PLEN_256)
1339
           || (config->txPreambLength == DWT_PLEN_512) || (config->txPreambLength == DWT_PLEN_1024) || (config->txPreambLength == DWT_PLEN_1536)
1340
           || (config->txPreambLength == DWT_PLEN_2048) || (config->txPreambLength == DWT_PLEN_4096));
1341
    assert((config->phrMode == DWT_PHRMODE_STD) || (config->phrMode == DWT_PHRMODE_EXT));
1342
#endif
1343

    
1344
    // For 110 kbps we need a special setup
1345
    if(DWT_BR_110K == config->dataRate)
1346
    {
1347
        pdw1000local->sysCFGreg |= SYS_CFG_RXM110K ;
1348
        reg16 >>= 3; // lde_replicaCoeff must be divided by 8
1349
    }
1350
    else
1351
    {
1352
        pdw1000local->sysCFGreg &= (~SYS_CFG_RXM110K) ;
1353
    }
1354

    
1355
    pdw1000local->longFrames = config->phrMode ;
1356

    
1357
    pdw1000local->sysCFGreg &= ~SYS_CFG_PHR_MODE_11;
1358
    pdw1000local->sysCFGreg |= (SYS_CFG_PHR_MODE_11 & (config->phrMode << SYS_CFG_PHR_MODE_SHFT));
1359

    
1360
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
1361
    // Set the lde_replicaCoeff
1362
    dwt_write16bitoffsetreg(LDE_IF_ID, LDE_REPC_OFFSET, reg16) ;
1363

    
1364
    _dwt_configlde(prfIndex);
1365

    
1366
    // Configure PLL2/RF PLL block CFG/TUNE (for a given channel)
1367
    dwt_write32bitoffsetreg(FS_CTRL_ID, FS_PLLCFG_OFFSET, fs_pll_cfg[chan_idx[chan]]);
1368
    dwt_write8bitoffsetreg(FS_CTRL_ID, FS_PLLTUNE_OFFSET, fs_pll_tune[chan_idx[chan]]);
1369

    
1370
    // Configure RF RX blocks (for specified channel/bandwidth)
1371
    dwt_write8bitoffsetreg(RF_CONF_ID, RF_RXCTRLH_OFFSET, rx_config[bw]);
1372

    
1373
    // Configure RF TX blocks (for specified channel and PRF)
1374
    // Configure RF TX control
1375
    dwt_write32bitoffsetreg(RF_CONF_ID, RF_TXCTRL_OFFSET, tx_config[chan_idx[chan]]);
1376

    
1377
    // Configure the baseband parameters (for specified PRF, bit rate, PAC, and SFD settings)
1378
    // DTUNE0
1379
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE0b_OFFSET, sftsh[config->dataRate][config->nsSFD]);
1380

    
1381
    // DTUNE1
1382
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1a_OFFSET, dtune1[prfIndex]);
1383

    
1384
    if(config->dataRate == DWT_BR_110K)
1385
    {
1386
        dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_110K);
1387
    }
1388
    else
1389
    {
1390
        if(config->txPreambLength == DWT_PLEN_64)
1391
        {
1392
            dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_6M8_PRE64);
1393
            dwt_write8bitoffsetreg(DRX_CONF_ID, DRX_TUNE4H_OFFSET, DRX_TUNE4H_PRE64);
1394
        }
1395
        else
1396
        {
1397
            dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_850K_6M8);
1398
            dwt_write8bitoffsetreg(DRX_CONF_ID, DRX_TUNE4H_OFFSET, DRX_TUNE4H_PRE128PLUS);
1399
        }
1400
    }
1401

    
1402
    // DTUNE2
1403
    dwt_write32bitoffsetreg(DRX_CONF_ID, DRX_TUNE2_OFFSET, digital_bb_config[prfIndex][config->rxPAC]);
1404

    
1405
    // DTUNE3 (SFD timeout)
1406
    // Don't allow 0 - SFD timeout will always be enabled
1407
    if(config->sfdTO == 0)
1408
    {
1409
        config->sfdTO = DWT_SFDTOC_DEF;
1410
    }
1411
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_SFDTOC_OFFSET, config->sfdTO);
1412

    
1413
    // Configure AGC parameters
1414
    dwt_write32bitoffsetreg( AGC_CFG_STS_ID, 0xC, agc_config.lo32);
1415
    dwt_write16bitoffsetreg( AGC_CFG_STS_ID, 0x4, agc_config.target[prfIndex]);
1416

    
1417
    // Set (non-standard) user SFD for improved performance,
1418
    if(config->nsSFD)
1419
    {
1420
        // Write non standard (DW) SFD length
1421
        dwt_write8bitoffsetreg(USR_SFD_ID, 0x00, dwnsSFDlen[config->dataRate]);
1422
        nsSfd_result = 3 ;
1423
        useDWnsSFD = 1 ;
1424
    }
1425
    regval =  (CHAN_CTRL_TX_CHAN_MASK & (chan << CHAN_CTRL_TX_CHAN_SHIFT)) | // Transmit Channel
1426
              (CHAN_CTRL_RX_CHAN_MASK & (chan << CHAN_CTRL_RX_CHAN_SHIFT)) | // Receive Channel
1427
              (CHAN_CTRL_RXFPRF_MASK & (config->prf << CHAN_CTRL_RXFPRF_SHIFT)) | // RX PRF
1428
              ((CHAN_CTRL_TNSSFD|CHAN_CTRL_RNSSFD) & (nsSfd_result << CHAN_CTRL_TNSSFD_SHIFT)) | // nsSFD enable RX&TX
1429
              (CHAN_CTRL_DWSFD & (useDWnsSFD << CHAN_CTRL_DWSFD_SHIFT)) | // Use DW nsSFD
1430
              (CHAN_CTRL_TX_PCOD_MASK & (config->txCode << CHAN_CTRL_TX_PCOD_SHIFT)) | // TX Preamble Code
1431
              (CHAN_CTRL_RX_PCOD_MASK & (config->rxCode << CHAN_CTRL_RX_PCOD_SHIFT)) ; // RX Preamble Code
1432

    
1433
    dwt_write32bitreg(CHAN_CTRL_ID,regval) ;
1434

    
1435
    // Set up TX Preamble Size, PRF and Data Rate
1436
    pdw1000local->txFCTRL = ((config->txPreambLength | config->prf) << TX_FCTRL_TXPRF_SHFT) | (config->dataRate << TX_FCTRL_TXBR_SHFT);
1437
    dwt_write32bitreg(TX_FCTRL_ID, pdw1000local->txFCTRL);
1438

    
1439
    // The SFD transmit pattern is initialised by the DW1000 upon a user TX request, but (due to an IC issue) it is not done for an auto-ACK TX. The
1440
    // SYS_CTRL write below works around this issue, by simultaneously initiating and aborting a transmission, which correctly initialises the SFD
1441
    // after its configuration or reconfiguration.
1442
    // This issue is not documented at the time of writing this code. It should be in next release of DW1000 User Manual (v2.09, from July 2016).
1443
    dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, SYS_CTRL_TXSTRT | SYS_CTRL_TRXOFF); // Request TX start and TRX off at the same time
1444
} // end dwt_configure()
1445

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

    
1465
/*! ------------------------------------------------------------------------------------------------------------------
1466
 * @fn dwt_settxantennadelay()
1467
 *
1468
 * @brief This API function writes the antenna delay (in time units) to TX registers
1469
 *
1470
 * input parameters:
1471
 * @param txDelay - this is the total (TX) antenna delay value, which
1472
 *                          will be programmed into the TX delay register
1473
 *
1474
 * output parameters
1475
 *
1476
 * no return value
1477
 */
1478
void dwt_settxantennadelay(uint16_t txDelay)
1479
{
1480
    // Set the TX antenna delay for auto TX timestamp adjustment
1481
    dwt_write16bitoffsetreg(TX_ANTD_ID, TX_ANTD_OFFSET, txDelay);
1482
}
1483

    
1484
/*! ------------------------------------------------------------------------------------------------------------------
1485
 * @fn dwt_writetxdata()
1486
 *
1487
 * @brief This API function writes the supplied TX data into the DW1000's
1488
 * TX buffer.  The input parameters are the data length in bytes and a pointer
1489
 * to those data bytes.
1490
 *
1491
 * input parameters
1492
 * @param txFrameLength  - This is the total frame length, including the two byte CRC.
1493
 *                         Note: this is the length of TX message (including the 2 byte CRC) - max is 1023
1494
 *                         standard PHR mode allows up to 127 bytes
1495
 *                         if > 127 is programmed, DWT_PHRMODE_EXT needs to be set in the phrMode configuration
1496
 *                         see dwt_configure function
1497
 * @param txFrameBytes   - Pointer to the user’s buffer containing the data to send.
1498
 * @param txBufferOffset - This specifies an offset in the DW1000’s TX Buffer at which to start writing data.
1499
 *
1500
 * output parameters
1501
 *
1502
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
1503
 */
1504
int dwt_writetxdata(uint16_t txFrameLength, uint8_t *txFrameBytes, uint16_t txBufferOffset)
1505
{
1506
#ifdef DWT_API_ERROR_CHECK
1507
    assert(txFrameLength >= 2);
1508
    assert((pdw1000local->longFrames && (txFrameLength <= 1023)) || (txFrameLength <= 127));
1509
    assert((txBufferOffset + txFrameLength) <= 1024);
1510
#endif
1511

    
1512
    if ((txBufferOffset + txFrameLength) <= 1024)
1513
    {
1514
        // Write the data to the IC TX buffer, (-2 bytes for auto generated CRC)
1515
        dwt_writetodevice( TX_BUFFER_ID, txBufferOffset, txFrameLength-2, txFrameBytes);
1516
        return DWT_SUCCESS;
1517
    }
1518
    else
1519
    {
1520
        return DWT_ERROR;
1521
    }
1522
} // end dwt_writetxdata()
1523

    
1524
/*! ------------------------------------------------------------------------------------------------------------------
1525
 * @fn dwt_writetxfctrl()
1526
 *
1527
 * @brief This API function configures the TX frame control register before the transmission of a frame
1528
 *
1529
 * input parameters:
1530
 * @param txFrameLength - this is the length of TX message (including the 2 byte CRC) - max is 1023
1531
 *                              NOTE: standard PHR mode allows up to 127 bytes
1532
 *                              if > 127 is programmed, DWT_PHRMODE_EXT needs to be set in the phrMode configuration
1533
 *                              see dwt_configure function
1534
 * @param txBufferOffset - the offset in the tx buffer to start writing the data
1535
 * @param ranging - 1 if this is a ranging frame, else 0
1536
 *
1537
 * output parameters
1538
 *
1539
 * no return value
1540
 */
1541
void dwt_writetxfctrl(uint16_t txFrameLength, uint16_t txBufferOffset, int ranging)
1542
{
1543

    
1544
#ifdef DWT_API_ERROR_CHECK
1545
    assert((pdw1000local->longFrames && (txFrameLength <= 1023)) || (txFrameLength <= 127));
1546
#endif
1547

    
1548
    // Write the frame length to the TX frame control register
1549
    // pdw1000local->txFCTRL has kept configured bit rate information
1550
    uint32_t reg32 = pdw1000local->txFCTRL | txFrameLength | (txBufferOffset << TX_FCTRL_TXBOFFS_SHFT) | (ranging << TX_FCTRL_TR_SHFT);
1551
    dwt_write32bitreg(TX_FCTRL_ID, reg32);
1552
} // end dwt_writetxfctrl()
1553

    
1554

    
1555
/*! ------------------------------------------------------------------------------------------------------------------
1556
 * @fn dwt_readrxdata()
1557
 *
1558
 * @brief This is used to read the data from the RX buffer, from an offset location give by offset parameter
1559
 *
1560
 * input parameters
1561
 * @param buffer - the buffer into which the data will be read
1562
 * @param length - the length of data to read (in bytes)
1563
 * @param rxBufferOffset - the offset in the rx buffer from which to read the data
1564
 *
1565
 * output parameters
1566
 *
1567
 * no return value
1568
 */
1569
void dwt_readrxdata(uint8_t *buffer, uint16_t length, uint16_t rxBufferOffset)
1570
{
1571
    dwt_readfromdevice(RX_BUFFER_ID,rxBufferOffset,length,buffer) ;
1572
}
1573

    
1574
/*! ------------------------------------------------------------------------------------------------------------------
1575
 * @fn dwt_readaccdata()
1576
 *
1577
 * @brief This is used to read the data from the Accumulator buffer, from an offset location give by offset parameter
1578
 *
1579
 * NOTE: Because of an internal memory access delay when reading the accumulator the first octet output is a dummy octet
1580
 *       that should be discarded. This is true no matter what sub-index the read begins at.
1581
 *
1582
 * input parameters
1583
 * @param buffer - the buffer into which the data will be read
1584
 * @param length - the length of data to read (in bytes)
1585
 * @param accOffset - the offset in the acc buffer from which to read the data
1586
 *
1587
 * output parameters
1588
 *
1589
 * no return value
1590
 */
1591
void dwt_readaccdata(uint8_t *buffer, uint16_t len, uint16_t accOffset)
1592
{
1593
    // Force on the ACC clocks if we are sequenced
1594
    _dwt_enableclocks(READ_ACC_ON);
1595

    
1596
    dwt_readfromdevice(ACC_MEM_ID,accOffset,len,buffer) ;
1597

    
1598
    _dwt_enableclocks(READ_ACC_OFF); // Revert clocks back
1599
}
1600

    
1601
/*! ------------------------------------------------------------------------------------------------------------------
1602
 * @fn dwt_readdiagnostics()
1603
 *
1604
 * @brief this function reads the RX signal quality diagnostic data
1605
 *
1606
 * input parameters
1607
 * @param diagnostics - diagnostic structure pointer, this will contain the diagnostic data read from the DW1000
1608
 *
1609
 * output parameters
1610
 *
1611
 * no return value
1612
 */
1613
void dwt_readdiagnostics(dwt_rxdiag_t *diagnostics)
1614
{
1615
    // Read the HW FP index
1616
    diagnostics->firstPath = dwt_read16bitoffsetreg(RX_TIME_ID, RX_TIME_FP_INDEX_OFFSET);
1617

    
1618
    // LDE diagnostic data
1619
    diagnostics->maxNoise = dwt_read16bitoffsetreg(LDE_IF_ID, LDE_THRESH_OFFSET);
1620

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

    
1624
    diagnostics->firstPathAmp1 = dwt_read16bitoffsetreg(RX_TIME_ID, RX_TIME_FP_AMPL1_OFFSET);
1625

    
1626
    diagnostics->rxPreamCount = (dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXPACC_MASK) >> RX_FINFO_RXPACC_SHIFT  ;
1627
}
1628

    
1629
/*! ------------------------------------------------------------------------------------------------------------------
1630
 * @fn dwt_readtxtimestamp()
1631
 *
1632
 * @brief This is used to read the TX timestamp (adjusted with the programmed antenna delay)
1633
 *
1634
 * input parameters
1635
 * @param timestamp - a pointer to a 5-byte buffer which will store the read TX timestamp time
1636
 *
1637
 * output parameters - the timestamp buffer will contain the value after the function call
1638
 *
1639
 * no return value
1640
 */
1641
void dwt_readtxtimestamp(uint8_t * timestamp)
1642
{
1643
    dwt_readfromdevice(TX_TIME_ID, TX_TIME_TX_STAMP_OFFSET, TX_TIME_TX_STAMP_LEN, timestamp) ; // Read bytes directly into buffer
1644
}
1645

    
1646
/*! ------------------------------------------------------------------------------------------------------------------
1647
 * @fn dwt_readtxtimestamphi32()
1648
 *
1649
 * @brief This is used to read the high 32-bits of the TX timestamp (adjusted with the programmed antenna delay)
1650
 *
1651
 * input parameters
1652
 *
1653
 * output parameters
1654
 *
1655
 * returns high 32-bits of TX timestamp
1656
 */
1657
uint32_t dwt_readtxtimestamphi32(void)
1658
{
1659
    return dwt_read32bitoffsetreg(TX_TIME_ID, 1); // Offset is 1 to get the 4 upper bytes out of 5
1660
}
1661

    
1662
/*! ------------------------------------------------------------------------------------------------------------------
1663
 * @fn dwt_readtxtimestamplo32()
1664
 *
1665
 * @brief This is used to read the low 32-bits of the TX timestamp (adjusted with the programmed antenna delay)
1666
 *
1667
 * input parameters
1668
 *
1669
 * output parameters
1670
 *
1671
 * returns low 32-bits of TX timestamp
1672
 */
1673
uint32_t dwt_readtxtimestamplo32(void)
1674
{
1675
    return dwt_read32bitreg(TX_TIME_ID); // Read TX TIME as a 32-bit register to get the 4 lower bytes out of 5
1676
}
1677

    
1678
/*! ------------------------------------------------------------------------------------------------------------------
1679
 * @fn dwt_readrxtimestamp()
1680
 *
1681
 * @brief This is used to read the RX timestamp (adjusted time of arrival)
1682
 *
1683
 * input parameters
1684
 * @param timestamp - a pointer to a 5-byte buffer which will store the read RX timestamp time
1685
 *
1686
 * output parameters - the timestamp buffer will contain the value after the function call
1687
 *
1688
 * no return value
1689
 */
1690
void dwt_readrxtimestamp(uint8_t * timestamp)
1691
{
1692
    dwt_readfromdevice(RX_TIME_ID, RX_TIME_RX_STAMP_OFFSET, RX_TIME_RX_STAMP_LEN, timestamp) ; // Get the adjusted time of arrival
1693
}
1694

    
1695
/*! ------------------------------------------------------------------------------------------------------------------
1696
 * @fn dwt_readrxtimestamphi32()
1697
 *
1698
 * @brief This is used to read the high 32-bits of the RX timestamp (adjusted with the programmed antenna delay)
1699
 *
1700
 * input parameters
1701
 *
1702
 * output parameters
1703
 *
1704
 * returns high 32-bits of RX timestamp
1705
 */
1706
uint32_t dwt_readrxtimestamphi32(void)
1707
{
1708
    return dwt_read32bitoffsetreg(RX_TIME_ID, 1); // Offset is 1 to get the 4 upper bytes out of 5
1709
}
1710

    
1711
/*! ------------------------------------------------------------------------------------------------------------------
1712
 * @fn dwt_readrxtimestamplo32()
1713
 *
1714
 * @brief This is used to read the low 32-bits of the RX timestamp (adjusted with the programmed antenna delay)
1715
 *
1716
 * input parameters
1717
 *
1718
 * output parameters
1719
 *
1720
 * returns low 32-bits of RX timestamp
1721
 */
1722
uint32_t dwt_readrxtimestamplo32(void)
1723
{
1724
    return dwt_read32bitreg(RX_TIME_ID); // Read RX TIME as a 32-bit register to get the 4 lower bytes out of 5
1725
}
1726

    
1727
/*! ------------------------------------------------------------------------------------------------------------------
1728
 * @fn dwt_readsystimestamphi32()
1729
 *
1730
 * @brief This is used to read the high 32-bits of the system time
1731
 *
1732
 * input parameters
1733
 *
1734
 * output parameters
1735
 *
1736
 * returns high 32-bits of system time timestamp
1737
 */
1738
uint32_t dwt_readsystimestamphi32(void)
1739
{
1740
    return dwt_read32bitoffsetreg(SYS_TIME_ID, 1); // Offset is 1 to get the 4 upper bytes out of 5
1741
}
1742

    
1743
/*! ------------------------------------------------------------------------------------------------------------------
1744
 * @fn dwt_readsystime()
1745
 *
1746
 * @brief This is used to read the system time
1747
 *
1748
 * input parameters
1749
 * @param timestamp - a pointer to a 5-byte buffer which will store the read system time
1750
 *
1751
 * output parameters
1752
 * @param timestamp - the timestamp buffer will contain the value after the function call
1753
 *
1754
 * no return value
1755
 */
1756
void dwt_readsystime(uint8_t * timestamp)
1757
{
1758
    dwt_readfromdevice(SYS_TIME_ID, SYS_TIME_OFFSET, SYS_TIME_LEN, timestamp) ;
1759
}
1760

    
1761
/*! ------------------------------------------------------------------------------------------------------------------
1762
 * @fn dwt_writetodevice()
1763
 *
1764
 * @brief  this function is used to write to the DW1000 device registers
1765
 * Notes:
1766
 *        1. Firstly we create a header (the first byte is a header byte)
1767
 *        a. check if sub index is used, if subindexing is used - set bit-6 to 1 to signify that the sub-index address follows the register index byte
1768
 *        b. set bit-7 (or with 0x80) for write operation
1769
 *        c. if extended sub address index is used (i.e. if index > 127) set bit-7 of the first sub-index byte following the first header byte
1770
 *
1771
 *        2. Write the header followed by the data bytes to the DW1000 device
1772
 *
1773
 *
1774
 * input parameters:
1775
 * @param recordNumber  - ID of register file or buffer being accessed
1776
 * @param index         - byte index into register file or buffer being accessed
1777
 * @param length        - number of bytes being written
1778
 * @param buffer        - pointer to buffer containing the 'length' bytes to be written
1779
 *
1780
 * output parameters
1781
 *
1782
 * no return value
1783
 */
1784
void dwt_writetodevice
1785
(
1786
    uint16_t      recordNumber,
1787
    uint16_t      index,
1788
    uint32_t      length,
1789
    const uint8_t *buffer
1790
)
1791
{
1792
    uint8_t header[3] ; // Buffer to compose header in
1793
    int   cnt = 0; // Counter for length of header
1794
#ifdef DWT_API_ERROR_CHECK
1795
    assert(recordNumber <= 0x3F); // Record number is limited to 6-bits.
1796
#endif
1797

    
1798
    // Write message header selecting WRITE operation and addresses as appropriate (this is one to three bytes long)
1799
    if (index == 0) // For index of 0, no sub-index is required
1800
    {
1801
        header[cnt++] = 0x80 | recordNumber ; // Bit-7 is WRITE operation, bit-6 zero=NO sub-addressing, bits 5-0 is reg file id