Statistics
| Branch: | Tag: | Revision:

amiro-lld / drivers / DW1000 / v2 / decadriver / deca_device.c @ 99ca7610

History | View | Annotate | Download (142.18 KB)

1 22401187 Thomas Schöpping
/*! ------------------------------------------------------------------------------------------------------------------
2
 * @file    deca_device.c
3
 * @brief   Decawave device configuration and control functions
4
 *
5
 * @attention
6
 *
7
 * Copyright 2013 (c) Decawave Ltd, Dublin, Ireland.
8
 *
9
 * All rights reserved.
10
 *
11
 */
12
13
#include <assert.h>
14
#include <stdlib.h>
15
16
#include "deca_types.h"
17
#include "deca_param_types.h"
18
#include "deca_regs.h"
19
#include "deca_device_api.h"
20
21
// Defines for enable_clocks function
22
#define FORCE_SYS_XTI  0
23
#define ENABLE_ALL_SEQ 1
24
#define FORCE_SYS_PLL  2
25
#define READ_ACC_ON    7
26
#define READ_ACC_OFF   8
27
#define FORCE_OTP_ON   11
28
#define FORCE_OTP_OFF  12
29
#define FORCE_TX_PLL   13
30
#define FORCE_LDE      14
31
32
// Defines for ACK request bitmask in DATA and MAC COMMAND frame control (first byte) - Used to detect AAT bit wrongly set.
33
#define FCTRL_ACK_REQ_MASK 0x20
34
// Frame control maximum length in bytes.
35
#define FCTRL_LEN_MAX 2
36
37
// #define DWT_API_ERROR_CHECK     // define so API checks config input parameters
38
39
// -------------------------------------------------------------------------------------------------------------------
40
//
41
// Internal functions for controlling and configuring the device
42
//
43
// -------------------------------------------------------------------------------------------------------------------
44
45
// Enable and Configure specified clocks
46
void _dwt_enableclocks(int clocks) ;
47
// Configure the ucode (FP algorithm) parameters
48
void _dwt_configlde(int prf);
49
// Load ucode from OTP/ROM
50
void _dwt_loaducodefromrom(void);
51
// Read non-volatile memory
52
uint32 _dwt_otpread(uint16 address);
53
// Program the non-volatile memory
54
uint32 _dwt_otpprogword32(uint32 data, uint16 address);
55
// Upload the device configuration into always on memory
56
void _dwt_aonarrayupload(void);
57
// -------------------------------------------------------------------------------------------------------------------
58
59
/*!
60
 * Static data for DW1000 DecaWave Transceiver control
61
 */
62
63
// -------------------------------------------------------------------------------------------------------------------
64
// Structure to hold device data
65
typedef struct
66
{
67
    uint32      partID ;            // IC Part ID - read during initialisation
68
    uint32      lotID ;             // IC Lot ID - read during initialisation
69
    uint8       vBatP ;             // IC V bat read during production and stored in OTP (Vmeas @ 3V3)
70
    uint8       tempP ;             // IC V temp read during production and stored in OTP (Tmeas @ 23C)
71
    uint8       longFrames ;        // Flag in non-standard long frame mode
72
    uint8       otprev ;            // OTP revision number (read during initialisation)
73
    uint32      txFCTRL ;           // Keep TX_FCTRL register config
74
    uint32      sysCFGreg ;         // Local copy of system config register
75
    uint8       dblbuffon;          // Double RX buffer mode flag
76
    uint8       wait4resp ;         // wait4response was set with last TX start command
77
    uint16      sleep_mode;         // Used for automatic reloading of LDO tune and microcode at wake-up
78
    uint16      otp_mask ;          // Local copy of the OTP mask used in dwt_initialise call
79
    dwt_cb_data_t cbData;           // Callback data structure
80
    dwt_cb_t    cbTxDone;           // Callback for TX confirmation event
81
    dwt_cb_t    cbRxOk;             // Callback for RX good frame event
82
    dwt_cb_t    cbRxTo;             // Callback for RX timeout events
83
    dwt_cb_t    cbRxErr;            // Callback for RX error events
84
} dwt_local_data_t ;
85
86
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
87
static dwt_local_data_t *pdw1000local = dw1000local ; // Static local data structure pointer
88
89
90
/*! ------------------------------------------------------------------------------------------------------------------
91
 * @fn dwt_apiversion()
92
 *
93
 * @brief This function returns the version of the API as defined by DW1000_DRIVER_VERSION
94
 *
95
 * input parameters
96
 *
97
 * output parameters
98
 *
99
 * returns version (DW1000_DRIVER_VERSION)
100
 */
