Statistics
| Branch: | Tag: | Revision:

amiro-os / devices / DiWheelDrive / main.cpp @ 552936c8

History | View | Annotate | Download (31.743 KB)

1 58fe0e0b Thomas Schöpping
#define BL_CALLBACK_TABLE_ADDR  (0x08000000 + 0x01C0)
2
#define BL_MAGIC_NUMBER         ((uint32_t)0xFF669900u)
3
4
#define SHUTDOWN_NONE             0
5
#define SHUTDOWN_TRANSPORTATION   1
6
#define SHUTDOWN_DEEPSLEEP        2
7
#define SHUTDOWN_HIBERNATE        3
8
#define SHUTDOWN_RESTART          4
9
#define SHUTDOWN_HANDLE_REQUEST   5
10
11
#include <ch.hpp>
12
13
#include <amiro/util/util.h>
14
#include <global.hpp>
15
#include <exti.hpp>
16
17
#include <chprintf.h>
18
#include <shell.h>
19
20
using namespace chibios_rt;
21
22
Global global;
23
24
void systemShutdown() {
25
  types::kinematic k;
26
  uint8_t i;
27
28
//  // make sure we assert SYS_PD_N to delay shutdown until we're done.
29
//  boardRequestShutdown();
30
31
    // stop the user thread
32
  global.userThread.requestTerminate();
33
  global.userThread.wait();
34
35
  k.x = 0x00u;
36
  k.w_z = 0x00u;
37
38
  // stop wheels
39
  global.robot.setTargetSpeed(k);
40
  global.robot.terminate();
41
42
  for (i = 0x00; i < global.vcnl4020.size(); i++) {
43
    global.vcnl4020[i].requestTerminate();
44
    global.vcnl4020[i].wait();
45
  }
46
47
  global.ina219.requestTerminate();
48
  global.ina219.wait();
49
  global.hmc5883l.requestTerminate();
50
  global.hmc5883l.wait();
51
  global.l3g4200d.requestTerminate();
52
  global.l3g4200d.wait();
53
54
  global.motorcontrol.requestTerminate();
55
  global.motorcontrol.wait();
56
  global.odometry.requestTerminate();
57
  global.odometry.wait();
58
59
  // stop I²C
60
  for (i = 0; i < global.V_I2C2.size(); ++i)
61
    global.V_I2C2[i].stop();
62
  global.HW_I2C2.stop();
63
64
  global.lis331dlh.requestTerminate();
65
  global.lis331dlh.wait();
66
67
  global.lis331dlh.configure(&global.accel_sleep_config);
68
//  global.lis331dlh.start(NORMALPRIO +4);
69
70
//  boardWriteIoPower(0);
71
//  boardStandby();
72
73
  return;
74
}
75
76
77
//void (*shellcmd_t)(BaseSequentialStream *chp, int argc, char *argv[]);
78
79
void shellRequestShutdown(BaseSequentialStream *chp, int argc, char *argv[]) {
80
81
  chprintf(chp, "shellRequestShutdown\n");
82
83
  /* if nor argument was given, print some help text */
84
  if (argc == 0 || strcmp(argv[0], "help") == 0) {
85
    chprintf(chp, "\tUSAGE:\n");
86
    chprintf(chp, "> shutdown <type>\n");
87
    chprintf(chp, "\n");
88
    chprintf(chp, "\ttype\n");
89
    chprintf(chp, "The type of shutdown to perform.\n");
90
    chprintf(chp, "Choose one of the following types:\n");
91
    chprintf(chp, "  transportation - Ultra low-power mode with all wakeups disabled.\n");
92
    chprintf(chp, "                   The robot can not be charged.\n");
93
    chprintf(chp, "  deepsleep      - Ultra low-power mode with several wakeups enabled.\n");
94
    chprintf(chp, "                   The robot can only be charged via the power plug.\n");
95
    chprintf(chp, "  hibernate      - Medium low-power mode, but with full charging capabilities.\n");
96
    chprintf(chp, "  restart        - Performs a system restart.\n");
97
    chprintf(chp, "Alternatively, you can use the shortcuts 't', 'd', 'h', and 'r' respectively.");
98
    chprintf(chp, "\n");
99
    return;
100
  }
101
102
  if (strcmp(argv[0],"transportation") == 0 || strcmp(argv[0],"t") == 0) {
103
    shutdown_now = SHUTDOWN_TRANSPORTATION;
104
    chprintf(chp, "shutdown to transportation mode initialized\n");
105
  } else if (strcmp(argv[0],"deepsleep") == 0 || strcmp(argv[0],"d") == 0) {
106
    shutdown_now = SHUTDOWN_DEEPSLEEP;
107
    chprintf(chp, "shutdown to deepsleep mode initialized\n");
108
  } else if (strcmp(argv[0],"hibernate") == 0 || strcmp(argv[0],"h") == 0) {
109
    shutdown_now = SHUTDOWN_HIBERNATE;
110
    chprintf(chp, "shutdown to hibernate mode initialized\n");
111
  } else if (strcmp(argv[0],"restart") == 0 || strcmp(argv[0],"r") == 0) {
112
    chprintf(chp, "restart initialized\n");
113
    shutdown_now = SHUTDOWN_RESTART;
114
  } else {
115
    chprintf(chp, "ERROR: unknown argument!\n");
116
    shutdown_now = SHUTDOWN_NONE;
117
  }
118
119
  return;
120
}
121
122
void shellRequestWakeup(BaseSequentialStream *chp, int argc, char *argv[]) {
123
  int i;
124
  chprintf(chp, "shellRequestWakeup\n");
125
126
  for (i = 0x00u; i < argc; i++)
127
    chprintf(chp, "%s\n", argv[i]);
128
129
  boardWakeup();
130
}
131
132
void shellRequestGetMemoryData(BaseSequentialStream *chp, int argc, char *argv[]) {
133
  enum Type {HEX, U8, U16, U32, S8, S16, S32};
134
135
  chprintf(chp, "shellRequestReadData\n");
136
137
  if (argc < 2 || strcmp(argv[0],"help") == 0)
138
  {
139
    chprintf(chp, "Usage: %s\n","get_memory_data <type> <start> [<count>]");
140
    chprintf(chp, "\n");
141
    chprintf(chp, "\ttype\n");
142
    chprintf(chp, "The data type as which to interpret the data.\n");
143
    chprintf(chp, "Choose one of the following types:\n");
144
    chprintf(chp, "  hex - one byte as hexadecimal value\n");
145
    chprintf(chp, "  u8  - unsigned integer (8 bit)\n");
146
    chprintf(chp, "  u16 - unsigned integer (16 bit)\n");
147
    chprintf(chp, "  u32 - unsigned integer (32 bit)\n");
148
    chprintf(chp, "  s8  - signed integer (8 bit)\n");
149
    chprintf(chp, "  s16 - signed integer (16 bit)\n");
150
    chprintf(chp, "  s32 - signed integer (32 bit)\n");
151
    chprintf(chp, "\tstart\n");
152
    chprintf(chp, "The first byte to read from the memory.\n");
153
    chprintf(chp, "\tcount [default = 1]\n");
154
    chprintf(chp, "The number of elements to read.\n");
155
    chprintf(chp, "\n");
156
    chprintf(chp, "\tNOTE\n");
157
    chprintf(chp, "Type conversions of this function might fail.\n");
158
    chprintf(chp, "If so, use type=hex and convert by hand.\n");
159
    chprintf(chp, "\n");
160
    return;
161
  }
162
163
  uint8_t type_size = 0;
164
  Type type = HEX;
165
  if (strcmp(argv[0],"hex") == 0) {
166
    type_size = sizeof(unsigned char);
167
    type = HEX;
168
  } else if(strcmp(argv[0],"u8") == 0) {
169
    type_size = sizeof(uint8_t);
170
    type = U8;
171
  } else if(strcmp(argv[0],"u16") == 0) {
172
    type_size = sizeof(uint16_t);
173
    type = U16;
174
  } else if(strcmp(argv[0],"u32") == 0) {
175
    type_size = sizeof(uint32_t);
176
    type = U32;
177
  } else if(strcmp(argv[0],"s8") == 0) {
178
    type_size = sizeof(int8_t);
179
    type = S8;
180
  } else if(strcmp(argv[0],"s16") == 0) {
181
    type_size = sizeof(int16_t);
182
    type = S16;
183
  } else if(strcmp(argv[0],"s32") == 0) {
184
    type_size = sizeof(int32_t);
185
    type = S32;
186
  } else {
187
    chprintf(chp, "First argument invalid. Use 'get_memory_data help' for help.\n");
188
    return;
189
  }
190
191
  unsigned int start_byte = atoi(argv[1]);
192
193
  unsigned int num_elements = 1;
194
  if (argc >= 3)
195
    num_elements = atoi(argv[2]);
196
197
  const size_t eeprom_size = EEPROM::getsize(&global.at24c01);
198
  uint8_t buffer[eeprom_size];
199
  if (start_byte + (type_size * num_elements) > eeprom_size) {
200
    num_elements = (eeprom_size - start_byte) / type_size;
201
    chprintf(chp, "Warning: request exceeds eeprom size -> limiting to %u values.\n", num_elements);
202
  }
203
204
  chFileStreamSeek((BaseFileStream*)&global.at24c01, start_byte);
205
206
  // Work around, because stm32f1 cannot read a single byte
207
  if (type_size*num_elements < 2)
208
    type_size = 2;
209
210
  uint32_t bytes_read = chSequentialStreamRead((BaseFileStream*)&global.at24c01, buffer, type_size*num_elements);
211
212
  if (bytes_read != type_size*num_elements)
213
    chprintf(chp, "Warning: %u of %u requested bytes were read.\n", bytes_read, type_size*num_elements);
214
215
  for (unsigned int i = 0; i < num_elements; ++i) {
216
    switch (type) {
217
      case HEX:
218
        chprintf(chp, "%02X ", buffer[i]);
219
        break;
220
      case U8:
221
        chprintf(chp, "%03u ", ((uint8_t*)buffer)[i]);
222
        break;
223
      case U16:
224
        chprintf(chp, "%05u ", ((uint16_t*)buffer)[i]);
225
        break;
226
      case U32:
227
        chprintf(chp, "%010u ", ((uint32_t*)buffer)[i]);
228
        break;
229
      case S8:
230
        chprintf(chp, "%+03d ", ((int8_t*)buffer)[i]);
231
        break;
232
      case S16:
233
        chprintf(chp, "%+05d ", ((int16_t*)buffer)[i]);
234
        break;
235
      case S32:
236
        chprintf(chp, "%+010d ", ((int32_t*)buffer)[i]);
237
        break;
238
      default:
239
        break;
240
    }
241
  }
242
  chprintf(chp, "\n");
243
244
  return;
245
}
246
247
void shellRequestSetLights(BaseSequentialStream *chp, int argc, char *argv[]) {
248
249
  if (argc < 2 || argc == 3 ||strcmp(argv[0],"help") == 0) {
250
    chprintf(chp, "\tUSAGE:\n");
251
    chprintf(chp, "> set_lights <led mask> <white/red> [<green> <blue>]\n");
252
    chprintf(chp, "\n");
253
    chprintf(chp, "\tled mask\n");
254
    chprintf(chp, "The LEDs to be set.\n");
255
    chprintf(chp, "You can set multiple LEDs at once by adding the following values:\n");
256
    chprintf(chp, "  0x01 - rear left LED (SSW)\n");
257
    chprintf(chp, "  0x02 - left rear LED (WSW)\n");
258
    chprintf(chp, "  0x04 - left front LED (WNW)\n");
259
    chprintf(chp, "  0x08 - front left LED (NNW)\n");
260
    chprintf(chp, "  0x10 - front right LED (NNE)\n");
261
    chprintf(chp, "  0x20 - right front LED (ENE)\n");
262
    chprintf(chp, "  0x40 - right rear LED (ESE)\n");
263
    chprintf(chp, "  0x80 - rear right LED (SSE)\n");
264
    chprintf(chp, "\twhite/red\n");
265
    chprintf(chp, "If no optional argument is given, this arguments sets the white value of the selected LEDs.\n");
266
    chprintf(chp, "Otherwise this arguments sets the red color channel value.\n");
267
    chprintf(chp, "\tgreen\n");
268
    chprintf(chp, "Sets the green color channel value.\n");
269
    chprintf(chp, "\tblue\n");
270
    chprintf(chp, "Sets the blue color channel value.\n");
271
    chprintf(chp, "\n");
272
    chprintf(chp, "\tExample:\n");
273
    chprintf(chp, "This line will set the two most left and two most right LEDs to bright cyan.\n");
274
    chprintf(chp, "> set_lights 0x66 0 255 255\n");
275
    chprintf(chp, "\n");
276
    return;
277
  }
278
279
  int arg_mask = strtol(argv[0], NULL, 0);
280
  int red = strtol(argv[1], NULL, 0);
281
  int green = red;
282
  int blue = red;
283
  if (argc >= 4) {
284
    green = strtol(argv[2], NULL, 0);
285
    blue = strtol(argv[3], NULL, 0);
286
  }
287
  Color color(red, green, blue);
288
289
  if (arg_mask & 0x01) {
290
    global.robot.setLightColor(constants::LightRing::LED_SSW, color);
291
  }
292
  if (arg_mask & 0x02) {
293
    global.robot.setLightColor(constants::LightRing::LED_WSW, color);
294
  }
295
  if (arg_mask & 0x04) {
296
    global.robot.setLightColor(constants::LightRing::LED_WNW, color);
297
  }
298
  if (arg_mask & 0x08) {
299
    global.robot.setLightColor(constants::LightRing::LED_NNW, color);
300
  }
301
  if (arg_mask & 0x10) {
302
    global.robot.setLightColor(constants::LightRing::LED_NNE, color);
303
  }
304
  if (arg_mask & 0x20) {
305
    global.robot.setLightColor(constants::LightRing::LED_ENE, color);
306
  }
307
  if (arg_mask & 0x40) {
308
    global.robot.setLightColor(constants::LightRing::LED_ESE, color);
309
  }
310
  if (arg_mask & 0x80) {
311
    global.robot.setLightColor(constants::LightRing::LED_SSE, color);
312
  }
313
314
  return;
315
}
316
317
void boardPeripheryCheck(BaseSequentialStream *chp) {
318
  msg_t result;
319
  chprintf(chp, "\nCHECK: START\n");
320
  // Check the accelerometer
321
  result = global.lis331dlh.getCheck();
322
  if (result == global.lis331dlh.CHECK_OK)
323
    chprintf(chp, "LIS331DLH: OK\n");
324
  else
325
    chprintf(chp, "LIS331DLH: FAIL\n");
326
327
  // Self-test accelerometer
328
//  lis331dlh.printSelfTest(NULL);
329
330
  // Check the eeprom
331
  result = global.memory.getCheck();
332
  if ( result != global.memory.OK)
333
    chprintf(chp, "Memory Structure: FAIL\n");
334
  else
335
    chprintf(chp, "Memory Structure: OK\n");
336
337
  // Check the gyroscope
338
  result = global.l3g4200d.getCheck();
339
  if (result == global.l3g4200d.CHECK_OK)
340
    chprintf(chp, "L3G4200D: OK\n");
341
  else
342
    chprintf(chp, "L3G4200D: FAIL\n");
343
344
  // Check the magnetometer
345
  result = global.hmc5883l.getCheck();
346
  if (result == global.hmc5883l.CHECK_OK)
347
    chprintf(chp, "HMC5883L: OK\n");
348
  else
349
    chprintf(chp, "HMC5883L: FAIL\n");
350
351
  // Check the MUX
352
  result = global.HW_PCA9544.getCheck();
353
  if (result == global.HW_PCA9544.CHECK_OK)
354
    chprintf(chp, "PCA9544: OK\n");
355
  else
356
    chprintf(chp, "PCA9544: FAIL\n");
357
358
  // Check the power monitor
359
  chprintf(chp, "INA219:\tVDD (3.3V):\n");
360
  result = global.ina219.selftest();
361
  if (result == BaseSensor<>::NOT_IMPLEMENTED)
362
    chprintf(chp, "->\tnot implemented\n");
363
  else if (result != INA219::Driver::ST_OK)
364
    chprintf(chp, "->\tFAIL (error code 0x%02X)\n", result);
365
  else
366
    chprintf(chp, "->\tOK\n");
367
368
  // Check the proximitysensors
369
  for (uint8_t i = 0x00; i < global.vcnl4020.size(); i++) {
370
    result = global.vcnl4020[i].getCheck();
371
    if (result == global.vcnl4020[i].CHECK_OK)
372
      chprintf(chp, "VCNL4020: %d OK\n", i);
373
    else
374
      chprintf(chp, "VCNL4020: %d FAIL\n", i);
375
  }
376
  chprintf(chp, "CHECK: FINISH\n");
377
}
378
379
void shellRequestCheck(BaseSequentialStream *chp, int __unused argc, char __unused *argv[]) {
380
  chprintf(chp, "shellRequestCheck\n");
381
  boardPeripheryCheck(chp);
382
}
383
384
void shellRequestResetMemory(BaseSequentialStream *chp, int __unused argc, char __unused *argv[]) {
385
  chprintf(chp, "shellRequestInitMemory\n");
386
387
  msg_t res = global.memory.resetMemory();
388
  if ( res != global.memory.OK)
389
    chprintf(chp, "Memory Init: FAIL\n");
390
  else
391
    chprintf(chp, "Memory Init: OK\n");
392
}
393
394
void shellRequestGetBoardId(BaseSequentialStream *chp, int __unused argc, char __unused *argv[]) {
395
  chprintf(chp, "shellRequestGetBoardId\n");
396
  uint8_t id = 0xFFu;
397
398
  msg_t res = global.memory.getBoardId(&id);
399
400
  if (res != global.memory.OK)
401
    chprintf(chp, "Get Board ID: FAIL\n");
402
  else
403
    chprintf(chp, "Get Board ID: %u\n", id);
404
}
405
406
void shellRequestSetBoardId(BaseSequentialStream *chp, int argc, char *argv[]) {
407
  chprintf(chp, "shellRequestSetBoardId\n");
408
409
  if (argc == 0) {
410
    chprintf(chp, "Usage: %s\n","set_board_id <idx>");
411
  } else {
412
    msg_t res = global.memory.setBoardId(atoi(argv[0]));
413
    if (res != global.memory.OK)
414
      chprintf(chp, "Set Board ID: FAIL\n");
415
    else
416
      chprintf(chp, "Set Board ID: OK\n");
417
  }
418
}
419
420
void shellRequestResetCalibrationConstants(BaseSequentialStream *chp, int __unused argc, char __unused *argv[]) {
421
  chprintf(chp, "shellRequestResetCalibrationConstants\n");
422
  chprintf(chp, "Setting Ed=1.0f, Eb=1.0f\n");
423
  msg_t res;
424
425
  res = global.memory.setEd(1.0f);
426
  if (res != global.memory.OK)
427
    chprintf(chp, "Set Ed: FAIL\n");
428
  else
429
    chprintf(chp, "Set Ed: OK\n");
430
431
  res = global.memory.setEb(1.0f);
432
  if (res != global.memory.OK)
433
    chprintf(chp, "Set Eb: FAIL\n");
434
  else
435
    chprintf(chp, "Set Eb: OK\n");
436
}
437
438
void shellRequestGetCalibrationConstants(BaseSequentialStream *chp, int __unused argc, char __unused *argv[]) {
439
  chprintf(chp, "shellRequestGetCalibrationConstants\n");
440
  msg_t res;
441
  float Ed, Eb;
442
443
  res = global.memory.getEd(&Ed);
444
  if (res != global.memory.OK)
445
    chprintf(chp, "Get Ed: FAIL\n");
446
  else
447
    chprintf(chp, "Get Ed: OK \t Ed=%f\n", Ed);
448
449
  res = global.memory.getEb(&Eb);
450
  if (res != global.memory.OK)
451
    chprintf(chp, "Get Eb: FAIL\n");
452
  else
453
    chprintf(chp, "Get Eb: OK \t Eb=%f\n", Eb);
454
}
455
456
void shellRequestSetCalibrationConstants(BaseSequentialStream *chp, int argc, char *argv[]) {
457
  chprintf(chp, "shellRequestSetCalibrationConstants\n");
458
  msg_t res;
459
460
  if (argc != 3) {
461
    chprintf(chp, "Usage: %s\n","set_Ed_Eb <Ed> <Eb> <Write To Eeprom ? 1 : 0>");
462
    chprintf(chp, "(Call with floating point values for Ed and Eb values and write condition):\n");
463
    return;
464
  }
465
  // Get the write condition
466
  const float Ed = atof(argv[0]);
467
  const float Eb = atof(argv[1]);
468
  bool_t writeToMemory = atoi(argv[2]) == 1 ? true : false;
469
470
  res = global.motorcontrol.setWheelDiameterCorrectionFactor(Ed, writeToMemory);
471
  if (res != global.memory.OK)
472
    chprintf(chp, "Set Ed: FAIL\n");
473
  else
474
    chprintf(chp, "Set Ed: OK \t Ed=%f\n", Ed);
475
476
  res = global.motorcontrol.setActualWheelBaseDistance(Eb, writeToMemory);
477
  if (res != global.memory.OK)
478
    chprintf(chp, "Set Eb: FAIL\n");
479
  else
480
    chprintf(chp, "Set Eb: OK \t Ed=%f\n", Eb);
481
}
482
483
void shellRequestGetVcnl(BaseSequentialStream *chp, int argc, char *argv[]) {
484
  chprintf(chp, "shellRequestGetVcnl\n");
485
  // Print the sensor information
486
  if (argc != 1) {
487
    chprintf(chp, "Usage: %s\n","get_vcnl <rep>");
488
    return;
489
  }
490
  for (int32_t rep = 0x00; rep < atoi(argv[0]); ++rep) {
491
    for (uint8_t idx = 0x00; idx < global.vcnl4020.size(); idx++) {
492
     chprintf(chp, "%d: Ambi %d\tProx raw %d\tProx scaled %d\n", idx, global.vcnl4020[idx].getAmbientLight(), global.vcnl4020[idx].getProximity(), global.vcnl4020[idx].getProximityScaledWoOffset());
493
    }
494
    chprintf(chp, "\n\n");
495
    BaseThread::sleep(MS2ST(250));
496
  }
497
}
498
499
void shellRequestSetVcnlOffset(BaseSequentialStream *chp, int argc, char *argv[]) {
500
  chprintf(chp, "shellRequestSetVcnlOffset\n");
501
  if (argc != 2) {
502
    chprintf(chp, "Usage: %s\n","set_vcnl <idx> <offset>");
503
    return;
504
  }
505
506
  uint8_t vcnlIdx = static_cast<uint8_t>(atoi(argv[0]));
507
  uint16_t vcnlOffset = static_cast<uint16_t>(atoi(argv[1]));
508
509
  if (vcnlIdx >= global.vcnl4020.size()) {
510
    chprintf(chp, "Wrong VCNL index: Choose [0 .. %d]\n", global.vcnl4020.size()-1);
511
    return;
512
  }
513
514
  msg_t res = global.memory.setVcnl4020Offset(vcnlOffset, vcnlIdx);
515
  if (res != global.memory.OK) {
516
    chprintf(chp, "Set Offset: FAIL\n");
517
  } else {
518
    chprintf(chp, "Set Offset: OK\n");
519
    global.vcnl4020[vcnlIdx].setProximityOffset(vcnlOffset);
520
  }
521
}
522
523
void shellRequestResetVcnlOffset(BaseSequentialStream *chp, int argc, char *argv[]) {
524
  msg_t res = global.memory.OK;
525
  for (uint8_t idx = 0; idx < 4; ++idx) {
526
    msg_t r = global.memory.setVcnl4020Offset(0, idx);
527
    if (r == global.memory.OK) {
528
      global.vcnl4020[idx].setProximityOffset(0);
529
    } else {
530
      chprintf(chp, "Reset Offset %u: FAIL\n", idx);
531
      res = r;
532
    }
533
  }
534
535
  if (res == global.memory.OK) {
536
    chprintf(chp, "Reset Offset: DONE\n");
537
  }
538
539
  return;
540
}
541
542
void shellRequestGetVcnlOffset(BaseSequentialStream *chp, int argc, char *argv[]) {
543
  chprintf(chp, "shellRequestGetVcnlOffset\n");
544
  if (argc != 1) {
545
    chprintf(chp, "Call with decimal numbers: get_vcnl <idx>\n");
546
    return;
547
  }
548
549
  uint8_t vcnlIdx = static_cast<uint8_t>(atoi(argv[0]));
550
551
  if (vcnlIdx >= global.vcnl4020.size()) {
552
    chprintf(chp, "Wrong VCNL index: Choose [0 .. %d]\n", global.vcnl4020.size()-1);
553
    return;
554
  }
555
556
  uint16_t vcnlOffset;
557
  msg_t res = global.memory.getVcnl4020Offset(&vcnlOffset, vcnlIdx);
558
  if (res != global.memory.OK) {
559
    chprintf(chp, "Get Offset: FAIL\n");
560
  } else {
561
    chprintf(chp, "Get Offset: OK \t Offset=%d\n", vcnlOffset);
562
  }
563
}
564
565
void shellRequestCalib(BaseSequentialStream *chp, int __unused argc, char __unused *argv[]) {
566
  chprintf(chp, "shellRequestCalib\n");
567
  global.robot.calibrate();
568
}
569
570
void shellRequestGetRobotId(BaseSequentialStream *chp, int __unused argc, char __unused *argv[]) {
571
  chprintf(chp, "shellRequestGetRobotId\n");
572
  chprintf(chp, "Robot ID: %u\n", global.robot.getRobotID());
573
  if (global.robot.getRobotID() == 0)
574
    chprintf(chp, "Warning: The board ID seems to be uninitialized.\n");
575
}
576
577
void shellRequestGetSystemLoad(BaseSequentialStream *chp, int argc, char *argv[]) {
578
  chprintf(chp, "shellRequestGetSystemLoad\n");
579
  uint8_t seconds = 1;
580
  if (argc >= 1) {
581
    seconds = atoi(argv[0]);
582
  }
583
  chprintf(chp, "measuring CPU load for %u %s...\n", seconds, (seconds>1)? "seconds" : "second");
584
585
  const systime_t before = chThdGetTicks(chSysGetIdleThread());
586
  BaseThread::sleep(S2ST(seconds));
587
  const systime_t after = chThdGetTicks(chSysGetIdleThread());
588
  const float usage = 1.0f - (float(after - before) / float(seconds * CH_FREQUENCY));
589
590
  chprintf(chp, "CPU load: %3.2f%%\n", usage * 100);
591
  const uint32_t memory_total = 0x10000;
592
  const uint32_t memory_load = memory_total - chCoreStatus();
593
  chprintf(chp, "RAM load: %3.2f%% (%u / %u Byte)\n", float(memory_load)/float(memory_total) * 100, memory_load, memory_total);
594
}
595
596
void shellSwitchBoardCmd(BaseSequentialStream *chp, int argc, char *argv[]) {
597
  if (argc != 1) {
598
    chprintf(chp, "Call with decimal numbers: shell_board <idx>\n");
599
    return;
600
  }
601
  uint8_t boardIdx = static_cast<uint8_t>(atoi(argv[0]));
602
603
  chprintf(chp, "shellSwitchBoardCmd\n");
604
  global.sercanmux1.sendSwitchCmd(boardIdx);
605
}
606
607
void shellRequestGetBootloaderInfo(BaseSequentialStream* chp, int argc, char *argv[]) {
608
  // check the magic number
609
  if (*((uint32_t*)(BL_CALLBACK_TABLE_ADDR)) == BL_MAGIC_NUMBER) {
610
    chprintf(chp, "Bootloader version:  %u.%u.%u\n",
611
             *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (1*4))),
612
             *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (2*4))),
