Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (150.79 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

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

    
35
#include <v1/alld_dw1000_regs_v1.h>
36

    
37
#include <aos_thread.h>
38
#include <assert.h>
39
#include <string.h>
40
#include <stdlib.h>
41
#include <math.h>
42

    
43

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

    
50
static int readfromspi(uint16_t headerLength,
51
                const uint8_t *headerBuffer,
52
                uint32_t readlength,
53
                uint8_t *readBuffer);
54

    
55

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

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

    
72

    
73
typedef struct {
74
    uint32_t lo32;
75
    uint16_t target[NUM_PRF];
76
} agc_cfg_struct ;
77

    
78
extern const agc_cfg_struct agc_config ;
79

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

    
83
extern const uint16_t dtune1[NUM_PRF];
84

    
85
#define XMLPARAMS_VERSION   (1.17f)
86

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

    
96
#define PEAK_MULTPLIER  (0x60) //3 -> (0x3 * 32) & 0x00E0
97
#define N_STD_FACTOR    (13)
98
#define LDE_PARAM1      (PEAK_MULTPLIER | N_STD_FACTOR)
99

    
100
#define LDE_PARAM3_16 (0x1607)
101
#define LDE_PARAM3_64 (0x0607)
102

    
103
#define MIXER_GAIN_STEP (0.5)
104
#define DA_ATTN_STEP    (2.5)
105

    
106
// #define DWT_API_ERROR_CHECK     // define so API checks config input parameters
107

    
108
//-----------------------------------------
109
// map the channel number to the index in the configuration arrays below
110
// 0th element is chan 1, 1st is chan 2, 2nd is chan 3, 3rd is chan 4, 4th is chan 5, 5th is chan 7
111
const uint8_t chan_idx[NUM_CH_SUPPORTED] = {0, 0, 1, 2, 3, 4, 0, 5};
112

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

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

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

    
146
//bandwidth configuration
147
const uint8_t rx_config[NUM_BW] =
148
{
149
    RF_RXCTRLH_NBW,
150
    RF_RXCTRLH_WBW
151
};
152

    
153

    
154
const agc_cfg_struct agc_config =
155
{
156
    AGC_TUNE2_VAL,
157
    { AGC_TUNE1_16M , AGC_TUNE1_64M }  //adc target
158
};
159

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

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

    
185
const uint16_t dtune1[NUM_PRF] =
186
{
187
    DRX_TUNE1a_PRF16,
188
    DRX_TUNE1a_PRF64
189
};
190

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

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

    
236
const double txpwr_compensation[NUM_CH] = {
237
    0.0,
238
    0.035,
239
    0.0,
240
    0.0,
241
    0.065,
242
    0.0
243
};
244

    
245

    
246
#define NUM_16M_OFFSET  (37)
247
#define NUM_16M_OFFSETWB  (68)
248
#define NUM_64M_OFFSET  (26)
249
#define NUM_64M_OFFSETWB  (59)
250

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

    
254
//---------------------------------------------------------------------------------------------------------------------------
255
// Range Bias Correction TABLES of range values in integer units of 25 CM, for 8-bit unsigned storage, MUST END IN 255 !!!!!!
256
//---------------------------------------------------------------------------------------------------------------------------
257

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

    
260
#define CM_OFFSET_16M_NB    (-23)   // for normal band channels at 16 MHz PRF
261
#define CM_OFFSET_16M_WB    (-28)   // for wider  band channels at 16 MHz PRF
262
#define CM_OFFSET_64M_NB    (-17)   // for normal band channels at 64 MHz PRF
263
#define CM_OFFSET_64M_WB    (-30)   // for wider  band channels at 64 MHz PRF
264

    
265

    
266
//---------------------------------------------------------------------------------------------------------------------------
267
// range25cm16PRFnb: Range Bias Correction table for narrow band channels at 16 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
268
//---------------------------------------------------------------------------------------------------------------------------
269

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

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

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

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

    
437

    
438
//---------------------------------------------------------------------------------------------------------------------------
439
// range25cm16PRFwb: Range Bias Correction table for wide band channels at 16 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
440
//---------------------------------------------------------------------------------------------------------------------------
441

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

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

    
589
//---------------------------------------------------------------------------------------------------------------------------
590
// range25cm64PRFnb: Range Bias Correction table for narrow band channels at 64 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
591
//---------------------------------------------------------------------------------------------------------------------------
592

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

    
625
    // ch 2 - range25cm64PRFnb
626
    {
627
           1,
628
           2,
629
           2,
630
           3,
631
           4,
632
           4,
633
           6,
634
           9,
635
          12,
636
          14,
637
          17,
638
          19,
639
          21,
640
          24,
641
          26,
642
          28,
643
          31,
644
          33,
645
          37,
646
          42,
647
          49,
648
          68,
649
          89,
650
         105,
651
         138,
652
         255
653
    },
654

    
655
    // ch 3 - range25cm64PRFnb
656
    {
657
           1,
658
           1,
659
           2,
660
           3,
661
           3,
662
           4,
663
           5,
664
           8,
665
          10,
666
          13,
667
          15,
668
          17,
669
          19,
670
          21,
671
          23,
672
          25,
673
          27,
674
          30,
675
          33,
676
          37,
677
          44,
678
          60,
679
          79,
680
          93,
681
         122,
682
         255
683
    },
684

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

    
716
//---------------------------------------------------------------------------------------------------------------------------
717
// range25cm64PRFwb: Range Bias Correction table for wide band channels at 64 MHz PRF, NB: !!!! each MUST END IN 255 !!!!
718
//---------------------------------------------------------------------------------------------------------------------------
719

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

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

    
849

    
850

    
851

    
852

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

    
874
    double mOffset ;                                // final offset result in metres
875

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

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

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

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

    
923

    
924
    mOffset = (float) cmoffseti ;                                       // offset result in centimmetres
925

    
926
    mOffset *= 0.01 ;                                                   // convert to metres
927

    
928
    return (mOffset) ;
929
}
930

    
931

    
932

    
933
// -------------------------------------------------------------------------------------------------------------------
934
//
935
// Internal functions for controlling and configuring the device
936
//
937
// -------------------------------------------------------------------------------------------------------------------
938

    
939
// Enable and Configure specified clocks
940
void _dwt_enableclocks(int clocks) ;
941
// Configure the ucode (FP algorithm) parameters
942
void _dwt_configlde(int prf);
943
// Load ucode from OTP/ROM
944
void _dwt_loaducodefromrom(void);
945
// Read non-volatile memory
946
uint32_t _dwt_otpread(uint32_t address);
947
// Program the non-volatile memory
948
uint32_t _dwt_otpprogword32(uint32_t data, uint16_t address);
949
// Upload the device configuration into always on memory
950
void _dwt_aonarrayupload(void);
951
// -------------------------------------------------------------------------------------------------------------------
952

    
953
/*!
954
 * Static data for DW1000 DecaWave Transceiver control
955
 */
956

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

    
960

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

    
981
    pdw1000local = &dw1000local[index];
982

    
983
    return DWT_SUCCESS ;
984
}
985

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

    
1016
int dwt_initialise(const uint16_t config, DW1000Driver* drv)
1017
//int dwt_initialise(const uint16_t config)  // TODO:
1018
{
1019
    uint16_t otp_addr = 0;
1020
    uint32_t ldo_tune = 0;
1021

    
1022
    pdw1000local->dblbuffon = 0; // Double buffer mode off by default
1023
    pdw1000local->wait4resp = 0;
1024
    pdw1000local->sleep_mode = 0;
1025

    
1026
    pdw1000local->cbTxDone = NULL;
1027
    pdw1000local->cbRxOk = NULL;
1028
    pdw1000local->cbRxTo = NULL;
1029
    pdw1000local->cbRxErr = NULL;
1030

    
1031
    pdw1000local->driver = drv;  // TODO:
1032

    
1033
    // Read and validate device ID return -1 if not recognised
1034
    if (DWT_DEVICE_ID != dwt_readdevid()) // MP IC ONLY (i.e. DW1000) FOR THIS CODE
1035
    {
1036
        return DWT_ERROR ;
1037
    }
1038

    
1039
    // Make sure the device is completely reset before starting initialisation
1040
    dwt_softreset();
1041

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

    
1044
    // Configure the CPLL lock detect
1045
    dwt_write8bitoffsetreg(EXT_SYNC_ID, EC_CTRL_OFFSET, EC_CTRL_PLLLCK);
1046

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

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

    
1060
    // Load Part and Lot ID from OTP
1061
    pdw1000local->partID = _dwt_otpread(PARTID_ADDRESS);
1062
    pdw1000local->lotID = _dwt_otpread(LOTID_ADDRESS);
1063

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

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

    
1086
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
1087

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

    
1091
    // Read system register / store local copy
1092
    pdw1000local->sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
1093

    
1094
    return DWT_SUCCESS ;
1095

    
1096
} // end dwt_initialise()
1097

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

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

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

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

    
1190
    buf[0] = command & 0xff;
1191
    buf[1] = (command >> 8) & 0xff;
1192
    buf[2] = (command >> 16) & 0xff;
1193

    
1194
    dwt_writetodevice(GPIO_CTRL_ID, GPIO_DIR_OFFSET, GPIO_DIR_LEN, buf);
1195
}
1196

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

    
1215
    buf[0] = command & 0xff;
1216
    buf[1] = (command >> 8) & 0xff;
1217
    buf[2] = (command >> 16) & 0xff;
1218

    
1219
    dwt_writetodevice(GPIO_CTRL_ID, GPIO_DOUT_OFFSET, GPIO_DOUT_LEN, buf);
1220
}
1221

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

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

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

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

    
1291
    // Configure RF TX PG_DELAY
1292
    dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGDELAY_OFFSET, config->PGdly);
1293

    
1294
    // Configure TX power
1295
    dwt_write32bitreg(TX_POWER_ID, config->power);
1296

    
1297
}
1298

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

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

    
1338
    // For 110 kbps we need a special setup
1339
    if(DWT_BR_110K == config->dataRate)
1340
    {
1341
        pdw1000local->sysCFGreg |= SYS_CFG_RXM110K ;
1342
        reg16 >>= 3; // lde_replicaCoeff must be divided by 8
1343
    }
1344
    else
1345
    {
1346
        pdw1000local->sysCFGreg &= (~SYS_CFG_RXM110K) ;
1347
    }
1348

    
1349
    pdw1000local->longFrames = config->phrMode ;
1350

    
1351
    pdw1000local->sysCFGreg &= ~SYS_CFG_PHR_MODE_11;
1352
    pdw1000local->sysCFGreg |= (SYS_CFG_PHR_MODE_11 & (config->phrMode << SYS_CFG_PHR_MODE_SHFT));
1353

    
1354
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
1355
    // Set the lde_replicaCoeff
1356
    dwt_write16bitoffsetreg(LDE_IF_ID, LDE_REPC_OFFSET, reg16) ;
1357

    
1358
    _dwt_configlde(prfIndex);
1359

    
1360
    // Configure PLL2/RF PLL block CFG/TUNE (for a given channel)
1361
    dwt_write32bitoffsetreg(FS_CTRL_ID, FS_PLLCFG_OFFSET, fs_pll_cfg[chan_idx[chan]]);
1362
    dwt_write8bitoffsetreg(FS_CTRL_ID, FS_PLLTUNE_OFFSET, fs_pll_tune[chan_idx[chan]]);
1363

    
1364
    // Configure RF RX blocks (for specified channel/bandwidth)
1365
    dwt_write8bitoffsetreg(RF_CONF_ID, RF_RXCTRLH_OFFSET, rx_config[bw]);
1366

    
1367
    // Configure RF TX blocks (for specified channel and PRF)
1368
    // Configure RF TX control
1369
    dwt_write32bitoffsetreg(RF_CONF_ID, RF_TXCTRL_OFFSET, tx_config[chan_idx[chan]]);
1370

    
1371
    // Configure the baseband parameters (for specified PRF, bit rate, PAC, and SFD settings)
1372
    // DTUNE0
1373
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE0b_OFFSET, sftsh[config->dataRate][config->nsSFD]);
1374

    
1375
    // DTUNE1
1376
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1a_OFFSET, dtune1[prfIndex]);
1377

    
1378
    if(config->dataRate == DWT_BR_110K)
1379
    {
1380
        dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_110K);
1381
    }
1382
    else
1383
    {
1384
        if(config->txPreambLength == DWT_PLEN_64)
1385
        {
1386
            dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_6M8_PRE64);
1387
            dwt_write8bitoffsetreg(DRX_CONF_ID, DRX_TUNE4H_OFFSET, DRX_TUNE4H_PRE64);
1388
        }
1389
        else
1390
        {
1391
            dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, DRX_TUNE1b_850K_6M8);
1392
            dwt_write8bitoffsetreg(DRX_CONF_ID, DRX_TUNE4H_OFFSET, DRX_TUNE4H_PRE128PLUS);
1393
        }
1394
    }
1395

    
1396
    // DTUNE2
1397
    dwt_write32bitoffsetreg(DRX_CONF_ID, DRX_TUNE2_OFFSET, digital_bb_config[prfIndex][config->rxPAC]);
1398

    
1399
    // DTUNE3 (SFD timeout)
1400
    // Don't allow 0 - SFD timeout will always be enabled
1401
    if(config->sfdTO == 0)
1402
    {
1403
        config->sfdTO = DWT_SFDTOC_DEF;
1404
    }
1405
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_SFDTOC_OFFSET, config->sfdTO);
1406

    
1407
    // Configure AGC parameters
1408
    dwt_write32bitoffsetreg( AGC_CFG_STS_ID, 0xC, agc_config.lo32);
1409
    dwt_write16bitoffsetreg( AGC_CFG_STS_ID, 0x4, agc_config.target[prfIndex]);
1410

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

    
1427
    dwt_write32bitreg(CHAN_CTRL_ID,regval) ;
1428

    
1429
    // Set up TX Preamble Size, PRF and Data Rate
1430
    pdw1000local->txFCTRL = ((config->txPreambLength | config->prf) << TX_FCTRL_TXPRF_SHFT) | (config->dataRate << TX_FCTRL_TXBR_SHFT);
1431
    dwt_write32bitreg(TX_FCTRL_ID, pdw1000local->txFCTRL);
1432

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

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

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

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

    
1506
    if ((txBufferOffset + txFrameLength) <= 1024)
1507
    {
1508
        // Write the data to the IC TX buffer, (-2 bytes for auto generated CRC)
1509
        dwt_writetodevice( TX_BUFFER_ID, txBufferOffset, txFrameLength-2, txFrameBytes);
1510
        return DWT_SUCCESS;
1511
    }
1512
    else
1513
    {
1514
        return DWT_ERROR;
1515
    }
1516
} // end dwt_writetxdata()
1517

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

    
1538
#ifdef DWT_API_ERROR_CHECK
1539
    assert((pdw1000local->longFrames && (txFrameLength <= 1023)) || (txFrameLength <= 127));
1540
#endif
1541

    
1542
    // Write the frame length to the TX frame control register
1543
    // pdw1000local->txFCTRL has kept configured bit rate information
1544
    uint32_t reg32 = pdw1000local->txFCTRL | txFrameLength | (txBufferOffset << TX_FCTRL_TXBOFFS_SHFT) | (ranging << TX_FCTRL_TR_SHFT);
1545
    dwt_write32bitreg(TX_FCTRL_ID, reg32);
1546
} // end dwt_writetxfctrl()
1547

    
1548

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

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

    
1590
    dwt_readfromdevice(ACC_MEM_ID,accOffset,len,buffer) ;
1591

    
1592
    _dwt_enableclocks(READ_ACC_OFF); // Revert clocks back
1593
}
1594

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

    
1612
    // LDE diagnostic data
1613
    diagnostics->maxNoise = dwt_read16bitoffsetreg(LDE_IF_ID, LDE_THRESH_OFFSET);
1614

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

    
1618
    diagnostics->firstPathAmp1 = dwt_read16bitoffsetreg(RX_TIME_ID, RX_TIME_FP_AMPL1_OFFSET);
1619

    
1620
    diagnostics->rxPreamCount = (dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXPACC_MASK) >> RX_FINFO_RXPACC_SHIFT  ;
1621
}
1622

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

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

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

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

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

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

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

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

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

    
1792
    // Write message header selecting WRITE operation and addresses as appropriate (this is one to three bytes long)
1793
    if (index == 0) // For index of 0, no sub-index is required
1794
    {
1795
        header[cnt++] = 0x80 | recordNumber ; // Bit-7 is WRITE operation, bit-6 zero=NO sub-addressing, bits 5-0 is reg file id
1796
    }
1797
    else
