Statistics
| Branch: | Tag: | Revision:

amiro-os / unittests / periphery-lld / src / ut_alld_dw1000_v1.c @ 55a84503

History | View | Annotate | Download (11.544 KB)

1 d3710331 Cung Sang
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3
Copyright (C) 2016..2019  Thomas Schöpping et al.
4

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU 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 General Public License for more details.
14

15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#include <amiroos.h>
20
21
#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_DW1000) && (AMIROLLD_CFG_DW1000 == 1)) || defined(__DOXYGEN__)
22
23
#include <aos_debug.h>
24
#include <chprintf.h>
25
#include <aos_thread.h>
26
#include <math.h>
27
#include <module.h>
28
#include <alld_DW1000.h>
29
#include <v1/deca_instance_v1.h>
30
31
32
/******************************************************************************/
33
/* LOCAL DEFINITIONS                                                          */
34
/******************************************************************************/
35
36
//#define UNIT_TEST_SNIPPETS_DW1000   // switch between unit test and demo apps
37
38
#define SWS1_SHF_MODE 0x02  //short frame mode (6.81M)
39
#define SWS1_CH5_MODE 0x04  //channel 5 mode
40
#define SWS1_ANC_MODE 0x08  //anchor mode
41
#define SWS1_A1A_MODE 0x10  //anchor/tag address A1
42
#define SWS1_A2A_MODE 0x20  //anchor/tag address A2
43
#define SWS1_A3A_MODE 0x40  //anchor/tag address A3
44
45
#define S1_SWITCH_ON  (1)
46
#define S1_SWITCH_OFF (0)
47
48
/******************************************************************************/
49
/* EXPORTED VARIABLES                                                         */
50
/******************************************************************************/
51
52
/******************************************************************************/
53
/* LOCAL TYPES                                                                */
54
/******************************************************************************/
55
56
/******************************************************************************/
57
/* LOCAL VARIABLES                                                            */
58
/******************************************************************************/
59
uint8_t s1switch = 0;
60
int instance_anchaddr = 0;
61
int dr_mode = 0;
62
int chan, tagaddr, ancaddr;
63
int instance_mode = ANCHOR;
64
65
66
/******************************************************************************/
67
/* LOCAL FUNCTIONS                                                            */
68
/******************************************************************************/
69
70 7b6ab4bf Cung Sang
/*! @brief Change the SPI speed configuration on the fly */
71
void setHighSpeed_SPI(bool speedValue, DW1000Driver* drv){
72 d3710331 Cung Sang
73 7b6ab4bf Cung Sang
  spiStop(drv->spid);
74 d3710331 Cung Sang
75
  if (speedValue == FALSE){
76 7b6ab4bf Cung Sang
    spiStart(drv->spid, &moduleHalSpiUwbLsConfig);  // low speed spi configuration
77 d3710331 Cung Sang
  }
78
  else{
79 7b6ab4bf Cung Sang
    spiStart(drv->spid, &moduleHalSpiUwbHsConfig); // high speed spi configuration
80 d3710331 Cung Sang
  }
81
}
82
83 10b520a8 Cung Sang
/*! @brief entry point to the IRQn event in DW1000 module
84
 *
85
 * */