613
             *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (3*4))));
614
    chprintf(chp, "Callback functions:\n");
615
    if (*((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (1*4))) == 0 && *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (2*4))) == 2) {
616
      chprintf(chp, "\thibernate:      %s\n", *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (4*4))) ? "available" : "unsupported");
617
      chprintf(chp, "\tdeepsleep:      %s\n", *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (5*4))) ? "available" : "unsupported");
618
      chprintf(chp, "\ttransportation: %s\n", *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (6*4))) ? "available" : "unsupported");
619
      chprintf(chp, "\trestart:        %s\n", *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (10*4))) ? "available" : "unsupported");
620
    } else if (*((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (1*4))) == 0 && *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (2*4))) == 3) {
621
      chprintf(chp, "\thibernate:      %s\n", *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (4*4))) ? "available" : "unsupported");
622
      chprintf(chp, "\tdeepsleep:      %s\n", *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (5*4))) ? "available" : "unsupported");
623
      chprintf(chp, "\ttransportation: %s\n", *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (6*4))) ? "available" : "unsupported");
624
      chprintf(chp, "\trestart:        %s\n", *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (7*4))) ? "available" : "unsupported");
625
      chprintf(chp, "\thandle request: %s\n", *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (8*4))) ? "available" : "unsupported");
626
    }