1798
    {
1799
#ifdef DWT_API_ERROR_CHECK
1800
        assert((index <= 0x7FFF) && ((index + length) <= 0x7FFF)); // Index and sub-addressable area are limited to 15-bits.
1801
#endif
1802
        header[cnt++] = 0xC0 | recordNumber ; // Bit-7 is WRITE operation, bit-6 one=sub-address follows, bits 5-0 is reg file id
1803

    
1804
        if (index <= 127) // For non-zero index < 127, just a single sub-index byte is required
1805
        {
1806
            header[cnt++] = (uint8_t)index ; // Bit-7 zero means no extension, bits 6-0 is index.
1807
        }
1808
        else
1809
        {
1810
            header[cnt++] = 0x80 | (uint8_t)(index) ; // Bit-7 one means extended index, bits 6-0 is low seven bits of index.
1811
            header[cnt++] =  (uint8_t) (index >> 7) ; // 8-bit value = high eight bits of index.
1812
        }
1813
    }
1814

    
1815
    // Write it to the SPI
1816
    writetospi(cnt,header,length,buffer);
1817
} // end dwt_writetodevice()
1818

    
1819
/*! ------------------------------------------------------------------------------------------------------------------
1820
 * @fn dwt_readfromdevice()
1821
 *
1822
 * @brief  this function is used to read from the DW1000 device registers
1823
 * Notes:
1824
 *        1. Firstly we create a header (the first byte is a header byte)
1825
 *        a. check if sub index is used, if subindexing is used - set bit-6 to 1 to signify that the sub-index address follows the register index byte
1826
 *        b. set bit-7 (or with 0x80) for write operation
1827
 *        c. if extended sub address index is used (i.e. if index > 127) set bit-7 of the first sub-index byte following the first header byte
1828
 *
1829
 *        2. Write the header followed by the data bytes to the DW1000 device
1830
 *        3. Store the read data in the input buffer
1831
 *
1832
 * input parameters:
1833
 * @param recordNumber  - ID of register file or buffer being accessed
1834
 * @param index         - byte index into register file or buffer being accessed
1835
 * @param length        - number of bytes being read
1836
 * @param buffer        - pointer to buffer in which to return the read data.
1837
 *
1838
 * output parameters
1839
 *
1840
 * no return value
1841
 */
1842
void dwt_readfromdevice
1843
(
1844
    uint16_t  recordNumber,
1845
    uint16_t  index,
1846
    uint32_t  length,
1847
    uint8_t   *buffer
1848
)
1849
{
1850
    uint8_t header[3] ; // Buffer to compose header in
1851
    int   cnt = 0; // Counter for length of header
1852
#ifdef DWT_API_ERROR_CHECK
1853
    assert(recordNumber <= 0x3F); // Record number is limited to 6-bits.
1854
#endif
1855

    
1856
    // Write message header selecting READ operation and addresses as appropriate (this is one to three bytes long)
1857
    if (index == 0) // For index of 0, no sub-index is required
1858
    {
1859
        header[cnt++] = (uint8_t) recordNumber ; // Bit-7 zero is READ operation, bit-6 zero=NO sub-addressing, bits 5-0 is reg file id
1860
    }
1861
    else
1862
    {
1863
#ifdef DWT_API_ERROR_CHECK
1864
        assert((index <= 0x7FFF) && ((index + length) <= 0x7FFF)); // Index and sub-addressable area are limited to 15-bits.
1865
#endif
1866
        header[cnt++] = (uint8_t)(0x40 | recordNumber) ; // Bit-7 zero is READ operation, bit-6 one=sub-address follows, bits 5-0 is reg file id
1867

    
1868
        if (index <= 127) // For non-zero index < 127, just a single sub-index byte is required
1869
        {
1870
            header[cnt++] = (uint8_t) index ; // Bit-7 zero means no extension, bits 6-0 is index.
1871
        }
1872
        else
1873
        {
1874
            header[cnt++] = 0x80 | (uint8_t)(index) ; // Bit-7 one means extended index, bits 6-0 is low seven bits of index.
1875
            header[cnt++] =  (uint8_t) (index >> 7) ; // 8-bit value = high eight bits of index.
1876
        }
1877
    }
1878

    
1879
    // Do the read from the SPI
1880
    readfromspi(cnt, header, length, buffer);
1881
} // end dwt_readfromdevice()
1882

    
1883

    
1884

    
1885
/*! ------------------------------------------------------------------------------------------------------------------
1886
 * @fn dwt_read32bitoffsetreg()
1887
 *
1888
 * @brief  this function is used to read 32-bit value from the DW1000 device registers
1889
 *
1890
 * input parameters:
1891
 * @param regFileID - ID of register file or buffer being accessed
1892
 * @param regOffset - the index into register file or buffer being accessed
1893
 *
1894
 * output parameters
1895
 *
1896
 * returns 32 bit register value
1897
 */
1898
uint32_t dwt_read32bitoffsetreg(int regFileID,int regOffset)
1899
{
1900
    uint32_t  regval = 0 ;
1901
    int     j ;
1902
    uint8_t   buffer[4] ;
1903

    
1904
    dwt_readfromdevice(regFileID,regOffset,4,buffer); // Read 4 bytes (32-bits) register into buffer
1905

    
1906
    for (j = 3 ; j >= 0 ; j --)
1907
    {
1908
        regval = (regval << 8) + buffer[j] ;
1909
    }
1910
    return regval ;
1911

    
1912
} // end dwt_read32bitoffsetreg()
1913

    
1914
/*! ------------------------------------------------------------------------------------------------------------------
1915
 * @fn dwt_read16bitoffsetreg()
1916
 *
1917
 * @brief  this function is used to read 16-bit value from the DW1000 device registers
1918
 *
1919
 * input parameters:
1920
 * @param regFileID - ID of register file or buffer being accessed
1921
 * @param regOffset - the index into register file or buffer being accessed
1922
 *
1923
 * output parameters
1924
 *
1925
 * returns 16 bit register value
1926
 */
1927
uint16_t dwt_read16bitoffsetreg(int regFileID,int regOffset)
1928
{
1929
    uint16_t  regval = 0 ;
1930
    uint8_t   buffer[2] ;
1931

    
1932
    dwt_readfromdevice(regFileID,regOffset,2,buffer); // Read 2 bytes (16-bits) register into buffer
1933

    
1934
    regval = (buffer[1] << 8) + buffer[0] ;
1935
    return regval ;
1936

    
1937
} // end dwt_read16bitoffsetreg()
1938

    
1939
/*! ------------------------------------------------------------------------------------------------------------------
1940
 * @fn dwt_read8bitoffsetreg()
1941
 *
1942
 * @brief  this function is used to read an 8-bit value from the DW1000 device registers
1943
 *
1944
 * input parameters:
1945
 * @param regFileID - ID of register file or buffer being accessed
1946
 * @param regOffset - the index into register file or buffer being accessed
1947
 *
1948
 * output parameters
1949
 *
1950
 * returns 8-bit register value
1951
 */
1952
uint8_t dwt_read8bitoffsetreg(int regFileID, int regOffset)
1953
{
1954
    uint8_t regval;
1955

    
1956
    dwt_readfromdevice(regFileID, regOffset, 1, &regval);
1957

    
1958
    return regval ;
1959
}
1960

    
1961
/*! ------------------------------------------------------------------------------------------------------------------
1962
 * @fn dwt_write8bitoffsetreg()
1963
 *
1964
 * @brief  this function is used to write an 8-bit value to the DW1000 device registers
1965
 *
1966
 * input parameters:
1967
 * @param regFileID - ID of register file or buffer being accessed
1968
 * @param regOffset - the index into register file or buffer being accessed
1969
 * @param regval    - the value to write
1970
 *
1971
 * output parameters
1972
 *
1973
 * no return value
1974
 */
1975
void dwt_write8bitoffsetreg(int regFileID, int regOffset, uint8_t regval)
1976
{
1977
    dwt_writetodevice(regFileID, regOffset, 1, &regval);
1978
}
1979

    
1980
/*! ------------------------------------------------------------------------------------------------------------------
1981
 * @fn dwt_write16bitoffsetreg()
1982
 *
1983
 * @brief  this function is used to write 16-bit value to the DW1000 device registers
1984
 *
1985
 * input parameters:
1986
 * @param regFileID - ID of register file or buffer being accessed
1987
 * @param regOffset - the index into register file or buffer being accessed
1988
 * @param regval    - the value to write
1989
 *
1990
 * output parameters
1991
 *
1992
 * no return value
1993
 */
1994
void dwt_write16bitoffsetreg(int regFileID,int regOffset,uint16_t regval)
1995
{
1996
    uint8_t   buffer[2] ;
1997

    
1998
    buffer[0] = regval & 0xFF;
1999
    buffer[1] = regval >> 8 ;
2000

    
2001
    dwt_writetodevice(regFileID,regOffset,2,buffer);
2002
} // end dwt_write16bitoffsetreg()
2003

    
2004
/*! ------------------------------------------------------------------------------------------------------------------
2005
 * @fn dwt_write32bitoffsetreg()
2006
 *
2007
 * @brief  this function is used to write 32-bit value to the DW1000 device registers
2008
 *
2009
 * input parameters:
2010
 * @param regFileID - ID of register file or buffer being accessed
2011
 * @param regOffset - the index into register file or buffer being accessed
2012
 * @param regval    - the value to write
2013
 *
2014
 * output parameters
2015
 *
2016
 * no return value
2017
 */
2018
void dwt_write32bitoffsetreg(int regFileID,int regOffset,uint32_t regval)
2019
{
2020
    int     j ;
2021
    uint8_t   buffer[4] ;
2022

    
2023
    for ( j = 0 ; j < 4 ; j++ )
2024
    {
2025
        buffer[j] = regval & 0xff ;
2026
        regval >>= 8 ;
2027
    }
2028

    
2029
    dwt_writetodevice(regFileID,regOffset,4,buffer);
2030
} // end dwt_write32bitoffsetreg()
2031

    
2032
/*! ------------------------------------------------------------------------------------------------------------------
2033
 * @fn dwt_enableframefilter()
2034
 *
2035
 * @brief This is used to enable the frame filtering - (the default option is to
2036
 * accept any data and ACK frames with correct destination address
2037
 *
2038
 * input parameters
2039
 * @param - bitmask - enables/disables the frame filtering options according to
2040
 *      DWT_FF_NOTYPE_EN        0x000   no frame types allowed
2041
 *      DWT_FF_COORD_EN         0x002   behave as coordinator (can receive frames with no destination address (PAN ID has to match))
2042
 *      DWT_FF_BEACON_EN        0x004   beacon frames allowed
2043
 *      DWT_FF_DATA_EN          0x008   data frames allowed
2044
 *      DWT_FF_ACK_EN           0x010   ack frames allowed
2045
 *      DWT_FF_MAC_EN           0x020   mac control frames allowed
2046
 *      DWT_FF_RSVD_EN          0x040   reserved frame types allowed
2047
 *
2048
 * output parameters
2049
 *
2050
 * no return value
2051
 */
2052
void dwt_enableframefilter(uint16_t enable)
2053
{
2054
    uint32_t sysconfig = SYS_CFG_MASK & dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
2055

    
2056
    if(enable)
2057
    {
2058
        // Enable frame filtering and configure frame types
2059
        sysconfig &= ~(SYS_CFG_FF_ALL_EN); // Clear all
2060
        sysconfig |= (enable & SYS_CFG_FF_ALL_EN) | SYS_CFG_FFE;
2061
    }
2062
    else
2063
    {
2064
        sysconfig &= ~(SYS_CFG_FFE);
2065
    }
2066

    
2067
    pdw1000local->sysCFGreg = sysconfig ;
2068
    dwt_write32bitreg(SYS_CFG_ID,sysconfig) ;
2069
}
2070

    
2071
/*! ------------------------------------------------------------------------------------------------------------------
2072
 * @fn dwt_setpanid()
2073
 *
2074
 * @brief This is used to set the PAN ID
2075
 *
2076
 * input parameters
2077
 * @param panID - this is the PAN ID
2078
 *
2079
 * output parameters
2080
 *
2081
 * no return value
2082
 */
2083
void dwt_setpanid(uint16_t panID)
2084
{
2085
    // PAN ID is high 16 bits of register
2086
    dwt_write16bitoffsetreg(PANADR_ID, PANADR_PAN_ID_OFFSET, panID);
2087
}
2088

    
2089
/*! ------------------------------------------------------------------------------------------------------------------
2090
 * @fn dwt_setaddress16()
2091
 *
2092
 * @brief This is used to set 16-bit (short) address
2093
 *
2094
 * input parameters
2095
 * @param shortAddress - this sets the 16 bit short address
2096
 *
2097
 * output parameters
2098
 *
2099
 * no return value
2100
 */
2101
void dwt_setaddress16(uint16_t shortAddress)
2102
{
2103
    // Short address into low 16 bits
2104
    dwt_write16bitoffsetreg(PANADR_ID, PANADR_SHORT_ADDR_OFFSET, shortAddress);
2105
}
2106

    
2107
/*! ------------------------------------------------------------------------------------------------------------------
2108
 * @fn dwt_seteui()
2109
 *
2110
 * @brief This is used to set the EUI 64-bit (long) address
2111
 *
2112
 * input parameters
2113
 * @param eui64 - this is the pointer to a buffer that contains the 64bit address
2114
 *
2115
 * output parameters
2116
 *
2117
 * no return value
2118
 */
2119
void dwt_seteui(uint8_t *eui64)
2120
{
2121
    dwt_writetodevice(EUI_64_ID, EUI_64_OFFSET, EUI_64_LEN, eui64);
2122
}
2123

    
2124
/*! ------------------------------------------------------------------------------------------------------------------
2125
 * @fn dwt_geteui()
2126
 *
2127
 * @brief This is used to get the EUI 64-bit from the DW1000
2128
 *
2129
 * input parameters
2130
 * @param eui64 - this is the pointer to a buffer that will contain the read 64-bit EUI value
2131
 *
2132
 * output parameters
2133
 *
2134
 * no return value
2135
 */
2136
void dwt_geteui(uint8_t *eui64)
2137
{
2138
    dwt_readfromdevice(EUI_64_ID, EUI_64_OFFSET, EUI_64_LEN, eui64);
2139
}
2140

    
2141
/*! ------------------------------------------------------------------------------------------------------------------
2142
 * @fn dwt_otpread()
2143
 *
2144
 * @brief This is used to read the OTP data from given address into provided array
2145
 *
2146
 * input parameters
2147
 * @param address - this is the OTP address to read from
2148
 * @param array - this is the pointer to the array into which to read the data
2149
 * @param length - this is the number of 32 bit words to read (array needs to be at least this length)
2150
 *
2151
 * output parameters
2152
 *
2153
 * no return value
2154
 */
2155
void dwt_otpread(uint32_t address, uint32_t *array, uint8_t length)
2156
{
2157
    int i;
2158

    
2159
    _dwt_enableclocks(FORCE_SYS_XTI); // NOTE: Set system clock to XTAL - this is necessary to make sure the values read by _dwt_otpread are reliable
2160

    
2161
    for(i=0; i<length; i++)
2162
    {
2163
        array[i] = _dwt_otpread(address + i) ;
2164
    }
2165

    
2166
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Restore system clock to PLL
2167

    
2168
    return ;
2169
}
2170

    
2171
/*! ------------------------------------------------------------------------------------------------------------------
2172
 * @fn _dwt_otpread()
2173
 *
2174
 * @brief function to read the OTP memory. Ensure that MR,MRa,MRb are reset to 0.
2175
 *
2176
 * input parameters
2177
 * @param address - address to read at
2178
 *
2179
 * output parameters
2180
 *
2181
 * returns the 32bit of read data
2182
 */
2183
uint32_t _dwt_otpread(uint32_t address)
2184
{
2185
    uint32_t ret_data;
2186

    
2187
    // Write the address
2188
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_ADDR, address);
2189

    
2190
    // Perform OTP Read - Manual read mode has to be set
2191
    dwt_write8bitoffsetreg(OTP_IF_ID, OTP_CTRL, OTP_CTRL_OTPREAD | OTP_CTRL_OTPRDEN);
2192
    dwt_write8bitoffsetreg(OTP_IF_ID, OTP_CTRL, 0x00); // OTPREAD is self clearing but OTPRDEN is not
2193

    
2194
    // Read read data, available 40ns after rising edge of OTP_READ
2195
    ret_data = dwt_read32bitoffsetreg(OTP_IF_ID, OTP_RDAT);
2196

    
2197
    // Return the 32bit of read data
2198
    return ret_data;