86
void process_deca_irq(void){
87
  do{
88
    dwt_isr();
89
    //while IRS line active (ARM can only do edge sensitive interrupts)
90
  }while(port_CheckEXT_IRQ() == 1);
91
}
92
93
/*! @brief Check the current value of GPIO pin and return the value */
94
apalGpioState_t port_CheckEXT_IRQ(void) {
95
  apalGpioState_t  val;
96
  apalGpioRead(moduleGpioDw1000Irqn.gpio, &val);
97
  return val;
98
}
99
100 d3710331 Cung Sang
/*! @brief Manually set the chip select pin of the SPI */
101 7b6ab4bf Cung Sang
void set_SPI_chip_select(void){
102 d3710331 Cung Sang
  apalGpioWrite(moduleGpioSpiChipSelect.gpio, APAL_GPIO_HIGH);
103
}
104
105
/*! @brief Manually reset the chip select pin of the SPI */
106 7b6ab4bf Cung Sang
void clear_SPI_chip_select(void){
107 d3710331 Cung Sang
  apalGpioWrite(moduleGpioSpiChipSelect.gpio, APAL_GPIO_LOW);
108
}
109
110
/*! @brief Manually reset the DW1000 module  */
111
void reset_DW1000(void){
112
113
  // Set the pin as output
114
  palSetPadMode(moduleGpioDw1000Reset.gpio->port, moduleGpioDw1000Reset.gpio->pad, APAL_GPIO_DIRECTION_OUTPUT);
115
116
  //drive the RSTn pin low
117
  apalGpioWrite(moduleGpioDw1000Reset.gpio, APAL_GPIO_LOW);
118
119
  //put the pin back to tri-state ... as input
120
//  palSetPadMode(moduleGpioDw1000Reset.gpio->port, moduleGpioDw1000Reset.gpio->pad, APAL_GPIO_DIRECTION_INPUT); // TODO:
121
122
  aosThdMSleep(2);
123
}
124
125 7b6ab4bf Cung Sang
/*! @brief Configure instance tag/anchor/etc... addresses */
126 d3710331 Cung Sang
void addressconfigure(uint8_t s1switch, uint8_t mode){
127
  uint16_t instAddress ;
128
129
  instance_anchaddr = (((s1switch & SWS1_A1A_MODE) << 2) + (s1switch & SWS1_A2A_MODE) + ((s1switch & SWS1_A3A_MODE) >> 2)) >> 4;
130
131
  if(mode == ANCHOR) {
132
    if(instance_anchaddr > 3) {
133
      instAddress = GATEWAY_ANCHOR_ADDR | 0x4 ; //listener
134
    }
135
    else {
136
      instAddress = GATEWAY_ANCHOR_ADDR | (uint16_t)instance_anchaddr;
137
    }
138
  }
139
  else{
140
    instAddress = (uint16_t)instance_anchaddr;
141
  }
142
143
  instancesetaddresses(instAddress);
144
}
145
146 7b6ab4bf Cung Sang
/*! @brief returns the use case / operational mode */
147 d3710331 Cung Sang
int decarangingmode(uint8_t s1switch){
148
  int mode = 0;
149
150
  if(s1switch & SWS1_SHF_MODE)  {
151
    mode = 1;
152
  }
153
154
  if(s1switch & SWS1_CH5_MODE) {
155
    mode = mode + 2;
156
  }
157
158
  return mode;
159
}
160
161 7b6ab4bf Cung Sang
/*! @brief Check connection setting and initialize DW1000 module */
162 10b520a8 Cung Sang
int32_t inittestapplication(uint8_t s1switch, DW1000Driver* drv){
163 d3710331 Cung Sang
  uint32_t devID ;
164
  int result;
165
166 7b6ab4bf Cung Sang
  setHighSpeed_SPI(FALSE, drv);          //low speed spi max. ~4M
167 d3710331 Cung Sang
  devID = instancereaddeviceid() ;
168
169
  if(DWT_DEVICE_ID != devID) {
170 7b6ab4bf Cung Sang
    clear_SPI_chip_select();
171 d3710331 Cung Sang
    Sleep(1);
172 7b6ab4bf Cung Sang
    set_SPI_chip_select();
173 d3710331 Cung Sang
    Sleep(7);
174
    devID = instancereaddeviceid() ;
175
    if(DWT_DEVICE_ID != devID){
176 7b6ab4bf Cung Sang
      return(-1) ;
177 d3710331 Cung Sang
    }    
178 7b6ab4bf Cung Sang
    dwt_softreset();
179 d3710331 Cung Sang
  }
180
181
    reset_DW1000();  //reset the DW1000 by driving the RSTn line low
182
183
  if((s1switch & SWS1_ANC_MODE) == 0){
184
    instance_mode = TAG;
185
  }
186
  else{
187
    instance_mode = ANCHOR;
188
  }
189
190 10b520a8 Cung Sang
  result = instance_init(drv) ;
191 d3710331 Cung Sang
192
  if (0 > result){
193
    return(-1) ;
194
  }
195
196 10b520a8 Cung Sang
  setHighSpeed_SPI(TRUE, drv);       // high speed spi max. ~ 20M
197 d3710331 Cung Sang
  devID = instancereaddeviceid() ;
198
199
  if (DWT_DEVICE_ID != devID){
200
    return(-1) ;
201
  }
202
203
  addressconfigure(s1switch, (uint8_t)instance_mode) ;
204
205
  if((instance_mode == ANCHOR) && (instance_anchaddr > 0x3)){
206
    instance_mode = LISTENER;
207
  }
208
209
  instancesetrole(instance_mode) ;       // Set this instance role
210
  dr_mode = decarangingmode(s1switch);
211
  chan = chConfig[dr_mode].channelNumber ;
212 7b6ab4bf Cung Sang
  instance_config(&chConfig[dr_mode], &sfConfig[dr_mode], drv) ;
213 d3710331 Cung Sang
214 10b520a8 Cung Sang
  return (int32_t)devID;
215 d3710331 Cung Sang
}
216
217 7b6ab4bf Cung Sang
/*! @brief Main Entry point to Initialization of UWB DW1000 configuration  */
218 d3710331 Cung Sang
#pragma GCC optimize ("O3")
219 7b6ab4bf Cung Sang
int UWB_Init(DW1000Driver* drv){
220 d3710331 Cung Sang
221
  /*! Software defined Configurartion for TAG, ANC, and other settings as needed */
222 7b6ab4bf Cung Sang
  s1switch = S1_SWITCH_OFF << 1  // (on = 6.8 Mbps, off = 110 kbps)
223
           | S1_SWITCH_OFF << 2  // (on = CH5, off = CH2)
224
           | S1_SWITCH_OFF << 3  // (on = Anchor, off = TAG)
225
           | S1_SWITCH_OFF << 4  // (configure Tag or anchor ID no.)
226
           | S1_SWITCH_OFF << 5  // (configure Tag or anchor ID no.)
227
           | S1_SWITCH_OFF << 6  // (configure Tag or anchor ID no.)
228
           | S1_SWITCH_OFF << 7; // Not use in this demo
229 d3710331 Cung Sang
230
231
  port_DisableEXT_IRQ();           //disable ScenSor IRQ until we configure the device
232
233 10b520a8 Cung Sang
  if(inittestapplication(s1switch, drv) == -1) {
234
    return (-1); //error
235 d3710331 Cung Sang
  }
236
237 10b520a8 Cung Sang
  aosThdMSleep(5);
238 d3710331 Cung Sang
239 10b520a8 Cung Sang
  port_EnableEXT_IRQ();  //enable DW1000 IRQ before starting
240 d3710331 Cung Sang
241
  return 0;
242
}
243
244
245
/******************************************************************************/
246
/* EXPORTED FUNCTIONS                                                         */
247
/******************************************************************************/
248
249
250
aos_utresult_t utAlldDw1000Func(BaseSequentialStream* stream, aos_unittest_t* ut) {
251
252
  aosDbgCheck(ut->data != NULL);
253
254
  aos_utresult_t result = {0, 0};
255
256 7b6ab4bf Cung Sang
  chprintf(stream, "init DW1000...\n");
257
  dwt_initialise(DWT_LOADUCODE, (DW1000Driver*) ut->data);
258
  aosThdMSleep(5);
259 d3710331 Cung Sang
260 7b6ab4bf Cung Sang
261
/*! Unit Test snippets for DW1000.
262 10b520a8 Cung Sang
 * @Note: Event IRQ for DW1000 should be tested separately
263 7b6ab4bf Cung Sang
 */
264 d3710331 Cung Sang
#ifdef UNIT_TEST_SNIPPETS_DW1000
265
266
  uint32_t actual_deviceId;
267
268
  port_DisableEXT_IRQ();
269
270 7b6ab4bf Cung Sang
  setHighSpeed_SPI(false, (DW1000Driver*) ut->data);
271 d3710331 Cung Sang
  chprintf(stream, "expected device ID (LS SPI): 0xDECA0130 \n");
272
  aosThdMSleep(5);
273
  actual_deviceId = instancereaddeviceid();
274
  chprintf(stream, "actual read ID: 0x%x\n", actual_deviceId);
275
  aosThdMSleep(5);
276
277 10b520a8 Cung Sang
  //if the read of device ID fails, the DW1000 could be asleep
278
  if(DWT_DEVICE_ID != actual_deviceId){
279
280
    clear_SPI_chip_select();
281
    aosThdMSleep(1);
282
    set_SPI_chip_select();
283 d3710331 Cung Sang
    aosThdMSleep(7);
284
    actual_deviceId = instancereaddeviceid() ;
285
286
    if(DWT_DEVICE_ID != actual_deviceId){
287 10b520a8 Cung Sang
      chprintf(stream, "SPI is not working or Unsupported Device ID\n");
288 d3710331 Cung Sang
      chprintf(stream, "actual device ID is: 0x%x\n", actual_deviceId);
289
      chprintf(stream, "expected device ID: 0xDECA0130 \n");
290
      aosThdMSleep(5);
291
    }
292
293
    //clear the sleep bit - so that after the hard reset below the DW does not go into sleep
294
    dwt_softreset();
295
  }
296
297 7b6ab4bf Cung Sang
  /*! UT1: Low speed SPI result */
298 d3710331 Cung Sang
  if (actual_deviceId == DWT_DEVICE_ID){
299
    aosUtPassed(stream, &result);
300
  } else {
301
    aosUtFailed(stream, &result);
302
  }
303
304 10b520a8 Cung Sang
  reset_DW1000();
305 d3710331 Cung Sang
306 10b520a8 Cung Sang
  chprintf(stream, "initialise instance for DW1000 \n");
307
  aosThdSleep(1);
308 d3710331 Cung Sang
309 10b520a8 Cung Sang
  int x_init = instance_init((DW1000Driver*) ut->data) ;
310 d3710331 Cung Sang
311
  if (0 != x_init){
312 10b520a8 Cung Sang
    chprintf(stream, "init error with return value: %d \n", x_init);
313
    aosThdSleep(1);
314 d3710331 Cung Sang
  }
315
  else {
316 10b520a8 Cung Sang
    chprintf(stream, "init success with return value: %d \n", x_init);
317
    aosThdSleep(1);
318 d3710331 Cung Sang
  }
319
320 7b6ab4bf Cung Sang
  /*! UT2: Initialization  result*/
321 d3710331 Cung Sang
  if (x_init == 0){
322
    aosUtPassed(stream, &result);
323
  } else {
324
    aosUtFailed(stream, &result);
325
  }
326
327 7b6ab4bf Cung Sang
  setHighSpeed_SPI(true, (DW1000Driver*) ut->data);
328 d3710331 Cung Sang
329
  chprintf(stream, "expected device ID (HS SPI): 0xDECA0130\n");
330
  actual_deviceId = instancereaddeviceid();
331
  chprintf(stream, "actual read ID: 0x%x\n", actual_deviceId);
332 10b520a8 Cung Sang
  aosThdMSleep(1);
333 d3710331 Cung Sang
334 7b6ab4bf Cung Sang
  /*! UT3: High speed SPI result*/
335 d3710331 Cung Sang
  if (actual_deviceId == DWT_DEVICE_ID){
336
    aosUtPassed(stream, &result);
337
  } else {
338
    aosUtFailed(stream, &result);
339
  }
340
341
  port_EnableEXT_IRQ();
342
  reset_DW1000();
343
344 10b520a8 Cung Sang
  chprintf(stream, "initialise the configuration for UWB application \n");
345
  aosThdSleep(1);
346 d3710331 Cung Sang
347 7b6ab4bf Cung Sang
  int uwb_init = UWB_Init((DW1000Driver*) ut->data);
348 d3710331 Cung Sang
349
  if (0 != uwb_init){
350
    chprintf(stream, "UWB config error with return value: %d \n", uwb_init);
351 10b520a8 Cung Sang
    aosThdSleep(1);
352 d3710331 Cung Sang
  }
353
  else {
354
    chprintf(stream, "UWB config success with return value: %d \n", uwb_init);
355 10b520a8 Cung Sang
    aosThdSleep(1);
356 d3710331 Cung Sang
  }
357
358 7b6ab4bf Cung Sang
  /*! UT4: UWB configuration result
359 d3710331 Cung Sang
   * If all the four unit tests are passed, the module is ready to run.
360
   * Note that the interrupt IRQn should be tested separately.
361
   */
362
  if (uwb_init == 0){
363
    aosUtPassed(stream, &result);
364
  } else {
365
    aosUtFailed(stream, &result);
366
  }
367
368
  /************** End of UNIT_TEST_SNIPPETS_DW1000*****************/
369
370
#else
371
372
373 10b520a8 Cung Sang
  /*! RUN THE STATE MACHINE DEMO APP (RTLS) */
374
375
  chprintf(stream, "initialise the State Machine \n");
376 d3710331 Cung Sang
  aosThdSleep(2);
377
378 7b6ab4bf Cung Sang
  /* Initialize UWB system with user defined configuration  */
379
  int uwb_init = UWB_Init((DW1000Driver*) ut->data);
380 d3710331 Cung Sang
381
  if (0 != uwb_init){
382 10b520a8 Cung Sang
    chprintf(stream, "error in UWB config with return value: %d \n", uwb_init);
383 d3710331 Cung Sang
  }
384
  else {
385 10b520a8 Cung Sang
    chprintf(stream, "succeed the init of UWB config \n");
386 d3710331 Cung Sang
  }
387
  aosThdSleep(1);
388
389 10b520a8 Cung Sang
  chprintf(stream, "running the RTLS demo application ... \n");
390 d3710331 Cung Sang
  aosThdSleep(1);
391
392 10b520a8 Cung Sang
  /*! Run the localization system demo app as a thread */
393 d3710331 Cung Sang
  while(1){
394
    instance_run();
395
//    aosThdUSleep(10);
396
  }
397
398
#endif  /*  UNIT_TEST_SNIPPETS_DW1000 */
399
400
  return result;
401
}
402
403
404
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_DW1000) && (AMIROLLD_CFG_DW1000 == 1) */