627
  } else {
628
    chprintf((BaseSequentialStream*) &SD1, "Bootloader deprecated\n");
629
  }
630
631
  return;
632
}
633
634
void shellRequestMotorDrive(BaseSequentialStream *chp, int argc, char *argv[]) {
635
  types::kinematic tmp;
636
  tmp.w_z = 0;
637
  tmp.x = 0;
638
  if (argc == 1){
639
    chprintf(chp, "Set speed to %i um/s \n", atoi(argv[0]));
640
    tmp.x = atoi(argv[0]);
641
  } else {
642
    if(argc == 2){
643
      chprintf(chp, "Set speed to %i \n um/s", atoi(argv[0]));
644
      chprintf(chp, "Set angular speed to %i \n urad/s", atoi(argv[1]));
645
      tmp.x = atoi(argv[0]);
646
      tmp.w_z= atoi(argv[1]);
647
    } else {
648
      chprintf(chp, "Wrong number of parameters given (%i), stopping robot \n", argc);
649
    }
650
  }
651
652
  global.motorcontrol.setTargetSpeed(tmp);
653
  return;
654
}
655
656
void shellRequestMotorStop(BaseSequentialStream *chp, int argc, char *argv[]) {
657
  types::kinematic tmp;
658
  tmp.x = 0;
659
  tmp.w_z = 0;
660
661
  global.motorcontrol.setTargetSpeed(tmp);
662
663
  chprintf(chp, "stop");
664
return;
665
}
666
667
void shellRequestMotorCalibrate(BaseSequentialStream *chp, int argc, char *argv[]) {
668
  global.motorcontrol.isCalibrating = true;
669
670
  return;
671
}
672
673
void shellRequestMotorGetGains(BaseSequentialStream *chp, int argc, char *argv[]){
674
  global.motorcontrol.printGains();
675
676
  return;
677
}
678
679
static const ShellCommand commands[] = {
680
  {"shutdown", shellRequestShutdown},
681
  {"wakeup", shellRequestWakeup},
682
  {"check", shellRequestCheck},
683
  {"reset_memory", shellRequestResetMemory},
684
  {"get_board_id", shellRequestGetBoardId},
685
  {"set_board_id", shellRequestSetBoardId},
686
  {"get_memory_data", shellRequestGetMemoryData},
687
  {"get_vcnl", shellRequestGetVcnl},
688
  {"calib_vcnl_offset", shellRequestCalib},
689
  {"set_vcnl_offset", shellRequestSetVcnlOffset},
690
  {"reset_vcnl_offset", shellRequestResetVcnlOffset},
691
  {"get_vcnl_offset", shellRequestGetVcnlOffset},
692
  {"reset_Ed_Eb", shellRequestResetCalibrationConstants},
693
  {"get_Ed_Eb", shellRequestGetCalibrationConstants},
694
  {"set_Ed_Eb", shellRequestSetCalibrationConstants},
695
  {"get_robot_id", shellRequestGetRobotId},
696
  {"get_system_load", shellRequestGetSystemLoad},
697
  {"set_lights", shellRequestSetLights},
698
  {"shell_board", shellSwitchBoardCmd},
699
  {"get_bootloader_info", shellRequestGetBootloaderInfo},
700
  {"motor_drive", shellRequestMotorDrive},
701
  {"motor_stop", shellRequestMotorStop},
702
  {"motor_calibrate", shellRequestMotorCalibrate},
703
  {"motor_getGains", shellRequestMotorGetGains},
704
  {NULL, NULL}
705
};
706
707
static const ShellConfig shell_cfg1 = {
708
  (BaseSequentialStream *) &global.sercanmux1,
709
  commands
710
};
711
712
void initPowermonitor(INA219::Driver &ina219, const float shuntResistance_O, const float maxExpectedCurrent_A, const uint16_t currentLsb_uA)
713
{
714
  INA219::CalibData calibData;
715
  INA219::InitData initData;
716
717
  calibData.input.configuration.content.brng = INA219::Configuration::BRNG_16V;
718
  calibData.input.configuration.content.pg = INA219::Configuration::PGA_40mV;
719
  calibData.input.configuration.content.badc = INA219::Configuration::ADC_68100us;
720
  calibData.input.configuration.content.sadc = INA219::Configuration::ADC_68100us;
721
  calibData.input.configuration.content.mode = INA219::Configuration::MODE_ShuntBus_Continuous;
722
  calibData.input.shunt_resistance_O = shuntResistance_O;
723
  calibData.input.max_expected_current_A = maxExpectedCurrent_A;
724
  calibData.input.current_lsb_uA = currentLsb_uA;
725
  if (ina219.calibration(&calibData) != BaseSensor<>::SUCCESS)
726
  {
727
    chprintf((BaseSequentialStream*)&SD1, "WARNING: calibration of INA219 failed.\n");
728
  }
729
730
  initData.configuration.value = calibData.input.configuration.value;
731
  initData.calibration = calibData.output.calibration_value;
732
  initData.current_lsb_uA = calibData.output.current_lsb_uA;
733
  if (ina219.init(&initData) != BaseSensor<>::SUCCESS)
734
  {
735
    chprintf((BaseSequentialStream*)&SD1, "WARNING: initialization of INA219 failed.\n");
736
  }
737
738
  if (calibData.input.current_lsb_uA != initData.current_lsb_uA)
739
  {
740
    chprintf((BaseSequentialStream*)&SD1, "NOTE: LSB for current measurement was limited when initializing INA219 (%u -> %u)", calibData.input.current_lsb_uA, initData.current_lsb_uA);
741
  }
742
743
  return;
744
}
745
746
/*
747
 * Application entry point.
748
 */