2199
}
2200

    
2201
/*! ------------------------------------------------------------------------------------------------------------------
2202
 * @fn _dwt_otpsetmrregs()
2203
 *
2204
 * @brief Configure the MR registers for initial programming (enable charge pump).
2205
 * Read margin is used to stress the read back from the
2206
 * programmed bit. In normal operation this is relaxed.
2207
 *
2208
 * input parameters
2209
 * @param mode - "0" : Reset all to 0x0:           MRA=0x0000, MRB=0x0000, MR=0x0000
2210
 *               "1" : Set for inital programming: MRA=0x9220, MRB=0x000E, MR=0x1024
2211
 *               "2" : Set for soak programming:   MRA=0x9220, MRB=0x0003, MR=0x1824
2212
 *               "3" : High Vpp:                   MRA=0x9220, MRB=0x004E, MR=0x1824
2213
 *               "4" : Low Read Margin:            MRA=0x0000, MRB=0x0003, MR=0x0000
2214
 *               "5" : Array Clean:                MRA=0x0049, MRB=0x0003, MR=0x0024
2215
 *               "4" : Very Low Read Margin:       MRA=0x0000, MRB=0x0003, MR=0x0000
2216
 *
2217
 * output parameters
2218
 *
2219
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2220
 */
2221
uint32_t _dwt_otpsetmrregs(int mode)
2222
{
2223
    uint8_t rd_buf[4];
2224
    uint8_t wr_buf[4];
2225
    uint32_t mra=0,mrb=0,mr=0;
2226

    
2227
    // PROGRAMME MRA
2228
    // Set MRA, MODE_SEL
2229
    wr_buf[0] = 0x03;
2230
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL+1,1,wr_buf);
2231

    
2232
    // Load data
2233
    switch(mode&0x0f) {
2234
    case 0x0 :
2235
        mr =0x0000;
2236
        mra=0x0000;
2237
        mrb=0x0000;
2238
        break;
2239
    case 0x1 :
2240
        mr =0x1024;
2241
        mra=0x9220; // Enable CPP mon
2242
        mrb=0x000e;
2243
        break;
2244
    case 0x2 :
2245
        mr =0x1824;
2246
        mra=0x9220;
2247
        mrb=0x0003;
2248
        break;
2249
    case 0x3 :
2250
        mr =0x1824;
2251
        mra=0x9220;
2252
        mrb=0x004e;
2253
        break;
2254
    case 0x4 :
2255
        mr =0x0000;
2256
        mra=0x0000;
2257
        mrb=0x0003;
2258
        break;
2259
    case 0x5 :
2260
        mr =0x0024;
2261
        mra=0x0000;
2262
        mrb=0x0003;
2263
        break;
2264
    default :
2265
        return DWT_ERROR;
2266
    }
2267

    
2268
    wr_buf[0] = mra & 0x00ff;
2269
    wr_buf[1] = (mra & 0xff00)>>8;
2270
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2271

    
2272

    
2273
    // Set WRITE_MR
2274
    wr_buf[0] = 0x08;
2275
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2276

    
2277
    // Wait?
2278

    
2279
    // Set Clear Mode sel
2280
    wr_buf[0] = 0x02;
2281
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2282

    
2283
    // Set AUX update, write MR
2284
    wr_buf[0] = 0x88;
2285
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2286
    // Clear write MR
2287
    wr_buf[0] = 0x80;
2288
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2289
    // Clear AUX update
2290
    wr_buf[0] = 0x00;
2291
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2292

    
2293
    ///////////////////////////////////////////
2294
    // PROGRAM MRB
2295
    // Set SLOW, MRB, MODE_SEL
2296
    wr_buf[0] = 0x05;
2297
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2298

    
2299
    wr_buf[0] = mrb & 0x00ff;
2300
    wr_buf[1] = (mrb & 0xff00)>>8;
2301
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2302

    
2303
    // Set WRITE_MR
2304
    wr_buf[0] = 0x08;
2305
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2306

    
2307
    // Wait?
2308

    
2309
    // Set Clear Mode sel
2310
    wr_buf[0] = 0x04;
2311
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2312

    
2313
    // Set AUX update, write MR
2314
    wr_buf[0] = 0x88;
2315
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2316
    // Clear write MR
2317
    wr_buf[0] = 0x80;
2318
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2319
    // Clear AUX update
2320
    wr_buf[0] = 0x00;
2321
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2322

    
2323
    ///////////////////////////////////////////
2324
    // PROGRAM MR
2325
    // Set SLOW, MODE_SEL
2326
    wr_buf[0] = 0x01;
2327
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2328
    // Load data
2329

    
2330
    wr_buf[0] = mr & 0x00ff;
2331
    wr_buf[1] = (mr & 0xff00)>>8;
2332
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT,2,wr_buf);
2333

    
2334
    // Set WRITE_MR
2335
    wr_buf[0] = 0x08;
2336
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2337

    
2338
    // Wait?
2339
    deca_sleep(10);
2340
    // Set Clear Mode sel
2341
    wr_buf[0] = 0x00;
2342
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2343

    
2344
    // Read confirm mode writes.
2345
    // Set man override, MRA_SEL
2346
    wr_buf[0] = OTP_CTRL_OTPRDEN;
2347
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2348
    wr_buf[0] = 0x02;
2349
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2350
    // MRB_SEL
2351
    wr_buf[0] = 0x04;
2352
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2353
    deca_sleep(100);
2354

    
2355
    // Clear mode sel
2356
    wr_buf[0] = 0x00;
2357
    dwt_writetodevice(OTP_IF_ID,OTP_CTRL+1,1,wr_buf);
2358
    // Clear MAN_OVERRIDE
2359
    wr_buf[0] = 0x00;
2360
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL,1,wr_buf);
2361

    
2362
    deca_sleep(10);
2363

    
2364
    if (((mode&0x0f) == 0x1)||((mode&0x0f) == 0x2))
2365
    {
2366
        // Read status register
2367
        dwt_readfromdevice(OTP_IF_ID, OTP_STAT,1,rd_buf);
2368
    }
2369

    
2370
    return DWT_SUCCESS;
2371
}
2372

    
2373
/*! ------------------------------------------------------------------------------------------------------------------
2374
 * @fn _dwt_otpprogword32()
2375
 *
2376
 * @brief function to program the OTP memory. Ensure that MR,MRa,MRb are reset to 0.
2377
 * VNM Charge pump needs to be enabled (see _dwt_otpsetmrregs)
2378
 * Note the address is only 11 bits long.
2379
 *
2380
 * input parameters
2381
 * @param address - address to read at
2382
 *
2383
 * output parameters
2384
 *
2385
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2386
 */
2387
uint32_t _dwt_otpprogword32(uint32_t data, uint16_t address)
2388
{
2389
    uint8_t rd_buf[1];
2390
    uint8_t wr_buf[4];
2391
    uint8_t otp_done;
2392

    
2393
    // Read status register
2394
    dwt_readfromdevice(OTP_IF_ID, OTP_STAT, 1, rd_buf);
2395

    
2396
    if((rd_buf[0] & 0x02) != 0x02)
2397
    {
2398
        return DWT_ERROR;
2399
    }
2400

    
2401
    // Write the data
2402
    wr_buf[3] = (data>>24) & 0xff;
2403
    wr_buf[2] = (data>>16) & 0xff;
2404
    wr_buf[1] = (data>>8) & 0xff;
2405
    wr_buf[0] = data & 0xff;
2406
    dwt_writetodevice(OTP_IF_ID, OTP_WDAT, 4, wr_buf);
2407

    
2408
    // Write the address [10:0]
2409
    wr_buf[1] = (address>>8) & 0x07;
2410
    wr_buf[0] = address & 0xff;
2411
    dwt_writetodevice(OTP_IF_ID, OTP_ADDR, 2, wr_buf);
2412

    
2413
    // Enable Sequenced programming
2414
    wr_buf[0] = OTP_CTRL_OTPPROG;
2415
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL, 1, wr_buf);
2416
    wr_buf[0] = 0x00; // And clear
2417
    dwt_writetodevice(OTP_IF_ID, OTP_CTRL, 1, wr_buf);
2418

    
2419
    // WAIT for status to flag PRGM OK..
2420
    otp_done = 0;
2421
    while(otp_done == 0)
2422
    {
2423
        deca_sleep(1);
2424
        dwt_readfromdevice(OTP_IF_ID, OTP_STAT, 1, rd_buf);
2425

    
2426
        if((rd_buf[0] & 0x01) == 0x01)
2427
        {
2428
            otp_done = 1;
2429
        }
2430
    }
2431

    
2432
    return DWT_SUCCESS;
2433
}
2434

    
2435
/*! ------------------------------------------------------------------------------------------------------------------
2436
 * @fn dwt_otpwriteandverify()
2437
 *
2438
 * @brief This is used to program 32-bit value into the DW1000 OTP memory.
2439
 *
2440
 * input parameters
2441
 * @param value - this is the 32-bit value to be programmed into OTP
2442
 * @param address - this is the 16-bit OTP address into which the 32-bit value is programmed
2443
 *
2444
 * output parameters
2445
 *
2446
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2447
 */
2448
int dwt_otpwriteandverify(uint32_t value, uint16_t address)
2449
{
2450
    int prog_ok = DWT_SUCCESS;
2451
    int retry = 0;
2452
    // Firstly set the system clock to crystal
2453
    _dwt_enableclocks(FORCE_SYS_XTI); //set system clock to XTI
2454

    
2455
    //
2456
    //!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!
2457
    //Set the supply to 3.7V
2458
    //
2459

    
2460
    _dwt_otpsetmrregs(1); // Set mode for programming
2461

    
2462
    // For each value to program - the readback/check is done couple of times to verify it has programmed successfully
2463
    while(1)
2464
    {
2465
        _dwt_otpprogword32(value, address);
2466

    
2467
        if(_dwt_otpread(address) == value)
2468
        {
2469
            break;
2470
        }
2471
        retry++;
2472
        if(retry==5)
2473
        {
2474
            break;
2475
        }
2476
    }
2477

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

    
2480
    _dwt_otpsetmrregs(4); // Set mode for reading
2481

    
2482
    if(_dwt_otpread(address) != value) // If this does not pass please check voltage supply on VDDIO
2483
    {
2484
        prog_ok = DWT_ERROR;
2485
    }
2486

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

    
2489
    return prog_ok;
2490
}
2491

    
2492
/*! ------------------------------------------------------------------------------------------------------------------
2493
 * @fn _dwt_aonconfigupload()
2494
 *
2495
 * @brief This function uploads always on (AON) configuration, as set in the AON_CFG0_OFFSET register.
2496
 *
2497
 * input parameters
2498
 *
2499
 * output parameters
2500
 *
2501
 * no return value
2502
 */
2503
void _dwt_aonconfigupload(void)
2504
{
2505
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_UPL_CFG);
2506
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00); // Clear the register
2507
}
2508

    
2509
/*! ------------------------------------------------------------------------------------------------------------------
2510
 * @fn _dwt_aonarrayupload()
2511
 *
2512
 * @brief This function uploads always on (AON) data array and configuration. Thus if this function is used, then _dwt_aonconfigupload
2513
 * is not necessary. The DW1000 will go so SLEEP straight after this if the DWT_SLP_EN has been set.
2514
 *
2515
 * input parameters
2516
 *
2517
 * output parameters
2518
 *
2519
 * no return value
2520
 */
2521
void _dwt_aonarrayupload(void)
2522
{
2523
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00); // Clear the register
2524
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_SAVE);
2525
}
2526

    
2527
/*! ------------------------------------------------------------------------------------------------------------------
2528
 * @fn dwt_entersleep()
2529
 *
2530
 * @brief This function puts the device into deep sleep or sleep. dwt_configuresleep() should be called first
2531
 * to configure the sleep and on-wake/wake-up parameters
2532
 *
2533
 * input parameters
2534
 *
2535
 * output parameters
2536
 *
2537
 * no return value
2538
 */
2539
void dwt_entersleep(void)
2540
{
2541
    // Copy config to AON - upload the new configuration
2542
    _dwt_aonarrayupload();
2543
}
2544

    
2545
/*! ------------------------------------------------------------------------------------------------------------------
2546
 * @fn dwt_configuresleepcnt()
2547
 *
2548
 * @brief sets the sleep counter to new value, this function programs the high 16-bits of the 28-bit counter
2549
 *
2550
 * NOTE: this function needs to be run before dwt_configuresleep, also the SPI frequency has to be < 3MHz
2551
 *
2552
 * input parameters
2553
 * @param sleepcnt - this it value of the sleep counter to program
2554
 *
2555
 * output parameters
2556
 *
2557
 * no return value
2558
 */
2559
void dwt_configuresleepcnt(uint16_t sleepcnt)
2560
{
2561
    // Force system clock to crystal
2562
    _dwt_enableclocks(FORCE_SYS_XTI);
2563

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

    
2568
    // Disable the sleep counter
2569
    _dwt_aonconfigupload();
2570

    
2571
    // Set new value
2572
    dwt_write16bitoffsetreg(AON_ID, AON_CFG0_OFFSET + AON_CFG0_SLEEP_TIM_OFFSET, sleepcnt);
2573
    _dwt_aonconfigupload();
2574

    
2575
    // Enable the sleep counter
2576
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, AON_CFG1_SLEEP_CEN);
2577
    _dwt_aonconfigupload();
2578

    
2579
    // Put system PLL back on
2580
    _dwt_enableclocks(ENABLE_ALL_SEQ);
2581
}
2582

    
2583

    
2584
/*! ------------------------------------------------------------------------------------------------------------------
2585
 * @fn dwt_calibratesleepcnt()
2586
 *
2587
 * @brief calibrates the local oscillator as its frequency can vary between 7 and 13kHz depending on temp and voltage
2588
 *
2589
 * NOTE: this function needs to be run before dwt_configuresleepcnt, so that we know what the counter units are
2590
 *
2591
 * input parameters
2592
 *
2593
 * output parameters
2594
 *
2595
 * returns the number of XTAL/2 cycles per low-power oscillator cycle. LP OSC frequency = 19.2 MHz/return value
2596
 */
2597
uint16_t dwt_calibratesleepcnt(void)
2598
{
2599
    uint16_t result;
2600

    
2601
    // Enable calibration of the sleep counter
2602
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, AON_CFG1_LPOSC_CAL);
2603
    _dwt_aonconfigupload();
2604

    
2605
    // Disable calibration of the sleep counter
2606
    dwt_write8bitoffsetreg(AON_ID, AON_CFG1_OFFSET, 0x00);
2607
    _dwt_aonconfigupload();
2608

    
2609
    // Force system clock to crystal
2610
    _dwt_enableclocks(FORCE_SYS_XTI);
2611

    
2612
    deca_sleep(1);
2613

    
2614
    // Read the number of XTAL/2 cycles one LP oscillator cycle took.
2615
    // Set up address - Read upper byte first
2616
    dwt_write8bitoffsetreg(AON_ID, AON_ADDR_OFFSET, AON_ADDR_LPOSC_CAL_1);
2617

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

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

    
2624
    // Read back byte from AON
2625
    result = dwt_read8bitoffsetreg(AON_ID, AON_RDAT_OFFSET);
2626
    result <<= 8;
2627

    
2628
    // Set up address - Read lower byte
2629
    dwt_write8bitoffsetreg(AON_ID, AON_ADDR_OFFSET, AON_ADDR_LPOSC_CAL_0);
2630

    
2631
    // Enable manual override
2632
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB);
2633

    
2634
    // Read confirm data that was written
2635
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, AON_CTRL_DCA_ENAB | AON_CTRL_DCA_READ);
2636

    
2637
    // Read back byte from AON
2638
    result |= dwt_read8bitoffsetreg(AON_ID, AON_RDAT_OFFSET);
2639

    
2640
    // Disable manual override
2641
    dwt_write8bitoffsetreg(AON_ID, AON_CTRL_OFFSET, 0x00);
2642

    
2643
    // Put system PLL back on
2644
    _dwt_enableclocks(ENABLE_ALL_SEQ);
2645

    
2646
    // Returns the number of XTAL/2 cycles per one LP OSC cycle
2647
    // This can be converted into LP OSC frequency by 19.2 MHz/result
2648
    return result;
2649
}
2650

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

    
2690
    dwt_write8bitoffsetreg(AON_ID, AON_CFG0_OFFSET, wake);
2691
}
2692

    
2693
/*! ------------------------------------------------------------------------------------------------------------------
2694
 * @fn dwt_entersleepaftertx(int enable)
2695
 *
2696
 * @brief sets the auto TX to sleep bit. This means that after a frame
2697
 * transmission the device will enter deep sleep mode. The dwt_configuresleep() function
2698
 * needs to be called before this to configure the on-wake settings
2699
 *
2700
 * NOTE: the IRQ line has to be low/inactive (i.e. no pending events)
2701
 *
2702
 * input parameters
2703
 * @param enable - 1 to configure the device to enter deep sleep after TX, 0 - disables the configuration
2704
 *
2705
 * output parameters
2706
 *
2707
 * no return value
2708
 */