101
int32 dwt_apiversion(void)
102
{
103
    return DW1000_DRIVER_VERSION ;
104
}
105
106
/*! ------------------------------------------------------------------------------------------------------------------
107
 * @fn dwt_setlocaldataptr()
108
 *
109
 * @brief This function sets the local data structure pointer to point to the element in the local array as given by the index.
110
 *
111
 * input parameters
112
 * @param index    - selects the array element to point to. Must be within the array bounds, i.e. < DWT_NUM_DW_DEV
113
 *
114
 * output parameters
115
 *
116
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
117
 */
118
int dwt_setlocaldataptr(unsigned int index)
119
{
120
    // Check the index is within the array bounds
121
    if (DWT_NUM_DW_DEV <= index) // return error if index outside the array bounds
122
    {
123
        return DWT_ERROR ;
124
    }
125
126
    pdw1000local = &dw1000local[index];
127
128
    return DWT_SUCCESS ;
129
}
130
131
/*! ------------------------------------------------------------------------------------------------------------------
132
 * @fn dwt_initialise()
133
 *
134
 * @brief This function initiates communications with the DW1000 transceiver
135
 * and reads its DEV_ID register (address 0x00) to verify the IC is one supported
136
 * by this software (e.g. DW1000 32-bit device ID value is 0xDECA0130).  Then it
137
 * does any initial once only device configurations needed for its use and initialises
138
 * as necessary any static data items belonging to this low-level driver.
139
 *
140
 * This function does not need to be called after DW1000 device is woken up from DEEPSLEEP,
141
 * the device will preserve register values e.g. LDO, UCODE, XTAL. However if needed this
142
 * function can be called to initialise internal structure  dw1000local[] if it has not been preserved
143
 * (e.g. if micro was in sleep and its RAM data (containing dw1000local structure was not preserved during sleep)
144
 *
145
 * NOTES:
146
 * 1. When DW1000 is powered on this function needs to be run before dwt_configuresleep,
147
 *    also the SPI frequency has to be < 3MHz
148
 * 2. It reads and applies LDO tune and crystal trim values from OTP memory
149
 * 3. If accurate RX timestamping is needed microcode/LDE must be loaded
150
 *
151
 * input parameters
152
 * @param config    -   specifies what configuration to load
153
 *                  DWT_LOADNONE         0x00 - do not load any values from OTP memory
154
 *                  DWT_LOADUCODE        0x01 - load the LDE microcode from ROM - enable accurate RX timestamp
155
 *                  DWT_DW_WAKE_UP       0x02 - just initialise dw1000local[] values (e.g. DW1000 has woken up)
156
 *                  DWT_DW_WUP_NO_UCODE  0x04 - if microcode/LDE algorithm has not already been loaded (on power up) e.g. when LDE is not used
157
 *                  DWT_READ_OTP_PID     0x10 - read part ID from OTP
158
 *                  DWT_READ_OTP_LID     0x20 - read lot ID from OTP
159
 *                  DWT_READ_OTP_BAT     0x40 - read ref voltage from OTP
160
 *                  DWT_READ_OTP_TMP     0x80 - read ref temperature from OTP
161
 * output parameters
162
 *
163
 * returns DWT_SUCCESS for success, or DWT_ERROR for error
164
 */