749
int main(void) {
750
751
//  int16_t accel;
752
  Thread *shelltp = NULL;
753
754
  /*
755
   * System initializations.
756
   * - HAL initialization, this also initializes the configured device drivers
757
   *   and performs the board-specific initializations.
758
   * - Kernel initialization, the main() function becomes a thread and the
759
   *   RTOS is active.
760
   */
761
  halInit();
762
  qeiInit();
763
  System::init();
764
765
//  boardWakeup();
766
//  boardWriteIoPower(1);
767
768
  /*
769
   * Activates the serial driver 2 using the driver default configuration.
770
   */
771
  sdStart(&SD1, &global.sd1_config);
772
773
  chprintf((BaseSequentialStream*) &SD1, "\n");
774
  chprintf((BaseSequentialStream*) &SD1, BOARD_NAME " " BOARD_VERSION "\n");
775
  if (*((uint32_t*)(BL_CALLBACK_TABLE_ADDR)) == BL_MAGIC_NUMBER) {
776
    chprintf((BaseSequentialStream*) &SD1, "Bootloader %u.%u.%u\n",
777
             *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (1*4))),
778
             *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (2*4))),
779
             *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (3*4))));
780
  } else {
781
    chprintf((BaseSequentialStream*) &SD1, "Bootloader deprecated\n");
782
  }