2709
void dwt_entersleepaftertx(int enable)
2710
{
2711
    uint32_t reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET);
2712
    // Set the auto TX -> sleep bit
2713
    if(enable)
2714
    {
2715
        reg |= PMSC_CTRL1_ATXSLP;
2716
    }
2717
    else
2718
    {
2719
        reg &= ~(PMSC_CTRL1_ATXSLP);
2720
    }
2721
    dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, reg);
2722
}
2723

    
2724

    
2725
/*! ------------------------------------------------------------------------------------------------------------------
2726
 * @fn dwt_spicswakeup()
2727
 *
2728
 * @brief wake up the device from sleep mode using the SPI read,
2729
 * the device will wake up on chip select line going low if the line is held low for at least 500us.
2730
 * To define the length depending on the time one wants to hold
2731
 * the chip select line low, use the following formula:
2732
 *
2733
 *      length (bytes) = time (s) * byte_rate (Hz)
2734
 *
2735
 * where fastest byte_rate is spi_rate (Hz) / 8 if the SPI is sending the bytes back-to-back.
2736
 * To save time and power, a system designer could determine byte_rate value more precisely.
2737
 *
2738
 * NOTE: Alternatively the device can be waken up with WAKE_UP pin if configured for that operation
2739
 *
2740
 * input parameters
2741
 * @param buff   - this is a pointer to the dummy buffer which will be used in the SPI read transaction used for the WAKE UP of the device
2742
 * @param length - this is the length of the dummy buffer
2743
 *
2744
 * output parameters
2745
 *
2746
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
2747
 */
2748
int dwt_spicswakeup(uint8_t *buff, uint16_t length)
2749
{
2750
    if(dwt_readdevid() != DWT_DEVICE_ID) // Device was in deep sleep (the first read fails)
2751
    {
2752
        // Need to keep chip select line low for at least 500us
2753
        dwt_readfromdevice(0x0, 0x0, length, buff); // Do a long read to wake up the chip (hold the chip select low)
2754

    
2755
        // Need 5ms for XTAL to start and stabilise (could wait for PLL lock IRQ status bit !!!)
2756
        // NOTE: Polling of the STATUS register is not possible unless frequency is < 3MHz
2757
        deca_sleep(5);
2758
    }
2759
    else
2760
    {
2761
        return DWT_SUCCESS;
2762
    }
2763
    // DEBUG - check if still in sleep mode
2764
    if(dwt_readdevid() != DWT_DEVICE_ID)
2765
    {
2766
        return DWT_ERROR;
2767
    }
2768

    
2769
    return DWT_SUCCESS;
2770
}
2771

    
2772
/*! ------------------------------------------------------------------------------------------------------------------
2773
 * @fn _dwt_configlde()
2774
 *
2775
 * @brief configure LDE algorithm parameters
2776
 *
2777
 * input parameters
2778
 * @param prf   -   this is the PRF index (0 or 1) 0 corresponds to 16 and 1 to 64 PRF
2779
 *
2780
 * output parameters
2781
 *
2782
 * no return value
2783
 */
2784
void _dwt_configlde(int prfIndex)
2785
{
2786
    dwt_write8bitoffsetreg(LDE_IF_ID, LDE_CFG1_OFFSET, LDE_PARAM1); // 8-bit configuration register
2787

    
2788
    if(prfIndex)
2789
    {
2790
        dwt_write16bitoffsetreg( LDE_IF_ID, LDE_CFG2_OFFSET, (uint16_t) LDE_PARAM3_64); // 16-bit LDE configuration tuning register
2791
    }
2792
    else
2793
    {
2794
        dwt_write16bitoffsetreg( LDE_IF_ID, LDE_CFG2_OFFSET, (uint16_t) LDE_PARAM3_16);
2795
    }
2796
}
2797

    
2798

    
2799
/*! ------------------------------------------------------------------------------------------------------------------
2800
 * @fn _dwt_loaducodefromrom()
2801
 *
2802
 * @brief  load ucode from OTP MEMORY or ROM
2803
 *
2804
 * input parameters
2805
 *
2806
 * output parameters
2807
 *
2808
 * no return value
2809
 */
2810
void _dwt_loaducodefromrom(void)
2811
{
2812
    // Set up clocks
2813
    _dwt_enableclocks(FORCE_LDE);
2814

    
2815
    // Kick off the LDE load
2816
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_CTRL, OTP_CTRL_LDELOAD); // Set load LDE kick bit
2817

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

    
2820
    // Default clocks (ENABLE_ALL_SEQ)
2821
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
2822
}
2823

    
2824
/*! ------------------------------------------------------------------------------------------------------------------
2825
 * @fn dwt_loadopsettabfromotp()
2826
 *
2827
 * @brief This is used to select which Operational Parameter Set table to load from OTP memory
2828
 *
2829
 * input parameters
2830
 * @param ops_sel - Operational Parameter Set table to load:
2831
 *                  DWT_OPSET_64LEN = 0x0 - load the operational parameter set table for 64 length preamble configuration
2832
 *                  DWT_OPSET_TIGHT = 0x1 - load the operational parameter set table for tight xtal offsets (<1ppm)
2833
 *                  DWT_OPSET_DEFLT = 0x2 - load the default operational parameter set table (this is loaded from reset)
2834
 *
2835
 * output parameters
2836
 *
2837
 * no return value
2838
 */
2839
void dwt_loadopsettabfromotp(uint8_t ops_sel)
2840
{
2841
    uint16_t reg = ((ops_sel << OTP_SF_OPS_SEL_SHFT) & OTP_SF_OPS_SEL_MASK) | OTP_SF_OPS_KICK; // Select defined OPS table and trigger its loading
2842

    
2843
    // Set up clocks
2844
    _dwt_enableclocks(FORCE_LDE);
2845

    
2846
    dwt_write16bitoffsetreg(OTP_IF_ID, OTP_SF, reg);
2847

    
2848
    // Default clocks (ENABLE_ALL_SEQ)
2849
    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
2850

    
2851
}
2852

    
2853
/*! ------------------------------------------------------------------------------------------------------------------
2854
 * @fn dwt_setsmarttxpower()
2855
 *
2856
 * @brief This call enables or disables the smart TX power feature.
2857
 *
2858
 * input parameters
2859
 * @param enable - this enables or disables the TX smart power (1 = enable, 0 = disable)
2860
 *
2861
 * output parameters
2862
 *
2863
 * no return value
2864
 */
2865
void dwt_setsmarttxpower(int enable)
2866
{
2867
    // Config system register
2868
    pdw1000local->sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register
2869

    
2870
    // Disable smart power configuration
2871
    if(enable)
2872
    {
2873
        pdw1000local->sysCFGreg &= ~(SYS_CFG_DIS_STXP) ;
2874
    }
2875
    else
2876
    {
2877
        pdw1000local->sysCFGreg |= SYS_CFG_DIS_STXP ;
2878
    }
2879

    
2880
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2881
}
2882

    
2883

    
2884
/*! ------------------------------------------------------------------------------------------------------------------
2885
 * @fn dwt_enableautoack()
2886
 *
2887
 * @brief This call enables the auto-ACK feature. If the responseDelayTime (parameter) is 0, the ACK will be sent a.s.a.p.
2888
 * otherwise it will be sent with a programmed delay (in symbols), max is 255.
2889
 * NOTE: needs to have frame filtering enabled as well
2890
 *
2891
 * input parameters
2892
 * @param responseDelayTime - if non-zero the ACK is sent after this delay, max is 255.
2893
 *
2894
 * output parameters
2895
 *
2896
 * no return value
2897
 */
2898
void dwt_enableautoack(uint8_t responseDelayTime)
2899
{
2900
    // Set auto ACK reply delay
2901
    dwt_write8bitoffsetreg(ACK_RESP_T_ID, ACK_RESP_T_ACK_TIM_OFFSET, responseDelayTime); // In symbols
2902
    // Enable auto ACK
2903
    pdw1000local->sysCFGreg |= SYS_CFG_AUTOACK;
2904
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2905
}
2906

    
2907
/*! ------------------------------------------------------------------------------------------------------------------
2908
 * @fn dwt_setdblrxbuffmode()
2909
 *
2910
 * @brief This call enables the double receive buffer mode
2911
 *
2912
 * input parameters
2913
 * @param enable - 1 to enable, 0 to disable the double buffer mode
2914
 *
2915
 * output parameters
2916
 *
2917
 * no return value
2918
 */
2919
void dwt_setdblrxbuffmode(int enable)
2920
{
2921
    if(enable)
2922
    {
2923
        // Enable double RX buffer mode
2924
        pdw1000local->sysCFGreg &= ~SYS_CFG_DIS_DRXB;
2925
        pdw1000local->dblbuffon = 1;
2926
    }
2927
    else
2928
    {
2929
        // Disable double RX buffer mode
2930
        pdw1000local->sysCFGreg |= SYS_CFG_DIS_DRXB;
2931
        pdw1000local->dblbuffon = 0;
2932
    }
2933

    
2934
    dwt_write32bitreg(SYS_CFG_ID,pdw1000local->sysCFGreg) ;
2935
}
2936

    
2937
/*! ------------------------------------------------------------------------------------------------------------------
2938
 * @fn dwt_setrxaftertxdelay()
2939
 *
2940
 * @brief This sets the receiver turn on delay time after a transmission of a frame
2941
 *
2942
 * input parameters
2943
 * @param rxDelayTime - (20 bits) - the delay is in UWB microseconds
2944
 *
2945
 * output parameters
2946
 *
2947
 * no return value
2948
 */
2949
void dwt_setrxaftertxdelay(uint32_t rxDelayTime)
2950
{
2951
    uint32_t val = dwt_read32bitreg(ACK_RESP_T_ID) ; // Read ACK_RESP_T_ID register
2952

    
2953
    val &= ~(ACK_RESP_T_W4R_TIM_MASK) ; // Clear the timer (19:0)
2954

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

    
2957
    dwt_write32bitreg(ACK_RESP_T_ID, val) ;
2958
}
2959

    
2960
/*! ------------------------------------------------------------------------------------------------------------------
2961
 * @fn dwt_setcallbacks()
2962
 *
2963
 * @brief This function is used to register the different callbacks called when one of the corresponding event occurs.
2964
 *
2965
 * NOTE: Callbacks can be undefined (set to NULL). In this case, dwt_isr() will process the event as usual but the 'null'
2966
 * callback will not be called.
2967
 *
2968
 * input parameters
2969
 * @param cbTxDone - the pointer to the TX confirmation event callback function
2970
 * @param cbRxOk - the pointer to the RX good frame event callback function
2971
 * @param cbRxTo - the pointer to the RX timeout events callback function
2972
 * @param cbRxErr - the pointer to the RX error events callback function
2973
 *
2974
 * output parameters
2975
 *
2976
 * no return value
2977
 */
2978
void dwt_setcallbacks(dwt_cb_t cbTxDone, dwt_cb_t cbRxOk, dwt_cb_t cbRxTo, dwt_cb_t cbRxErr)
2979
{
2980
    pdw1000local->cbTxDone = cbTxDone;
2981
    pdw1000local->cbRxOk = cbRxOk;
2982
    pdw1000local->cbRxTo = cbRxTo;
2983
    pdw1000local->cbRxErr = cbRxErr;
2984
}
2985

    
2986
/*! ------------------------------------------------------------------------------------------------------------------
2987
 * @fn dwt_checkirq()
2988
 *
2989
 * @brief This function checks if the IRQ line is active - this is used instead of interrupt handler
2990
 *
2991
 * input parameters
2992
 *
2993
 * output parameters
2994
 *
2995
 * return value is 1 if the IRQS bit is set and 0 otherwise
2996
 */
2997
uint8_t dwt_checkirq(void)
2998
{
2999
    return (dwt_read8bitoffsetreg(SYS_STATUS_ID, SYS_STATUS_OFFSET) & SYS_STATUS_IRQS); // Reading the lower byte only is enough for this operation
3000
}
3001

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

3020
 * input parameters
3021
 *
3022
 * output parameters
3023
 *
3024
 * no return value
3025
 */
3026
void dwt_isr(void)
3027
{
3028
    uint32_t status = pdw1000local->cbData.status = dwt_read32bitreg(SYS_STATUS_ID); // Read status register low 32bits
3029

    
3030
    // Handle RX good frame event
3031
    if(status & SYS_STATUS_RXFCG)
3032
    {
3033
        uint16_t finfo16;
3034
        uint16_t len;
3035

    
3036
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_GOOD); // Clear all receive status bits
3037

    
3038
        pdw1000local->cbData.rx_flags = 0;
3039

    
3040
        // Read frame info - Only the first two bytes of the register are used here.
3041
        finfo16 = dwt_read16bitoffsetreg(RX_FINFO_ID, RX_FINFO_OFFSET);
3042

    
3043
        // Report frame length - Standard frame length up to 127, extended frame length up to 1023 bytes
3044
        len = finfo16 & RX_FINFO_RXFL_MASK_1023;
3045
        if(pdw1000local->longFrames == 0)
3046
        {
3047
            len &= RX_FINFO_RXFLEN_MASK;
3048
        }
3049
        pdw1000local->cbData.datalength = len;
3050

    
3051
        // Report ranging bit
3052
        if(finfo16 & RX_FINFO_RNG)
3053
        {
3054
            pdw1000local->cbData.rx_flags |= DWT_CB_DATA_RX_FLAG_RNG;
3055
        }
3056

    
3057
        // Report frame control - First bytes of the received frame.
3058
        dwt_readfromdevice(RX_BUFFER_ID, 0, FCTRL_LEN_MAX, pdw1000local->cbData.fctrl);
3059

    
3060
        // Because of a previous frame not being received properly, AAT bit can be set upon the proper reception of a frame not requesting for
3061
        // acknowledgement (ACK frame is not actually sent though). If the AAT bit is set, check ACK request bit in frame control to confirm (this
3062
        // implementation works only for IEEE802.15.4-2011 compliant frames).
3063
        // This issue is not documented at the time of writing this code. It should be in next release of DW1000 User Manual (v2.09, from July 2016).
3064
        if((status & SYS_STATUS_AAT) && ((pdw1000local->cbData.fctrl[0] & FCTRL_ACK_REQ_MASK) == 0))
3065
        {
3066
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_AAT); // Clear AAT status bit in register
3067
            pdw1000local->cbData.status &= ~SYS_STATUS_AAT; // Clear AAT status bit in callback data register copy
3068
            pdw1000local->wait4resp = 0;
3069
        }
3070

    
3071
        // Call the corresponding callback if present
3072
        if(pdw1000local->cbRxOk != NULL)
3073
        {
3074
            pdw1000local->cbRxOk(&pdw1000local->cbData);
3075
        }
3076

    
3077
        if (pdw1000local->dblbuffon)
3078
        {
3079
            // Toggle the Host side Receive Buffer Pointer
3080
            dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_HRBT_OFFSET, 1);
3081
        }
3082
    }
3083

    
3084
    // Handle TX confirmation event
3085
    if(status & SYS_STATUS_TXFRS)
3086
    {
3087
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_TX); // Clear TX event bits
3088

    
3089
        // In the case where this TXFRS interrupt is due to the automatic transmission of an ACK solicited by a response (with ACK request bit set)
3090
        // that we receive through using wait4resp to a previous TX (and assuming that the IRQ processing of that TX has already been handled), then
3091
        // we need to handle the IC issue which turns on the RX again in this situation (i.e. because it is wrongly applying the wait4resp after the
3092
        // ACK TX).
3093
        // See section "Transmit and automatically wait for response" in DW1000 User Manual
3094
        if((status & SYS_STATUS_AAT) && pdw1000local->wait4resp)
3095
        {
3096
            dwt_forcetrxoff(); // Turn the RX off
3097
            dwt_rxreset(); // Reset in case we were late and a frame was already being received
3098
        }
3099

    
3100
        // Call the corresponding callback if present
3101
        if(pdw1000local->cbTxDone != NULL)
3102
        {
3103
            pdw1000local->cbTxDone(&pdw1000local->cbData);
3104
        }
3105
    }
3106

    
3107
    // Handle frame reception/preamble detect timeout events
3108
    if(status & SYS_STATUS_ALL_RX_TO)
3109
    {
3110
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXRFTO); // Clear RX timeout event bits
3111

    
3112
        pdw1000local->wait4resp = 0;