165
// OTP addresses definitions
166
#define LDOTUNE_ADDRESS (0x04)
167
#define PARTID_ADDRESS (0x06)
168
#define LOTID_ADDRESS  (0x07)
169
#define VBAT_ADDRESS   (0x08)
170
#define VTEMP_ADDRESS  (0x09)
171
#define XTRIM_ADDRESS  (0x1E)
172
173
int dwt_initialise(int config)
174
{
175
    uint16 otp_xtaltrim_and_rev = 0;
176
    uint32 ldo_tune = 0;
177
178
    pdw1000local->dblbuffon = 0; // - set to 0 - meaning double buffer mode is off by default
179
    pdw1000local->wait4resp = 0; // - set to 0 - meaning wait for response not active
180
    pdw1000local->sleep_mode = 0; // - set to 0 - meaning sleep mode has not been configured
181
182
    pdw1000local->cbTxDone = NULL;
183
    pdw1000local->cbRxOk = NULL;
184
    pdw1000local->cbRxTo = NULL;
185
    pdw1000local->cbRxErr = NULL;
186
187
#if DWT_API_ERROR_CHECK
188
    pdw1000local->otp_mask = config ; // Save the READ_OTP config mask
189
#endif
190
191
    // Read and validate device ID, return -1 if not recognised
192
    if (DWT_DEVICE_ID != dwt_readdevid()) // MP IC ONLY (i.e. DW1000) FOR THIS CODE
193
    {
194
        return DWT_ERROR ;
195
    }
196
197
    if(!(DWT_DW_WAKE_UP & config)) // Don't reset the device if DWT_DW_WAKE_UP bit is set, e.g. when calling this API after wake up
198
    {
199
        dwt_softreset(); // Make sure the device is completely reset before starting initialisation
200
    }
201
202
    if(!((DWT_DW_WAKE_UP & config) && ((DWT_READ_OTP_TMP | DWT_READ_OTP_BAT | DWT_READ_OTP_LID | DWT_READ_OTP_PID | DWT_DW_WUP_RD_OTPREV)& config)))
203
    {
204
        _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
205
    }                                  // when not reading from OTP, clocks don't need to change.
206
207
    // Configure the CPLL lock detect
208
    dwt_write8bitoffsetreg(EXT_SYNC_ID, EC_CTRL_OFFSET, EC_CTRL_PLLLCK);
209
210
    // When DW1000 IC is initialised from power up, then the LDO value should be kicked from OTP, otherwise if this API is called after
211
    // DW1000 IC has been woken up (DWT_DW_WAKE_UP bit is set) this can be skipped as LDO would have already been automatically
212
    // kicked/loaded on wake up
213
    if(!(DWT_DW_WAKE_UP & config))
214
    {
215
        // Load LDO tune from OTP and kick it if there is a value actually programmed.
216
        ldo_tune = _dwt_otpread(LDOTUNE_ADDRESS);
217
        if((ldo_tune & 0xFF) != 0)
218
        {
219
            // Kick LDO tune
220
            dwt_write8bitoffsetreg(OTP_IF_ID, OTP_SF, OTP_SF_LDO_KICK); // Set load LDO kick bit
221
            pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDO; // LDO tune must be kicked at wake-up
222
        }
223
    }
224
    else
225
    {   //if LDOTUNE reg contains value different from default it means it was kicked from OTP and thus set AON_WCFG_ONW_LLDO.
226
        if(dwt_read32bitoffsetreg(RF_CONF_ID, LDOTUNE) != LDOTUNE_DEFAULT)
227
            pdw1000local->sleep_mode |= AON_WCFG_ONW_LLDO;
228
    }
229
230
    if((!(DWT_DW_WAKE_UP & config)) || ((DWT_DW_WAKE_UP & config) && (DWT_DW_WUP_RD_OTPREV & config)))
231
    {
232
        // Read OTP revision number
233
        otp_xtaltrim_and_rev = _dwt_otpread(XTRIM_ADDRESS) & 0xffff;        // Read 32 bit value, XTAL trim val is in low octet-0 (5 bits)
234
        pdw1000local->otprev = (otp_xtaltrim_and_rev >> 8) & 0xff;          // OTP revision is the next byte
235
    }
236
    else
237
        pdw1000local->otprev = 0; // If OTP valuse are not used, if this API is called after DW1000 IC has been woken up
238
                                  // (DWT_DW_WAKE_UP bit is set), set otprev to 0
239