783
  chprintf((BaseSequentialStream*) &SD1, "ChibiOS " CH_KERNEL_VERSION "\n");
784
  // make sure that the info text is completetly printed
785
  BaseThread::sleep(10);
786
787
  extStart(&EXTD1, &extcfg);
788
789
  /*
790
   * Wait for a certain amount of time, so that the PowerBoard can activate
791
   * the IO voltages for the I2C Bus
792
   */
793
  BaseThread::sleep(MS2ST(2000));
794
795 b4885314 Thomas Schöpping
  boardClearI2CBus(GPIOB_COMPASS_SCL, GPIOB_COMPASS_SDA);
796
  boardClearI2CBus(GPIOB_IR_SCL, GPIOB_IR_SDA);
797 58fe0e0b Thomas Schöpping
798
  global.HW_I2C1.start(&global.i2c1_config);
799
  global.HW_I2C2.start(&global.i2c2_config);
800
801
  global.memory.init();
802
803
  uint8_t i = 0;
804
  if (global.memory.getBoardId(&i) == fileSystemIo::FileSystemIoBase::OK) {
805
    chprintf((BaseSequentialStream*) &SD1, "Board ID: %u\n", i);
806
  } else {
807
    chprintf((BaseSequentialStream*) &SD1, "Error reading board ID\n");
808
  }