3113

    
3114
        // Because of an issue with receiver restart after error conditions, an RX reset must be applied after any error or timeout event to ensure
3115
        // the next good frame's timestamp is computed correctly.
3116
        // See section "RX Message timestamp" in DW1000 User Manual.
3117
        dwt_forcetrxoff();
3118
        dwt_rxreset();
3119

    
3120
        // Call the corresponding callback if present
3121
        if(pdw1000local->cbRxTo != NULL)
3122
        {
3123
            pdw1000local->cbRxTo(&pdw1000local->cbData);
3124
        }
3125
    }
3126

    
3127
    // Handle RX errors events
3128
    if(status & SYS_STATUS_ALL_RX_ERR)
3129
    {
3130
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR); // Clear RX error event bits
3131

    
3132
        pdw1000local->wait4resp = 0;
3133

    
3134
        // Because of an issue with receiver restart after error conditions, an RX reset must be applied after any error or timeout event to ensure
3135
        // the next good frame's timestamp is computed correctly.
3136
        // See section "RX Message timestamp" in DW1000 User Manual.
3137
        dwt_forcetrxoff();
3138
        dwt_rxreset();
3139

    
3140
        // Call the corresponding callback if present
3141
        if(pdw1000local->cbRxErr != NULL)
3142
        {
3143
            pdw1000local->cbRxErr(&pdw1000local->cbData);
3144
        }
3145
    }
3146
}
3147

    
3148
/*! ------------------------------------------------------------------------------------------------------------------
3149
 * @fn dwt_isr_lplisten()
3150
 *
3151
 * @brief This is the DW1000's Interrupt Service Routine to use when low-power listening scheme is implemented. It will
3152
 *        only process/report the RXFCG event (through cbRxOk callback).
3153
 *        It clears RXFCG interrupt and reads received frame information and frame control before calling the callback.
3154
 *
3155
 *        /!\ This version of the ISR is designed for single buffering case only!
3156
 *
3157
 * input parameters
3158
 *
3159
 * output parameters
3160
 *
3161
 * no return value
3162
 */
3163
void dwt_lowpowerlistenisr(void)
3164
{
3165
    uint32_t status = pdw1000local->cbData.status = dwt_read32bitreg(SYS_STATUS_ID); // Read status register low 32bits
3166
    uint16_t finfo16;
3167
    uint16_t len;
3168

    
3169
    // The only interrupt handled when in low-power listening mode is RX good frame so proceed directly to the handling of the received frame.
3170

    
3171
    // Deactivate low-power listening before clearing the interrupt. If not, the DW1000 will go back to sleep as soon as the interrupt is cleared.
3172
    dwt_setlowpowerlistening(0);
3173

    
3174
    dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_GOOD); // Clear all receive status bits
3175

    
3176
    pdw1000local->cbData.rx_flags = 0;
3177

    
3178
    // Read frame info - Only the first two bytes of the register are used here.
3179
    finfo16 = dwt_read16bitoffsetreg(RX_FINFO_ID, 0);
3180

    
3181
    // Report frame length - Standard frame length up to 127, extended frame length up to 1023 bytes
3182
    len = finfo16 & RX_FINFO_RXFL_MASK_1023;
3183
    if(pdw1000local->longFrames == 0)
3184
    {
3185
        len &= RX_FINFO_RXFLEN_MASK;
3186
    }
3187
    pdw1000local->cbData.datalength = len;
3188

    
3189
    // Report ranging bit
3190
    if(finfo16 & RX_FINFO_RNG)
3191
    {
3192
        pdw1000local->cbData.rx_flags |= DWT_CB_DATA_RX_FLAG_RNG;
3193
    }
3194

    
3195
    // Report frame control - First bytes of the received frame.
3196
    dwt_readfromdevice(RX_BUFFER_ID, 0, FCTRL_LEN_MAX, pdw1000local->cbData.fctrl);
3197

    
3198
    // Because of a previous frame not being received properly, AAT bit can be set upon the proper reception of a frame not requesting for
3199
    // acknowledgement (ACK frame is not actually sent though). If the AAT bit is set, check ACK request bit in frame control to confirm (this
3200
    // implementation works only for IEEE802.15.4-2011 compliant frames).
3201
    // This issue is not documented at the time of writing this code. It should be in next release of DW1000 User Manual (v2.09, from July 2016).
3202
    if((status & SYS_STATUS_AAT) && ((pdw1000local->cbData.fctrl[0] & FCTRL_ACK_REQ_MASK) == 0))
3203
    {
3204
        dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_AAT); // Clear AAT status bit in register
3205
        pdw1000local->cbData.status &= ~SYS_STATUS_AAT; // Clear AAT status bit in callback data register copy
3206
        pdw1000local->wait4resp = 0;
3207
    }
3208

    
3209
    // Call the corresponding callback if present
3210
    if(pdw1000local->cbRxOk != NULL)
3211
    {
3212
        pdw1000local->cbRxOk(&pdw1000local->cbData);
3213
    }
3214
}
3215

    
3216
/*! ------------------------------------------------------------------------------------------------------------------
3217
 * @fn dwt_setleds()
3218
 *
3219
 * @brief This is used to set up Tx/Rx GPIOs which could be used to control LEDs
3220
 * Note: not completely IC dependent, also needs board with LEDS fitted on right I/O lines
3221
 *       this function enables GPIOs 2 and 3 which are connected to LED3 and LED4 on EVB1000
3222
 *
3223
 * input parameters
3224
 * @param mode - this is a bit field interpreted as follows:
3225
 *          - bit 0: 1 to enable LEDs, 0 to disable them
3226
 *          - bit 1: 1 to make LEDs blink once on init. Only valid if bit 0 is set (enable LEDs)
3227
 *          - bit 2 to 7: reserved
3228
 *
3229
 * output parameters none
3230
 *
3231
 * no return value
3232
 */
3233
void dwt_setleds(uint8_t mode)
3234
{
3235
    uint32_t reg;
3236

    
3237
    if (mode & DWT_LEDS_ENABLE)
3238
    {
3239
        // Set up MFIO for LED output.
3240
        reg = dwt_read32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET);
3241
        reg &= ~(GPIO_MSGP2_MASK | GPIO_MSGP3_MASK);
3242
        reg |= (GPIO_PIN2_RXLED | GPIO_PIN3_TXLED);
3243
        dwt_write32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET, reg);
3244

    
3245
        // Enable LP Oscillator to run from counter and turn on de-bounce clock.
3246
        reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET);
3247
        reg |= (PMSC_CTRL0_GPDCE | PMSC_CTRL0_KHZCLEN);
3248
        dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, reg);
3249

    
3250
        // Enable LEDs to blink and set default blink time.
3251
        reg = PMSC_LEDC_BLNKEN | PMSC_LEDC_BLINK_TIME_DEF;
3252
        // Make LEDs blink once if requested.
3253
        if (mode & DWT_LEDS_INIT_BLINK)
3254
        {
3255
            reg |= PMSC_LEDC_BLINK_NOW_ALL;
3256
        }
3257
        dwt_write32bitoffsetreg(PMSC_ID, PMSC_LEDC_OFFSET, reg);
3258
        // Clear force blink bits if needed.
3259
        if(mode & DWT_LEDS_INIT_BLINK)
3260
        {
3261
            reg &= ~PMSC_LEDC_BLINK_NOW_ALL;
3262
            dwt_write32bitoffsetreg(PMSC_ID, PMSC_LEDC_OFFSET, reg);
3263
        }
3264
    }
3265
    else
3266
    {
3267
        // Clear the GPIO bits that are used for LED control.
3268
        reg = dwt_read32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET);
3269
        reg &= ~(GPIO_MSGP2_MASK | GPIO_MSGP3_MASK);
3270
        dwt_write32bitoffsetreg(GPIO_CTRL_ID, GPIO_MODE_OFFSET, reg);
3271
    }
3272
}
3273

    
3274
/*! ------------------------------------------------------------------------------------------------------------------
3275
 * @fn _dwt_enableclocks()
3276
 *
3277
 * @brief function to enable/disable clocks to particular digital blocks/system
3278
 *
3279
 * input parameters
3280
 * @param clocks - set of clocks to enable/disable
3281
 *
3282
 * output parameters none
3283
 *
3284
 * no return value
3285
 */
3286
void _dwt_enableclocks(int clocks)
3287
{
3288
    uint8_t reg[2];
3289

    
3290
    dwt_readfromdevice(PMSC_ID, PMSC_CTRL0_OFFSET, 2, reg);
3291
    switch(clocks)
3292
    {
3293
        case ENABLE_ALL_SEQ:
3294
        {
3295
            reg[0] = 0x00 ;
3296
            reg[1] = reg[1] & 0xfe;
3297
        }
3298
        break;
3299
        case FORCE_SYS_XTI:
3300
        {
3301
            // System and RX
3302
            reg[0] = 0x01 | (reg[0] & 0xfc);
3303
        }
3304
        break;
3305
        case FORCE_SYS_PLL:
3306
        {
3307
            // System
3308
            reg[0] = 0x02 | (reg[0] & 0xfc);
3309
        }
3310
        break;
3311
        case READ_ACC_ON:
3312
        {
3313
            reg[0] = 0x48 | (reg[0] & 0xb3);
3314
            reg[1] = 0x80 | reg[1];
3315
        }
3316
        break;
3317
        case READ_ACC_OFF:
3318
        {
3319
            reg[0] = reg[0] & 0xb3;
3320
            reg[1] = 0x7f & reg[1];
3321
        }
3322
        break;
3323
        case FORCE_OTP_ON:
3324
        {
3325
            reg[1] = 0x02 | reg[1];
3326
        }
3327
        break;
3328
        case FORCE_OTP_OFF:
3329
        {
3330
            reg[1] = reg[1] & 0xfd;
3331
        }
3332
        break;
3333
        case FORCE_TX_PLL:
3334
        {
3335
            reg[0] = 0x20 | (reg[0] & 0xcf);
3336
        }
3337
        break;
3338
        case FORCE_LDE:
3339
        {
3340
            reg[0] = 0x01;
3341
            reg[1] = 0x03;
3342
        }
3343
        break;
3344
        default:
3345
        break;
3346
    }
3347

    
3348

    
3349
    // Need to write lower byte separately before setting the higher byte(s)
3350
    dwt_writetodevice(PMSC_ID, PMSC_CTRL0_OFFSET, 1, &reg[0]);
3351
    dwt_writetodevice(PMSC_ID, 0x1, 1, &reg[1]);
3352

    
3353
} // end _dwt_enableclocks()
3354

    
3355
/*! ------------------------------------------------------------------------------------------------------------------
3356
 * @fn _dwt_disablesequencing()
3357
 *
3358
 * @brief This function disables the TX blocks sequencing, it disables PMSC control of RF blocks, system clock is also set to XTAL
3359
 *
3360
 * input parameters none
3361
 *
3362
 * output parameters none
3363
 *
3364
 * no return value
3365
 */
3366
void _dwt_disablesequencing(void) // Disable sequencing and go to state "INIT"
3367
{
3368
    _dwt_enableclocks(FORCE_SYS_XTI); // Set system clock to XTI
3369

    
3370
    dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, PMSC_CTRL1_PKTSEQ_DISABLE); // Disable PMSC ctrl of RF and RX clk blocks
3371
}
3372

    
3373
/*! ------------------------------------------------------------------------------------------------------------------
3374
 * @fn dwt_setdelayedtrxtime()
3375
 *
3376
 * @brief This API function configures the delayed transmit time or the delayed RX on time
3377
 *
3378
 * input parameters
3379
 * @param starttime - the TX/RX start time (the 32 bits should be the high 32 bits of the system time at which to send the message,
3380
 * or at which to turn on the receiver)
3381
 *
3382
 * output parameters none
3383
 *
3384
 * no return value
3385
 */
3386
void dwt_setdelayedtrxtime(uint32_t starttime)
3387
{
3388
    dwt_write32bitoffsetreg(DX_TIME_ID, 1, starttime); // Write at offset 1 as the lower 9 bits of this register are ignored
3389

    
3390
} // end dwt_setdelayedtrxtime()
3391

    
3392
/*! ------------------------------------------------------------------------------------------------------------------
3393
 * @fn dwt_starttx()
3394
 *
3395
 * @brief This call initiates the transmission, input parameter indicates which TX mode is used see below
3396
 *
3397
 * input parameters:
3398
 * @param mode - if 0 immediate TX (no response expected)
3399
 *               if 1 delayed TX (no response expected)
3400
 *               if 2 immediate TX (response expected - so the receiver will be automatically turned on after TX is done)
3401
 *               if 3 delayed TX (response expected - so the receiver will be automatically turned on after TX is done)
3402
 *
3403
 * output parameters
3404
 *
3405
 * returns DWT_SUCCESS for success, or DWT_ERROR for error (e.g. a delayed transmission will fail if the delayed time has passed)
3406
 */
3407
int dwt_starttx(uint8_t mode)
3408
{
3409
    int retval = DWT_SUCCESS ;
3410
    uint8_t temp  = 0x00;
3411
    uint16_t checkTxOK = 0 ;
3412

    
3413
    if(mode & DWT_RESPONSE_EXPECTED)
3414
    {
3415
        temp = (uint8_t)SYS_CTRL_WAIT4RESP ; // Set wait4response bit
3416
        dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3417
        pdw1000local->wait4resp = 1;
3418
    }
3419

    
3420
    if (mode & DWT_START_TX_DELAYED)
3421
    {
3422
        // Both SYS_CTRL_TXSTRT and SYS_CTRL_TXDLYS to correctly enable TX
3423
        temp |= (uint8_t)(SYS_CTRL_TXDLYS | SYS_CTRL_TXSTRT) ;
3424
        dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3425
        checkTxOK = dwt_read16bitoffsetreg(SYS_STATUS_ID, 3); // Read at offset 3 to get the upper 2 bytes out of 5
3426
        if ((checkTxOK & SYS_STATUS_TXERR) == 0) // Transmit Delayed Send set over Half a Period away or Power Up error (there is enough time to send but not to power up individual blocks).
3427
        {
3428
            retval = DWT_SUCCESS ; // All okay
3429
        }
3430
        else
3431
        {
3432
            // I am taking DSHP set to Indicate that the TXDLYS was set too late for the specified DX_TIME.
3433
            // Remedial Action - (a) cancel delayed send
3434
            temp = (uint8_t)SYS_CTRL_TRXOFF; // This assumes the bit is in the lowest byte
3435
            dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3436
            // Note event Delayed TX Time too Late
3437
            // Could fall through to start a normal send (below) just sending late.....
3438
            // ... instead return and assume return value of 1 will be used to detect and recover from the issue.
3439
            pdw1000local->wait4resp = 0;
3440
            retval = DWT_ERROR ; // Failed !
3441
        }
3442
    }
3443
    else
3444
    {
3445
        temp |= (uint8_t)SYS_CTRL_TXSTRT ;
3446
        dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3447
    }
3448

    
3449
    return retval;
3450

    
3451
} // end dwt_starttx()
3452

    
3453
/*! ------------------------------------------------------------------------------------------------------------------
3454
 * @fn dwt_forcetrxoff()
3455
 *
3456
 * @brief This is used to turn off the transceiver
3457
 *
3458
 * input parameters
3459
 *
3460
 * output parameters
3461
 *
3462
 * no return value
3463
 */
3464
void dwt_forcetrxoff(void)
3465
{
3466
    decaIrqStatus_t stat ;
3467
    uint32_t mask;
3468

    
3469
    mask = dwt_read32bitreg(SYS_MASK_ID) ; // Read set interrupt mask
3470

    
3471
    // Need to beware of interrupts occurring in the middle of following read modify write cycle
3472
    // We can disable the radio, but before the status is cleared an interrupt can be set (e.g. the
3473
    // event has just happened before the radio was disabled)
3474
    // thus we need to disable interrupt during this operation
3475
    stat = decamutexon() ;
3476

    
3477
    dwt_write32bitreg(SYS_MASK_ID, 0) ; // Clear interrupt mask - so we don't get any unwanted events
3478

    
3479
    dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, (uint8_t)SYS_CTRL_TRXOFF) ; // Disable the radio
3480

    
3481
    // Forcing Transceiver off - so we do not want to see any new events that may have happened
3482
    dwt_write32bitreg(SYS_STATUS_ID, (SYS_STATUS_ALL_TX | SYS_STATUS_ALL_RX_ERR | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_GOOD));
3483

    
3484
    dwt_syncrxbufptrs();
3485

    
3486
    dwt_write32bitreg(SYS_MASK_ID, mask) ; // Set interrupt mask to what it was
3487

    
3488
    // Enable/restore interrupts again...
3489
    decamutexoff(stat) ;
3490
    pdw1000local->wait4resp = 0;
3491

    
3492
} // end deviceforcetrxoff()
3493

    
3494
/*! ------------------------------------------------------------------------------------------------------------------
3495
 * @fn dwt_syncrxbufptrs()
3496
 *
3497
 * @brief this function synchronizes rx buffer pointers
3498
 * need to make sure that the host/IC buffer pointers are aligned before starting RX
3499
 *
3500
 * input parameters:
3501
 *
3502
 * output parameters
3503
 *
3504
 * no return value
3505
 */
3506
void dwt_syncrxbufptrs(void)
3507
{
3508
    uint8_t  buff ;
3509
    // Need to make sure that the host/IC buffer pointers are aligned before starting RX
3510
    buff = dwt_read8bitoffsetreg(SYS_STATUS_ID, 3); // Read 1 byte at offset 3 to get the 4th byte out of 5
3511

    
3512
    if((buff & (SYS_STATUS_ICRBP >> 24)) !=     // IC side Receive Buffer Pointer
3513
       ((buff & (SYS_STATUS_HSRBP>>24)) << 1) ) // Host Side Receive Buffer Pointer
3514
    {
3515
        dwt_write8bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_HRBT_OFFSET , 0x01) ; // We need to swap RX buffer status reg (write one to toggle internally)
3516
    }
3517
}
3518

    
3519
/*! ------------------------------------------------------------------------------------------------------------------
3520
 * @fn dwt_setsniffmode()
3521
 *
3522
 * @brief enable/disable and configure SNIFF mode.
3523
 *
3524
 * SNIFF mode is a low-power reception mode where the receiver is sequenced on and off instead of being on all the time.
3525
 * The time spent in each state (on/off) is specified through the parameters below.
3526
 * See DW1000 User Manual section 4.5 "Low-Power SNIFF mode" for more details.
3527
 *
3528
 * input parameters:
3529
 * @param enable - 1 to enable SNIFF mode, 0 to disable. When 0, all other parameters are not taken into account.
3530
 * @param timeOn - duration of receiver ON phase, expressed in multiples of PAC size. The counter automatically adds 1 PAC
3531
 *                 size to the value set. Min value that can be set is 1 (i.e. an ON time of 2 PAC size), max value is 15.
3532
 * @param timeOff - duration of receiver OFF phase, expressed in multiples of 128/125 µs (~1 µs). Max value is 255.
3533
 *
3534
 * output parameters
3535
 *
3536
 * no return value
3537
 */
3538
void dwt_setsniffmode(int enable, uint8_t timeOn, uint8_t timeOff)
3539
{
3540
    uint32_t pmsc_reg;
3541
    if (enable)
3542
    {
3543
        /* Configure ON/OFF times and enable PLL2 on/off sequencing by SNIFF mode. */
3544
        uint16_t sniff_reg = ((timeOff << 8) | timeOn) & RX_SNIFF_MASK;
3545
        dwt_write16bitoffsetreg(RX_SNIFF_ID, RX_SNIFF_OFFSET, sniff_reg);
3546
        pmsc_reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET);
3547
        pmsc_reg |= PMSC_CTRL0_PLL2_SEQ_EN;
3548
        dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, pmsc_reg);
3549
    }
3550
    else
3551
    {
3552
        /* Clear ON/OFF times and disable PLL2 on/off sequencing by SNIFF mode. */
3553
        dwt_write16bitoffsetreg(RX_SNIFF_ID, RX_SNIFF_OFFSET, 0x0000);
3554
        pmsc_reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET);
3555
        pmsc_reg &= ~PMSC_CTRL0_PLL2_SEQ_EN;
3556
        dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, pmsc_reg);
3557
    }
3558
}
3559

    
3560
/*! ------------------------------------------------------------------------------------------------------------------
3561
 * @fn dwt_setlowpowerlistening()
3562
 *
3563
 * @brief enable/disable low-power listening mode.
3564
 *
3565
 * Low-power listening is a feature whereby the DW1000 is predominantly in the SLEEP state but wakes periodically, (after
3566
 * this "long sleep"), for a very short time to sample the air for a preamble sequence. This preamble sampling "listening"
3567
 * phase is actually two reception phases separated by a "short sleep" time. See DW1000 User Manual section "Low-Power
3568
 * Listening" for more details.
3569
 *
3570
 * NOTE: Before enabling low-power listening, the following functions have to be called to fully configure it:
3571
 *           - dwt_configuresleep() to configure long sleep phase. "mode" parameter should at least have DWT_PRESRV_SLEEP,
3572
 *             DWT_CONFIG and DWT_RX_EN set and "wake" parameter should at least have both DWT_WAKE_SLPCNT and DWT_SLP_EN set.
3573
 *           - dwt_calibratesleepcnt() and dwt_configuresleepcnt() to define the "long sleep" phase duration.
3574
 *           - dwt_setsnoozetime() to define the "short sleep" phase duration.
3575
 *           - dwt_setpreambledetecttimeout() to define the reception phases duration.
3576
 *           - dwt_setinterrupt() to activate RX good frame interrupt (DWT_INT_RFCG) only.
3577
 *       When configured, low-power listening mode can be triggered either by putting the DW1000 to sleep (using
3578
 *       dwt_entersleep()) or by activating reception (using dwt_rxenable()).
3579
 *
3580
 *       Please refer to the low-power listening examples (examples 8a/8b accompanying the API distribution on Decawave's
3581
 *       website). They form a working example code that shows how to use low-power listening correctly.
3582
 *
3583
 * input parameters:
3584
 * @param enable - 1 to enable low-power listening, 0 to disable.
3585
 *
3586
 * output parameters
3587
 *
3588
 * no return value
3589
 */
3590
void dwt_setlowpowerlistening(int enable)
3591
{
3592
    uint32_t pmsc_reg = dwt_read32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET);
3593
    if (enable)
3594
    {
3595
        /* Configure RX to sleep and snooze features. */
3596
        pmsc_reg |= (PMSC_CTRL1_ARXSLP | PMSC_CTRL1_SNOZE);
3597
    }
3598
    else
3599
    {
3600
        /* Reset RX to sleep and snooze features. */
3601
        pmsc_reg &= ~(PMSC_CTRL1_ARXSLP | PMSC_CTRL1_SNOZE);
3602
    }
3603
    dwt_write32bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, pmsc_reg);
3604
}
3605

    
3606
/*! ------------------------------------------------------------------------------------------------------------------
3607
 * @fn dwt_setsnoozetime()
3608
 *
3609
 * @brief Set duration of "short sleep" phase when in low-power listening mode.
3610
 *
3611
 * input parameters:
3612
 * @param snooze_time - "short sleep" phase duration, expressed in multiples of 512/19.2 µs (~26.7 µs). The counter
3613
 *                      automatically adds 1 to the value set. The smallest working value that should be set is 1,
3614
 *                      i.e. giving a snooze time of 2 units (or ~53 µs).
3615
 *
3616
 * output parameters
3617
 *
3618
 * no return value
3619
 */
3620
void dwt_setsnoozetime(uint8_t snooze_time)
3621
{
3622
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_SNOZT_OFFSET, snooze_time);
3623
}
3624

    
3625
/*! ------------------------------------------------------------------------------------------------------------------
3626
 * @fn dwt_rxenable()
3627
 *
3628
 * @brief This call turns on the receiver, can be immediate or delayed (depending on the mode parameter). In the case of a
3629
 * "late" error the receiver will only be turned on if the DWT_IDLE_ON_DLY_ERR is not set.
3630
 * The receiver will stay turned on, listening to any messages until
3631
 * it either receives a good frame, an error (CRC, PHY header, Reed Solomon) or  it times out (SFD, Preamble or Frame).
3632
 *
3633
 * input parameters
3634
 * @param mode - this can be one of the following allowed values:
3635
 *
3636
 * DWT_START_RX_IMMEDIATE      0 used to enbale receiver immediately
3637
 * DWT_START_RX_DELAYED        1 used to set up delayed RX, if "late" error triggers, then the RX will be enabled immediately
3638
 * (DWT_START_RX_DELAYED | DWT_IDLE_ON_DLY_ERR) 3 used to disable re-enabling of receiver if delayed RX failed due to "late" error
3639
 * (DWT_START_RX_IMMEDIATE | DWT_NO_SYNC_PTRS) 4 used to re-enable RX without trying to sync IC and host side buffer pointers, typically when
3640
 *                                               performing manual RX re-enabling in double buffering mode
3641
 *
3642
 * returns DWT_SUCCESS for success, or DWT_ERROR for error (e.g. a delayed receive enable will be too far in the future if delayed time has passed)
3643
 */
3644
int dwt_rxenable(int mode)
3645
{
3646
    uint16_t temp ;
3647
    uint8_t temp1 ;
3648

    
3649
    if ((mode & DWT_NO_SYNC_PTRS) == 0)
3650
    {
3651
        dwt_syncrxbufptrs();
3652
    }
3653

    
3654
    temp = (uint16_t)SYS_CTRL_RXENAB ;
3655

    
3656
    if (mode & DWT_START_RX_DELAYED)
3657
    {
3658
        temp |= (uint16_t)SYS_CTRL_RXDLYE ;
3659
    }
3660

    
3661
    dwt_write16bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, temp);
3662

    
3663
    if (mode & DWT_START_RX_DELAYED) // check for errors
3664
    {
3665
        temp1 = dwt_read8bitoffsetreg(SYS_STATUS_ID, 3); // Read 1 byte at offset 3 to get the 4th byte out of 5
3666
        if ((temp1 & (SYS_STATUS_HPDWARN >> 24)) != 0) // if delay has passed do immediate RX on unless DWT_IDLE_ON_DLY_ERR is true
3667
        {
3668
            dwt_forcetrxoff(); // turn the delayed receive off
3669

    
3670
            if((mode & DWT_IDLE_ON_DLY_ERR) == 0) // if DWT_IDLE_ON_DLY_ERR not set then re-enable receiver
3671
            {
3672
                dwt_write16bitoffsetreg(SYS_CTRL_ID, SYS_CTRL_OFFSET, SYS_CTRL_RXENAB);
3673
            }
3674
            return DWT_ERROR; // return warning indication
3675
        }
3676
    }
3677

    
3678
    return DWT_SUCCESS;
3679
} // end dwt_rxenable()
3680

    
3681
/*! ------------------------------------------------------------------------------------------------------------------
3682
 * @fn dwt_setrxtimeout()
3683
 *
3684
 * @brief This call enables RX timeout (SY_STAT_RFTO event)
3685
 *
3686
 * input parameters
3687
 * @param time - how long the receiver remains on from the RX enable command
3688
 *               The time parameter used here is in 1.0256 us (512/499.2MHz) units
3689
 *               If set to 0 the timeout is disabled.
3690
 *
3691
 * output parameters
3692
 *
3693
 * no return value
3694
 */
3695
void dwt_setrxtimeout(uint16_t time)
3696
{
3697
    uint8_t temp ;
3698

    
3699
    temp = dwt_read8bitoffsetreg(SYS_CFG_ID, 3); // Read at offset 3 to get the upper byte only
3700

    
3701
    if(time > 0)
3702
    {
3703
        dwt_write16bitoffsetreg(RX_FWTO_ID, RX_FWTO_OFFSET, time) ;
3704

    
3705
        temp |= (uint8_t)(SYS_CFG_RXWTOE>>24); // Shift RXWTOE mask as we read the upper byte only
3706
        // OR in 32bit value (1 bit set), I know this is in high byte.
3707
        pdw1000local->sysCFGreg |= SYS_CFG_RXWTOE;
3708

    
3709
        dwt_write8bitoffsetreg(SYS_CFG_ID, 3, temp); // Write at offset 3 to write the upper byte only
3710
    }
3711
    else
3712
    {
3713
        temp &= ~((uint8_t)(SYS_CFG_RXWTOE>>24)); // Shift RXWTOE mask as we read the upper byte only
3714
        // AND in inverted 32bit value (1 bit clear), I know this is in high byte.
3715
        pdw1000local->sysCFGreg &= ~(SYS_CFG_RXWTOE);
3716

    
3717
        dwt_write8bitoffsetreg(SYS_CFG_ID, 3, temp); // Write at offset 3 to write the upper byte only
3718
    }
3719

    
3720
} // end dwt_setrxtimeout()
3721

    
3722

    
3723
/*! ------------------------------------------------------------------------------------------------------------------
3724
 * @fn dwt_setpreambledetecttimeout()
3725
 *
3726
 * @brief This call enables preamble timeout (SY_STAT_RXPTO event)
3727
 *
3728
 * input parameters
3729
 * @param  timeout - Preamble detection timeout, expressed in multiples of PAC size. The counter automatically adds 1 PAC
3730
 *                   size to the value set. Min value that can be set is 1 (i.e. a timeout of 2 PAC size).
3731
 *
3732
 * output parameters
3733
 *
3734
 * no return value
3735
 */
3736
void dwt_setpreambledetecttimeout(uint16_t timeout)
3737
{
3738
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_PRETOC_OFFSET, timeout);
3739
}
3740

    
3741
/*! ------------------------------------------------------------------------------------------------------------------
3742
 * @fn void dwt_setinterrupt()
3743
 *
3744
 * @brief This function enables the specified events to trigger an interrupt.
3745
 * The following events can be enabled:
3746
 * DWT_INT_TFRS         0x00000080          // frame sent
3747
 * DWT_INT_RFCG         0x00004000          // frame received with good CRC
3748
 * DWT_INT_RPHE         0x00001000          // receiver PHY header error
3749
 * DWT_INT_RFCE         0x00008000          // receiver CRC error
3750
 * DWT_INT_RFSL         0x00010000          // receiver sync loss error
3751
 * DWT_INT_RFTO         0x00020000          // frame wait timeout
3752
 * DWT_INT_RXPTO        0x00200000          // preamble detect timeout
3753
 * DWT_INT_SFDT         0x04000000          // SFD timeout
3754
 * DWT_INT_ARFE         0x20000000          // frame rejected (due to frame filtering configuration)
3755
 *
3756
 *
3757
 * input parameters:
3758
 * @param bitmask - sets the events which will generate interrupt
3759
 * @param enable - if set the interrupts are enabled else they are cleared
3760
 *
3761
 * output parameters
3762
 *
3763
 * no return value
3764
 */
3765
void dwt_setinterrupt(uint32_t bitmask, uint8_t enable)
3766
{
3767
    decaIrqStatus_t stat ;
3768
    uint32_t mask ;
3769

    
3770
    // Need to beware of interrupts occurring in the middle of following read modify write cycle
3771
    stat = decamutexon() ;
3772

    
3773
    mask = dwt_read32bitreg(SYS_MASK_ID) ; // Read register
3774

    
3775
    if(enable)
3776
    {
3777
        mask |= bitmask ;
3778
    }
3779
    else
3780
    {
3781
        mask &= ~bitmask ; // Clear the bit
3782
    }
3783
    dwt_write32bitreg(SYS_MASK_ID,mask) ; // New value
3784

    
3785
    decamutexoff(stat) ;
3786
}
3787

    
3788
/*! ------------------------------------------------------------------------------------------------------------------
3789
 * @fn dwt_configeventcounters()
3790
 *
3791
 * @brief This is used to enable/disable the event counter in the IC
3792
 *
3793
 * input parameters
3794
 * @param - enable - 1 enables (and reset), 0 disables the event counters
3795
 * output parameters
3796
 *
3797
 * no return value
3798
 */
3799
void dwt_configeventcounters(int enable)
3800
{
3801
    // Need to clear and disable, can't just clear
3802
    dwt_write8bitoffsetreg(DIG_DIAG_ID, EVC_CTRL_OFFSET, (uint8_t)(EVC_CLR));
3803

    
3804
    if(enable)
3805
    {
3806
        dwt_write8bitoffsetreg(DIG_DIAG_ID, EVC_CTRL_OFFSET, (uint8_t)(EVC_EN)); // Enable
3807
    }
3808
}
3809

    
3810
/*! ------------------------------------------------------------------------------------------------------------------
3811
 * @fn dwt_readeventcounters()
3812
 *
3813
 * @brief This is used to read the event counters in the IC
3814
 *
3815
 * input parameters
3816
 * @param counters - pointer to the dwt_deviceentcnts_t structure which will hold the read data
3817
 *
3818
 * output parameters
3819
 *
3820
 * no return value
3821
 */
3822
void dwt_readeventcounters(dwt_deviceentcnts_t *counters)
3823
{
3824
    uint32_t temp;
3825

    
3826
    temp= dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_PHE_OFFSET); // Read sync loss (31-16), PHE (15-0)
3827
    counters->PHE = temp & 0xFFF;