809
  chprintf((BaseSequentialStream*) &SD1, "\n");
810
811
  initPowermonitor(global.ina219, 0.1f, 0.075f, 10);
812
813
  for (i = 0x00u; i < global.vcnl4020.size(); i++) {
814
    uint16_t buffer;
815
    global.memory.getVcnl4020Offset(&buffer,i);
816
    global.vcnl4020[i].setProximityOffset(buffer);
817
    global.vcnl4020[i].start(NORMALPRIO);
818
  }
819
820
  global.ina219.start(NORMALPRIO);
821
822
  global.hmc5883l.start(NORMALPRIO + 8);
823
824
  global.increments.start();  // Start the qei driver
825
826
  global.odometry.start(NORMALPRIO + 20);
827
828
  global.robot.start(HIGHPRIO - 1);
829
830
  global.motorcontrol.start(NORMALPRIO + 7);
831
832
  global.distcontrol.start(NORMALPRIO + 9);
833
834
  // Set target velocity
835
  types::kinematic velocity;
836
  velocity.x = 0; // E.g.  "100*1e3" equals "10 cm/s"
837
  velocity.w_z = 0; // E.g. "2*1e6" equals "2 rad/s"
838
  global.motorcontrol.setTargetSpeed(velocity);
839
840
  // Start the three axes linear accelerometer