3828
    counters->RSL = (temp >> 16) & 0xFFF;
3829

    
3830
    temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_FCG_OFFSET); // Read CRC bad (31-16), CRC good (15-0)
3831
    counters->CRCG = temp & 0xFFF;
3832
    counters->CRCB = (temp >> 16) & 0xFFF;
3833

    
3834
    temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_FFR_OFFSET); // Overruns (31-16), address errors (15-0)
3835
    counters->ARFE = temp & 0xFFF;
3836
    counters->OVER = (temp >> 16) & 0xFFF;
3837

    
3838
    temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_STO_OFFSET); // Read PTO (31-16), SFDTO (15-0)
3839
    counters->PTO = (temp >> 16) & 0xFFF;
3840
    counters->SFDTO = temp & 0xFFF;
3841

    
3842
    temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_FWTO_OFFSET); // Read RX TO (31-16), TXFRAME (15-0)
3843
    counters->TXF = (temp >> 16) & 0xFFF;
3844
    counters->RTO = temp & 0xFFF;
3845

    
3846
    temp = dwt_read32bitoffsetreg(DIG_DIAG_ID, EVC_HPW_OFFSET); // Read half period warning events
3847
    counters->HPW = temp & 0xFFF;
3848
    counters->TXW = (temp >> 16) & 0xFFF;                       // Power-up warning events
3849

    
3850
}
3851

    
3852
/*! ------------------------------------------------------------------------------------------------------------------
3853
 * @fn dwt_rxreset()
3854
 *
3855
 * @brief this function resets the receiver of the DW1000
3856
 *
3857
 * input parameters:
3858
 *
3859
 * output parameters
3860
 *
3861
 * no return value
3862
 */
3863
void dwt_rxreset(void)
3864
{
3865
    // Set RX reset
3866
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_SOFTRESET_OFFSET, PMSC_CTRL0_RESET_RX);
3867

    
3868
    // Clear RX reset
3869
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_SOFTRESET_OFFSET, PMSC_CTRL0_RESET_CLEAR);
3870
}
3871

    
3872
/*! ------------------------------------------------------------------------------------------------------------------
3873
 * @fn dwt_softreset()
3874
 *
3875
 * @brief this function resets the DW1000
3876
 *
3877
 * input parameters:
3878
 *
3879
 * output parameters
3880
 *
3881
 * no return value
3882
 */
3883
void dwt_softreset(void)
3884
{
3885
    _dwt_disablesequencing();
3886

    
3887
    // Clear any AON auto download bits (as reset will trigger AON download)
3888
    dwt_write16bitoffsetreg(AON_ID, AON_WCFG_OFFSET, 0x00);
3889
    // Clear the wake-up configuration
3890
    dwt_write8bitoffsetreg(AON_ID, AON_CFG0_OFFSET, 0x00);
3891
    // Upload the new configuration
3892
    _dwt_aonarrayupload();
3893

    
3894
    // Reset HIF, TX, RX and PMSC
3895
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_SOFTRESET_OFFSET, PMSC_CTRL0_RESET_ALL);
3896

    
3897
    // DW1000 needs a 10us sleep to let clk PLL lock after reset - the PLL will automatically lock after the reset
3898
    // Could also have polled the PLL lock flag, but then the SPI needs to be < 3MHz !! So a simple delay is easier
3899
    deca_sleep(1);
3900

    
3901
    // Clear reset
3902
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_SOFTRESET_OFFSET, PMSC_CTRL0_RESET_CLEAR);
3903

    
3904
    pdw1000local->wait4resp = 0;
3905
}
3906

    
3907
/*! ------------------------------------------------------------------------------------------------------------------
3908
 * @fn dwt_setxtaltrim()
3909
 *
3910
 * @brief This is used to adjust the crystal frequency
3911
 *
3912
 * input parameters:
3913
 * @param   value - crystal trim value (in range 0x0 to 0x1F) 31 steps (~1.5ppm per step)
3914
 *
3915
 * output parameters
3916
 *
3917
 * no return value
3918
 */
3919
void dwt_setxtaltrim(uint8_t value)
3920
{
3921
    // The 3 MSb in this 8-bit register must be kept to 0b011 to avoid any malfunction.
3922
    uint8_t reg_val = (3 << 5) | (value & FS_XTALT_MASK);
3923
    dwt_write8bitoffsetreg(FS_CTRL_ID, FS_XTALT_OFFSET, reg_val);
3924
}
3925

    
3926
/*! ------------------------------------------------------------------------------------------------------------------
3927
 * @fn dwt_getinitxtaltrim()
3928
 *
3929
 * @brief This function returns the value of XTAL trim that has been applied during initialisation (dwt_init). This can
3930
 *        be either the value read in OTP memory or a default value.
3931
 *
3932
 * NOTE: The value returned by this function is the initial value only! It is not updated on dwt_setxtaltrim calls.
3933
 *
3934
 * input parameters
3935
 *
3936
 * output parameters
3937
 *
3938
 * returns the XTAL trim value set upon initialisation
3939
 */
3940
uint8_t dwt_getinitxtaltrim(void)
3941
{
3942
    return pdw1000local->init_xtrim;
3943
}
3944

    
3945
/*! ------------------------------------------------------------------------------------------------------------------
3946
 * @fn dwt_configcwmode()
3947
 *
3948
 * @brief this function sets the DW1000 to transmit cw signal at specific channel frequency
3949
 *
3950
 * input parameters:
3951
 * @param chan - specifies the operating channel (e.g. 1, 2, 3, 4, 5, 6 or 7)
3952
 *
3953
 * output parameters
3954
 *
3955
 * no return value
3956
 */
3957
void dwt_configcwmode(uint8_t chan)
3958
{
3959
#ifdef DWT_API_ERROR_CHECK
3960
    assert((chan >= 1) && (chan <= 7) && (chan != 6));
3961
#endif
3962

    
3963
    //
3964
    // Disable TX/RX RF block sequencing (needed for cw frame mode)
3965
    //
3966
    _dwt_disablesequencing();
3967

    
3968
    // Config RF pll (for a given channel)
3969
    // Configure PLL2/RF PLL block CFG/TUNE
3970
    dwt_write32bitoffsetreg(FS_CTRL_ID, FS_PLLCFG_OFFSET, fs_pll_cfg[chan_idx[chan]]);
3971
    dwt_write8bitoffsetreg(FS_CTRL_ID, FS_PLLTUNE_OFFSET, fs_pll_tune[chan_idx[chan]]);
3972
    // PLL wont be enabled until a TX/RX enable is issued later on
3973
    // Configure RF TX blocks (for specified channel and prf)
3974
    // Config RF TX control
3975
    dwt_write32bitoffsetreg(RF_CONF_ID, RF_TXCTRL_OFFSET, tx_config[chan_idx[chan]]);
3976

    
3977
    //
3978
    // Enable RF PLL
3979
    //
3980
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXPLLPOWEN_MASK); // Enable LDO and RF PLL blocks
3981
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXALLEN_MASK); // Enable the rest of TX blocks
3982

    
3983
    //
3984
    // Configure TX clocks
3985
    //
3986
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, 0x22);
3987
    dwt_write8bitoffsetreg(PMSC_ID, 0x1, 0x07);
3988

    
3989
    // Disable fine grain TX sequencing
3990
    dwt_setfinegraintxseq(0);
3991

    
3992
    // Configure CW mode
3993
    dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGTEST_OFFSET, TC_PGTEST_CW);
3994
}
3995

    
3996
/*! ------------------------------------------------------------------------------------------------------------------
3997
 * @fn dwt_configcontinuousframemode()
3998
 *
3999
 * @brief this function sets the DW1000 to continuous tx frame mode for regulatory approvals testing.
4000
 *
4001
 * input parameters:
4002
 * @param framerepetitionrate - This is a 32-bit value that is used to set the interval between transmissions.
4003
*  The minimum value is 4. The units are approximately 8 ns. (or more precisely 512/(499.2e6*128) seconds)).
4004
 *
4005
 * output parameters
4006
 *
4007
 * no return value
4008
 */
4009
void dwt_configcontinuousframemode(uint32_t framerepetitionrate)
4010
{
4011
    //
4012
    // Disable TX/RX RF block sequencing (needed for continuous frame mode)
4013
    //
4014
    _dwt_disablesequencing();
4015

    
4016
    //
4017
    // Enable RF PLL and TX blocks
4018
    //
4019
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXPLLPOWEN_MASK); // Enable LDO and RF PLL blocks
4020
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXALLEN_MASK); // Enable the rest of TX blocks
4021

    
4022
    //
4023
    // Configure TX clocks
4024
    //
4025
    _dwt_enableclocks(FORCE_SYS_PLL);
4026
    _dwt_enableclocks(FORCE_TX_PLL);
4027

    
4028
    // Set the frame repetition rate
4029
    if(framerepetitionrate < 4)
4030
    {
4031
        framerepetitionrate = 4;
4032
    }
4033
    dwt_write32bitreg(DX_TIME_ID, framerepetitionrate);
4034

    
4035
    //
4036
    // Configure continuous frame TX
4037
    //
4038
    dwt_write8bitoffsetreg(DIG_DIAG_ID, DIAG_TMC_OFFSET, (uint8_t)(DIAG_TMC_TX_PSTM)); // Turn the tx power spectrum test mode - continuous sending of frames
4039
}
4040

    
4041
/*! ------------------------------------------------------------------------------------------------------------------
4042
 * @fn dwt_readtempvbat()
4043
 *
4044
 * @brief this function reads the battery voltage and temperature of the MP
4045
 * The values read here will be the current values sampled by DW1000 AtoD converters.
4046
 * Note on Temperature: the temperature value needs to be converted to give the real temperature
4047
 * the formula is: 1.13 * reading - 113.0
4048
 * Note on Voltage: the voltage value needs to be converted to give the real voltage
4049
 * the formula is: 0.0057 * reading + 2.3
4050
 *
4051
 * NB: To correctly read the temperature this read should be done with xtal clock
4052
 * however that means that the receiver will be switched off, if receiver needs to be on then
4053
 * the timer is used to make sure the value is stable before reading
4054
 *
4055
 * input parameters:
4056
 * @param fastSPI - set to 1 if SPI rate > than 3MHz is used
4057
 *
4058
 * output parameters
4059
 *
4060
 * returns  (temp_raw<<8)|(vbat_raw)
4061
 */
4062
uint16_t dwt_readtempvbat(uint8_t fastSPI)
4063
{
4064
    uint8_t wr_buf[2];
4065
    uint8_t vbat_raw;
4066
    uint8_t temp_raw;
4067

    
4068
    // These writes should be single writes and in sequence
4069
    wr_buf[0] = 0x80; // Enable TLD Bias
4070
    dwt_writetodevice(RF_CONF_ID,0x11,1,wr_buf);
4071

    
4072
    wr_buf[0] = 0x0A; // Enable TLD Bias and ADC Bias
4073
    dwt_writetodevice(RF_CONF_ID,0x12,1,wr_buf);
4074

    
4075
    wr_buf[0] = 0x0f; // Enable Outputs (only after Biases are up and running)
4076
    dwt_writetodevice(RF_CONF_ID,0x12,1,wr_buf);    //
4077

    
4078
    // Reading All SAR inputs
4079
    wr_buf[0] = 0x00;
4080
    dwt_writetodevice(TX_CAL_ID, TC_SARL_SAR_C,1,wr_buf);
4081
    wr_buf[0] = 0x01; // Set SAR enable
4082
    dwt_writetodevice(TX_CAL_ID, TC_SARL_SAR_C,1,wr_buf);
4083

    
4084
    if(fastSPI == 1)
4085
    {
4086
        deca_sleep(1); // If using PLL clocks(and fast SPI rate) then this sleep is needed
4087
        // Read voltage and temperature.
4088
        dwt_readfromdevice(TX_CAL_ID, TC_SARL_SAR_LVBAT_OFFSET,2,wr_buf);
4089
    }
4090
    else //change to a slow clock
4091
    {
4092
        _dwt_enableclocks(FORCE_SYS_XTI); // NOTE: set system clock to XTI - this is necessary to make sure the values read are reliable
4093
        // Read voltage and temperature.
4094
        dwt_readfromdevice(TX_CAL_ID, TC_SARL_SAR_LVBAT_OFFSET,2,wr_buf);
4095
        // Default clocks (ENABLE_ALL_SEQ)
4096
        _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing
4097
    }
4098

    
4099
    vbat_raw = wr_buf[0];
4100
    temp_raw = wr_buf[1];
4101

    
4102
    wr_buf[0] = 0x00; // Clear SAR enable
4103
    dwt_writetodevice(TX_CAL_ID, TC_SARL_SAR_C,1,wr_buf);
4104

    
4105
    return ((temp_raw<<8)|(vbat_raw));
4106
}
4107

    
4108
/*! ------------------------------------------------------------------------------------------------------------------
4109
 * @fn dwt_readwakeuptemp()
4110
 *
4111
 * @brief this function reads the temperature of the DW1000 that was sampled
4112
 * on waking from Sleep/Deepsleep. They are not current values, but read on last
4113
 * wakeup if DWT_TANDV bit is set in mode parameter of dwt_configuresleep
4114
 *
4115
 * input parameters:
4116
 *
4117
 * output parameters:
4118
 *
4119
 * returns: 8-bit raw temperature sensor value
4120
 */
4121
uint8_t dwt_readwakeuptemp(void)
4122
{
4123
    return dwt_read8bitoffsetreg(TX_CAL_ID, TC_SARL_SAR_LTEMP_OFFSET);
4124
}
4125

    
4126
/*! ------------------------------------------------------------------------------------------------------------------
4127
 * @fn dwt_readwakeupvbat()
4128
 *
4129
 * @brief this function reads the battery voltage of the DW1000 that was sampled
4130
 * on waking from Sleep/Deepsleep. They are not current values, but read on last
4131
 * wakeup if DWT_TANDV bit is set in mode parameter of dwt_configuresleep
4132
 *
4133
 * input parameters:
4134
 *
4135
 * output parameters:
4136
 *
4137
 * returns: 8-bit raw battery voltage sensor value
4138
 */
4139
uint8_t dwt_readwakeupvbat(void)
4140
{
4141
    return dwt_read8bitoffsetreg(TX_CAL_ID, TC_SARL_SAR_LVBAT_OFFSET);
4142
}
4143

    
4144
/*! ------------------------------------------------------------------------------------------------------------------
4145
 * @fn dwt_calcbandwidthtempadj()
4146
 *
4147
 * @brief this function determines the corrected bandwidth setting (PG_DELAY register setting)
4148
 * of the DW1000 which changes over temperature.
4149
 *
4150
 * input parameters:
4151
 * @param target_count - uint16_t - the PG count target to reach in order to correct the bandwidth
4152
 *
4153
 * output parameters:
4154
 *
4155
 * returns: (uint32) The setting to be programmed into the PG_DELAY value
4156
 */
4157
uint32_t dwt_calcbandwidthtempadj(uint16_t target_count)
4158
{
4159
    int i;
4160
    uint32_t bit_field, curr_bw;
4161
    int32_t delta_count = 0;
4162
    uint32_t best_bw = 0;
4163
    uint16_t raw_count = 0;
4164
    int32_t delta_lowest;
4165

    
4166
    // Used to store the current values of the registers so that they can be restored after
4167
    uint8_t old_pmsc_ctrl0;
4168
    uint16_t old_pmsc_ctrl1;
4169
    uint32_t old_rf_conf_txpow_mask;
4170

    
4171
    // Record the current values of these registers, to restore later
4172
    old_pmsc_ctrl0 = dwt_read8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET);
4173
    old_pmsc_ctrl1 = dwt_read16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET);
4174
    old_rf_conf_txpow_mask = dwt_read32bitreg(RF_CONF_ID);
4175

    
4176
    //  Set clock to XTAL
4177
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, PMSC_CTRL0_SYSCLKS_19M);
4178

    
4179
    //  Disable sequencing
4180
    dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, PMSC_CTRL1_PKTSEQ_DISABLE);
4181

    
4182
    //  Turn on CLK PLL, Mix Bias and PG
4183
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXPOW_MASK | RF_CONF_PGMIXBIASEN_MASK);
4184

    
4185
    //  Set sys and TX clock to PLL
4186
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, PMSC_CTRL0_SYSCLKS_125M | PMSC_CTRL0_TXCLKS_125M);
4187

    
4188
    // Set the MSB high for first guess
4189
    curr_bw = 0x80;
4190
    // Set starting bit
4191
    bit_field = 0x80;
4192
    // Initial lowest delta is the maximum difference that we should allow the count value to be from the target.