841
  global.lis331dlh.configure(&global.accel_run_config);
842
  global.lis331dlh.start(NORMALPRIO+4);
843
844
  // Start the three axes gyroscope
845
  global.l3g4200d.configure(&global.gyro_run_config);
846
  global.l3g4200d.start(NORMALPRIO+5);
847
848
  // Start the user thread
849
  global.userThread.start(NORMALPRIO);
850
851
  /* let the SYS_SYNC_N pin go, to signal that the initialization of the module is done */
852
  palWritePad(GPIOC, GPIOC_SYS_INT_N, PAL_HIGH);
853
854
  /* wait until all modules are done */
855
  while (palReadPad(GPIOC, GPIOC_SYS_INT_N) == PAL_LOW) {
856
    continue;
857
  }
858
859
  while (true) {
860
861
    if (!shelltp)
862
      shelltp = shellCreate(&shell_cfg1, THD_WA_SIZE(1024), NORMALPRIO);
863
    else if (chThdTerminated(shelltp)) {
864
      chThdRelease(shelltp);    /* Recovers memory of the previous shell. */
865
      shelltp = NULL;           /* Triggers spawning of a new shell.      */
866
    }
867
868
    // Let the LED just blink as an alive signal
869
    boardWriteLed(1);
870
    BaseThread::sleep(MS2ST(250));
871
    boardWriteLed(0);
872
    BaseThread::sleep(MS2ST(250));
873
874
    if (shutdown_now != SHUTDOWN_NONE) {
875
      if (*((uint32_t*)(BL_CALLBACK_TABLE_ADDR)) != BL_MAGIC_NUMBER) {
876
        chprintf((BaseSequentialStream*) &SD1, "ERROR: unable to shut down (bootloader deprecated).\n");
877
        shutdown_now = SHUTDOWN_NONE;
878
      } else {
879
        uint32_t blCallbackPtrAddr = BL_CALLBACK_TABLE_ADDR;
880
        if (*((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (1*4))) == 0 && *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (2*4))) == 2) {
881
          switch (shutdown_now) {
882
            case SHUTDOWN_TRANSPORTATION:
883
              blCallbackPtrAddr += 6 * 4;
884
              break;
885
            case SHUTDOWN_DEEPSLEEP:
886
              blCallbackPtrAddr += 5 * 4;
887
              break;
888
            case SHUTDOWN_HIBERNATE:
889
              blCallbackPtrAddr += 4 * 4;
890
              break;
891
            case SHUTDOWN_HANDLE_REQUEST:
892
            case SHUTDOWN_RESTART:
893
              blCallbackPtrAddr += 10 * 4;
894
              break;
895
            default:
896
              blCallbackPtrAddr = 0;
897
              break;
898
          }
899
        } else if (*((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (1*4))) == 0 && *((uint32_t*)(BL_CALLBACK_TABLE_ADDR + (2*4))) == 3) {
900
          switch (shutdown_now) {
901
            case SHUTDOWN_TRANSPORTATION:
902
              blCallbackPtrAddr += 6 * 4;
903
              break;
904
            case SHUTDOWN_DEEPSLEEP:
905
              blCallbackPtrAddr += 5 * 4;
906
              break;
907
            case SHUTDOWN_HIBERNATE:
908
              blCallbackPtrAddr += 4 * 4;
909
              break;
910
            case SHUTDOWN_RESTART:
911
              blCallbackPtrAddr += 7 * 4;
912
              break;
913
            case SHUTDOWN_HANDLE_REQUEST:
914
              blCallbackPtrAddr += 8 * 4;
915
              break;
916
            default:
917
              blCallbackPtrAddr = 0;
918
              break;
919
          }
920
        }
921
922
        void (*blCallback)(void) = NULL;
923
        if (blCallbackPtrAddr) {
924
          blCallback = (void (*)(void))(*((uint32_t*)blCallbackPtrAddr));
925
926
          if (!blCallback) {
927
            chprintf((BaseSequentialStream*) &SD1, "ERROR: Requested shutdown not supported.\n");
928
            shutdown_now = SHUTDOWN_NONE;
929
          } else {
930
            chprintf((BaseSequentialStream*)&SD1, "initiating shutdown sequence...\n");
931
            palWritePad(GPIOC, GPIOC_SYS_INT_N, PAL_LOW);
932
            palWritePad(GPIOC, GPIOC_SYS_PD_N, PAL_LOW);
933
934
            chprintf((BaseSequentialStream*)&SD1, "stopping all threads and periphery...");
935
            systemShutdown();
936
            chprintf((BaseSequentialStream*)&SD1, "\tdone\n");
937
            BaseThread::sleep(MS2ST(10)); // sleep to print everything
938
939
            blCallback();
940
          }
941
942
        } else {
943
          chprintf((BaseSequentialStream*) &SD1, "ERROR: invalid shutdown requested (%u).\n", shutdown_now);
944
          shutdown_now = SHUTDOWN_NONE;
945
        }
946
      }
947
948
//    for (uint8_t i = LIS331DLH::AXIS_X; i <= LIS331DLH::AXIS_Z; i++) {
949
//        accel = lis331dlh.getAcceleration(i);
950
//        chprintf((BaseSequentialStream*) &SD1, "%c%04X ", accel < 0 ? '-' : '+', accel < 0 ? -accel : accel);
951
//    }
952
//
953
//    chprintf((BaseSequentialStream*) &SD1, "\n");
954
//
955
//    // Print out an alive signal
956
//    chprintf((BaseSequentialStream*) &SD1, ".");
957
    }
958
  }
959
960
  return 0;
961
}