4193
    // If the algorithm is successful, it will be overwritten by a smaller value where the count value is closer
4194
    // to the target
4195
    delta_lowest = 300;
4196

    
4197
    for (i = 0; i < 7; i++)
4198
    {
4199
        // start with 0xc0 and test.
4200
        bit_field = bit_field >> 1;
4201
        curr_bw = curr_bw | bit_field;
4202

    
4203
        // Write bw setting to PG_DELAY register
4204
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGDELAY_OFFSET, curr_bw);
4205

    
4206
        // Set cal direction and time
4207
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGCCTRL_OFFSET, TC_PGCCTRL_DIR_CONV | TC_PGCCTRL_TMEAS_MASK);
4208

    
4209
        // Start cal
4210
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGCCTRL_OFFSET, TC_PGCCTRL_DIR_CONV | TC_PGCCTRL_TMEAS_MASK | TC_PGCCTRL_CALSTART);
4211
        // Allow cal to complete
4212
        deca_sleep(100);
4213

    
4214
        // Read count value from the PG cal block
4215
        raw_count = dwt_read16bitoffsetreg(TX_CAL_ID, TC_PGCAL_STATUS_OFFSET) & TC_PGCAL_STATUS_DELAY_MASK;
4216

    
4217
        // lets keep track of the closest value to the target in case we overshoot
4218
        delta_count = abs((int)raw_count - (int)target_count);
4219
        if (delta_count < delta_lowest)
4220
        {
4221
            delta_lowest = delta_count;
4222
            best_bw = curr_bw;
4223
        }
4224

    
4225
        // Test the count results
4226
        if (raw_count > target_count)
4227
            // Count was lower, BW was lower so increase PG DELAY
4228
            curr_bw = curr_bw | bit_field;
4229
        else
4230
            // Count was higher
4231
            curr_bw = curr_bw & (~(bit_field));
4232
    }
4233

    
4234
    // Restore old register values
4235
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, old_pmsc_ctrl0);
4236
    dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, old_pmsc_ctrl1);
4237
    dwt_write32bitreg(RF_CONF_ID, old_rf_conf_txpow_mask);
4238

    
4239
    // Returns the best PG_DELAY setting
4240
    return best_bw;
4241
}
4242

    
4243

    
4244
/*! ------------------------------------------------------------------------------------------------------------------
4245
 * @fn _dwt_computetxpowersetting()
4246
 *
4247
 * @brief this function calculates the appropriate change to the TX_POWER register to compensate
4248
 * the TX power output at different temperatures.
4249
 *
4250
 * input parameters:
4251
 * @param ref_powerreg - uint32_t - the TX_POWER register value recorded when reference measurements were made
4252
 * @param power_adj - uint32_t - the adjustment in power level to be made, in 0.5dB steps
4253
 *
4254
 * output parameters:
4255
 *
4256
 * returns: (uint32) The setting to be programmed into the TX_POWER register
4257
 */
4258
uint32_t _dwt_computetxpowersetting(uint32_t ref_powerreg, int32_t power_adj)
4259
{
4260
    int32_t da_attn_change, mixer_gain_change;
4261
    uint8_t current_da_attn, current_mixer_gain;
4262
    uint8_t new_da_attn, new_mixer_gain;
4263
    uint32_t new_regval = 0;
4264
    int i;
4265

    
4266
    for(i = 0; i < 4; i++)
4267
    {
4268
        da_attn_change = 0;
4269
        mixer_gain_change = power_adj;
4270
        current_da_attn = ((ref_powerreg >> (i*8)) & 0xE0) >> 5;
4271
        current_mixer_gain = (ref_powerreg >> (i*8)) & 0x1F;
4272

    
4273
        // Mixer gain gives best performance between 4 and 20
4274
        while((current_mixer_gain + mixer_gain_change < 4) ||
4275
              (current_mixer_gain + mixer_gain_change > 20))
4276
        {
4277
            // If mixer gain goes outside bounds, adjust the DA attenuation to compensate
4278
            if(current_mixer_gain + mixer_gain_change > 20)
4279
            {
4280
                da_attn_change += 1;
4281
                mixer_gain_change -= (int) (DA_ATTN_STEP / MIXER_GAIN_STEP);
4282
            }
4283
            else if(current_mixer_gain + mixer_gain_change < 4)
4284
            {
4285
                da_attn_change += 1;
4286
                mixer_gain_change += (int) (DA_ATTN_STEP / MIXER_GAIN_STEP);
4287
            }
4288
        }
4289

    
4290
        new_da_attn = current_da_attn + da_attn_change;
4291
        new_mixer_gain = current_mixer_gain + mixer_gain_change;
4292

    
4293
        new_regval |= ((uint32_t) ((new_da_attn << 5) | new_mixer_gain)) << (i * 8);
4294
    }
4295

    
4296
    return (uint32_t)new_regval;
4297
}
4298

    
4299
/*! ------------------------------------------------------------------------------------------------------------------
4300
 * @fn dwt_calcpowertempadj()
4301
 *
4302
 * @brief this function determines the corrected power setting (TX_POWER setting) for the
4303
 * DW1000 which changes over temperature.
4304
 *
4305
 * input parameters:
4306
 * @param channel - uint8_t - the channel at which compensation of power level will be applied
4307
 * @param ref_powerreg - uint32_t - the TX_POWER register value recorded when reference measurements were made
4308
 * @param current_temperature - double - the current ambient temperature in degrees Celcius
4309
 * @param reference_temperature - double - the temperature at which reference measurements were made
4310
 * output parameters: None
4311
 *
4312
 * returns: (uint32) The corrected TX_POWER register value
4313
 */
4314
 uint32_t dwt_calcpowertempadj
4315
(
4316
       uint8_t channel,
4317
       uint32_t ref_powerreg,
4318
       double curr_temp,
4319
       double ref_temp
4320
)
4321
{
4322
    double delta_temp;
4323
    double delta_power;
4324

    
4325
    // Find the temperature differential
4326
    delta_temp = curr_temp - ref_temp;
4327

    
4328
    // Calculate the expected power differential at the current temperature
4329
    delta_power = delta_temp * txpwr_compensation[chan_idx[channel]];
4330

    
4331
    // Adjust the TX_POWER register value
4332
    return _dwt_computetxpowersetting(ref_powerreg, (int32_t)(delta_power / MIXER_GAIN_STEP));
4333
}
4334

    
4335
/*! ------------------------------------------------------------------------------------------------------------------
4336
 * @fn dwt_calcpgcount()
4337
 *
4338
 * @brief this function calculates the value in the pulse generator counter register (PGC_STATUS) for a given PG_DELAY
4339
 * This is used to take a reference measurement, and the value recorded as the reference is used to adjust the
4340
 * bandwidth of the device when the temperature changes.
4341
 *
4342
 * input parameters:
4343
 * @param pgdly - uint8_t - the PG_DELAY to set (to control bandwidth), and to find the corresponding count value for
4344
 * output parameters: None
4345
 *
4346
 * returns: (uint16) PGC_STATUS count value calculated from the provided PG_DELAY value - used as reference for later
4347
 * bandwidth adjustments
4348
 */
4349
uint16_t dwt_calcpgcount(uint8_t pgdly)
4350
{
4351
    // Perform PG count read ten times and take an average to smooth out any noise
4352
    const int NUM_SAMPLES = 10;
4353
    uint32_t sum_count = 0;
4354
    uint16_t average_count = 0, count = 0;
4355
    int i = 0;
4356

    
4357
    // Used to store the current values of the registers so that they can be restored after
4358
    uint8_t old_pmsc_ctrl0;
4359
    uint16_t old_pmsc_ctrl1;
4360
    uint32_t old_rf_conf_txpow_mask;
4361

    
4362
    // Record the current values of these registers, to restore later
4363
    old_pmsc_ctrl0 = dwt_read8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET);
4364
    old_pmsc_ctrl1 = dwt_read16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET);
4365
    old_rf_conf_txpow_mask = dwt_read32bitreg(RF_CONF_ID);
4366

    
4367
    //  Set clock to XTAL
4368
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, PMSC_CTRL0_SYSCLKS_19M);
4369
    //  Disable sequencing
4370
    dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, PMSC_CTRL1_PKTSEQ_DISABLE);
4371
    //  Turn on CLK PLL, Mix Bias and PG
4372
    dwt_write32bitreg(RF_CONF_ID, RF_CONF_TXPOW_MASK | RF_CONF_PGMIXBIASEN_MASK);
4373
    //  Set sys and TX clock to PLL
4374
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, PMSC_CTRL0_SYSCLKS_125M | PMSC_CTRL0_TXCLKS_125M);
4375

    
4376
    for(i = 0; i < NUM_SAMPLES; i++) {
4377
        // Write bw setting to PG_DELAY register
4378
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGDELAY_OFFSET, pgdly);
4379

    
4380
        // Set cal direction and time
4381
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGCCTRL_OFFSET, TC_PGCCTRL_DIR_CONV | TC_PGCCTRL_TMEAS_MASK);
4382

    
4383
        // Start cal
4384
        dwt_write8bitoffsetreg(TX_CAL_ID, TC_PGCCTRL_OFFSET, TC_PGCCTRL_DIR_CONV | TC_PGCCTRL_TMEAS_MASK | TC_PGCCTRL_CALSTART);
4385

    
4386
        // Allow cal to complete - the TC_PGCCTRL_CALSTART bit will clear automatically
4387
        deca_sleep(100);
4388

    
4389
        // Read count value from the PG cal block
4390
        count = dwt_read16bitoffsetreg(TX_CAL_ID, TC_PGCAL_STATUS_OFFSET) & TC_PGCAL_STATUS_DELAY_MASK;
4391

    
4392
        sum_count += count;
4393
    }
4394

    
4395
     // Restore old register values
4396
    dwt_write8bitoffsetreg(PMSC_ID, PMSC_CTRL0_OFFSET, old_pmsc_ctrl0);
4397
    dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET, old_pmsc_ctrl1);
4398
    dwt_write32bitreg(RF_CONF_ID, old_rf_conf_txpow_mask);
4399

    
4400
    average_count = (int)(sum_count / NUM_SAMPLES);
4401
    return average_count;
4402
}
4403

    
4404

    
4405
/* ===============================================================================================
4406
   List of expected (known) device ID handled by this software
4407
   ===============================================================================================
4408

4409
    0xDECA0130                               // DW1000 - MP
4410

4411
   ===============================================================================================
4412
*/
4413

    
4414
/****************************************************************************************************************************************************
4415
 *
4416
 * Declaration of platform-dependent lower level functions.
4417
 *
4418
 ****************************************************************************************************************************************************/
4419

    
4420
/****************************************************************************//**
4421
 *
4422
 *         alld_dw1000.c                                        SPI Section
4423
 *
4424
 *******************************************************************************/
4425

    
4426
/*! ------------------------------------------------------------------------------------------------------------------
4427
 * Function: writetospi()
4428
 *
4429
 * Low level abstract function for DW1000 to write to the SPI
4430
 * Takes two separate byte buffers for write header and write data
4431
 * returns 0 for success, or -1 for error
4432
 */
4433
#pragma GCC optimize ("O3")
4434
static int writetospi(uint16_t headerLength,
4435
               const        uint8_t *headerBuffer,
4436
               uint32_t bodyLength,
4437
               const        uint8_t *bodyBuffer)
4438
{
4439

    
4440
    uint8_t buffer[bodyLength + 3];
4441
    memcpy(buffer, headerBuffer, headerLength); //copy data to buffer
4442
    memcpy(&buffer[headerLength], bodyBuffer, bodyLength); //copy data to buffer
4443

    
4444
    apalSPITransmit(&MODULE_HAL_SPI_UWB,
4445
                    buffer,
4446
                    bodyLength + headerLength); // send header and data
4447

    
4448
    return 0;
4449
} // end writetospi()
4450

    
4451

    
4452
/*! ------------------------------------------------------------------------------------------------------------------
4453
 * Function: readfromspi()
4454
 *
4455
 * Low level abstract function for DW1000 to read from the SPI
4456
 * Takes two separate byte buffers for write header and read data
4457
 * returns the offset into read buffer where first byte of read data may be found,
4458
 * or returns -1 if there was an error
4459
 */
4460
#pragma GCC optimize ("O3")
4461
static int readfromspi(uint16_t headerLength,
4462
                const uint8_t *headerBuffer,
4463
                uint32_t readlength,
4464
                uint8_t *readBuffer)
4465
{
4466

    
4467
    apalSPITransmitAndReceive(&MODULE_HAL_SPI_UWB, // TODO: "pdw1000local->driver->spid" fails two spi configs
4468
                              headerBuffer,
4469
                              readBuffer,
4470
                              headerLength,
4471
                              readlength);
4472

    
4473
    return 0;
4474
} // end readfromspi()
4475

    
4476
/****************************************************************************//**
4477
 *
4478
 *         alld_dw1000.c                                        IRQ section
4479
 *
4480
 *******************************************************************************/
4481

    
4482

    
4483
/*! ------------------------------------------------------------------------------------------------------------------
4484
 * Function: decamutexon()
4485
 *
4486
 * Description: This function should disable interrupts. This is called at the start of a critical section
4487
 * It returns the irq state before disable, this value is used to re-enable in decamutexoff call
4488
 *
4489
 * Note: The body of this function is platform specific
4490
 *
4491
 * input parameters:        
4492
 *
4493
 * output parameters
4494
 *
4495
 * returns the state of the DW1000 interrupt
4496
 */
4497
decaIrqStatus_t decamutexon(void)
4498
{
4499

    
4500
  decaIrqStatus_t s = port_GetEXT_IRQStatus();
4501
  if(s) {
4502
    port_DisableEXT_IRQ(); //disable the external interrupt line
4503
  }
4504
  return s ;   // return state before disable, value is used to re-enable in decamutexoff call
4505
}
4506

    
4507
/*! ------------------------------------------------------------------------------------------------------------------
4508
 * Function: decamutexoff()
4509
 *
4510
 * Description: This function should re-enable interrupts, or at least restore their state as returned(&saved) by decamutexon 
4511
 * This is called at the end of a critical section
4512
 *
4513
 * Note: The body of this function is platform specific
4514
 *
4515
 * input parameters:        
4516
 * @param s - the state of the DW1000 interrupt as returned by decamutexon
4517
 *
4518
 * output parameters
4519
 *
4520
 * returns the state of the DW1000 interrupt
4521
 */
4522
void decamutexoff(decaIrqStatus_t s)
4523
{
4524
//  (void) s;
4525
  if(s) { //need to check the port state as we can't use level sensitive interrupt on the STM ARM
4526
    port_EnableEXT_IRQ();
4527
  }
4528
  return;
4529
}
4530

    
4531

    
4532
/*! Wrapper function to be used by decadriver. Declared in deca_device_api.h 
4533
 *
4534
 */
4535

    
4536
void deca_sleep(unsigned int time_ms)
4537
{
4538
  aosThdMSleep(time_ms);
4539
}
4540

    
4541
void Sleep(unsigned int time_ms)
4542
{
4543
  aosThdMSleep(time_ms);
4544
}
4545

    
4546

    
4547
void port_wakeup_dw1000_fast(){ // NOT SUPPORTED
4548
  return;
4549
}
4550

    
4551
uint32_t portGetTickCnt(){
4552
  return chVTGetSystemTimeX();
4553
}
4554

    
4555
//inline uint32_t portGetTickCnt(){
4556
//    return (uint32_t) chVTGetSystemTimeX();
4557
//}
4558

    
4559

    
4560
void port_DisableEXT_IRQ(void){   
4561
  nvicDisableVector(DW1000_EXTI_IRQn);
4562

    
4563
}
4564

    
4565
void port_EnableEXT_IRQ(void){    
4566
  nvicEnableVector(DW1000_EXTI_IRQn, STM32_IRQ_EXTI10_15_PRIORITY);
4567
}
4568

    
4569

    
4570
decaIrqStatus_t port_GetEXT_IRQStatus(void){
4571
  decaIrqStatus_t bitstatus = RESET;
4572

    
4573
  if(NVIC_GetActive(DW1000_EXTI_IRQn)|| NVIC_GetPendingIRQ(DW1000_EXTI_IRQn)){
4574
    //  if(NVIC_GetPendingIRQ(EXTI15_10_IRQn)){ //if the interrupt is pending (background )
4575
    bitstatus = SET; //Interrupt is active or panding
4576
  }
4577
  else {
4578
    bitstatus = RESET; //No interrupt IRQ at the moment
4579
  }
4580

    
4581
  return bitstatus;
4582
}
4583

    
4584
#endif /* defined(AMIROLLD_CFG_DW1000) && (AMIROLLD_CFG_DW1000 == 1) */