blob: d3fbf76ea1f3bb4d25b8a8a3c03942a3eb61bbf7 [file] [log] [blame]
Ravago Jonesb83957c2021-12-29 19:57:34 -08001/**
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <stdio.h>
8
9#include <algorithm>
10#include <cstring>
11
12#include "hardware/dma.h"
13#include "hardware/gpio.h"
14#include "hardware/irq.h"
15#include "hardware/pio.h"
16#include "hardware/pwm.h"
17#include "hardware/spi.h"
18#include "hardware/timer.h"
19#include "pico/binary_info.h"
20#include "pico/bootrom.h"
21#include "pico/double.h"
22#include "pico/stdlib.h"
23#include "quadrature_encoder.pio.h"
24
25// Pinout definitions for the imu
26#define RST_IMU 22
27#define DR_IMU 20
28#define SYNC_IMU 21
29#define DIN_IMU 19
30#define DOUT_IMU 16
31#define SCLK_IMU 18
32#define CS_IMU 17
33
34// Pinout definitions for spi to the pi through the differential drivers
35#define DR_PI 14
36#define MOSI_PI 12
37#define MISO_PI 11
38#define SCK_PI 10
39#define CS_PI 13
40
41// The two drivetrain encoders
42#define ENC1_A 6
43#define ENC1_B 7
44#define ENC2_A 0
45#define ENC2_B 1
46
47// Backup outputs to the roborio
48#define RATE_PWM 2
49#define HEADING_PWM 4
50
51#define PWM_FREQ_HZ 200
52// PWM counts to this before wrapping
53#define PWM_TOP 62499
54
55#define SPI_IMU spi0
56#define SPI_PI spi1
57#define WRITE_BIT 0x8000
58
59// length in half-words of the buffer for communicating with the IMU
60// includes 2 non-data fields
61// the first element is used for recieving zeros while the initial request is
62// made the last element is the checksum
63#define IMU_NUM_ITEMS 17
64
65// length in bytes of the packet to the pi
66#define PI_NUM_ITEMS 42
67
68// number of samples for zeroing the z-gyro axis
69#define YAW_BUF_LEN 5000
70
71#define EXPECTED_PROD_ID 0x4079
72
73// Registers on the ADIS16505
74#define GLOB_CMD 0x68
75#define DIAG_STAT 0x02
76#define FIRM_REV 0x6C
77#define FIRM_DM 0x6E
78#define FIRM_Y 0x70
79#define PROD_ID 0x72
80#define SERIAL_NUM 0x74
81#define FILT_CTRL 0x5C
82#define MSC_CTRL 0x60
83#define DEC_RATE 0x64
84
85// TODO: replace with aos/events/logging/crc32.h
86const uint32_t kCrc32Table[256] = {
87 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
88 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
89 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
90 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
91 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
92 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
93 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
94 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
95 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
96 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
97 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
98 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
99 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
100 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
101 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
102 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
103 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
104 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
105 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
106 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
107 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
108 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
109 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
110 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
111 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
112 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
113 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
114 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
115 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
116 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
117 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
118 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
119 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
120 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
121 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
122 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
123 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
124 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
125 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
126 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
127 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
128 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
129 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
130
131// Buffer to start a burst read and recive 15 items + checksum
132static uint16_t imu_write_buf[IMU_NUM_ITEMS] = {0x6800, 0, 0, 0, 0, 0, 0, 0, 0,
133 0, 0, 0, 0, 0, 0, 0, 0};
134// recieves a byte of zeros followed by 15 items + checksum
135static uint16_t imu_data_buffer[IMU_NUM_ITEMS];
136
137static dma_channel_config imu_tx_config;
138static dma_channel_config imu_rx_config;
139static uint imu_dma_tx;
140static uint imu_dma_rx;
141
142// The packet to the pi contains the whole burst read from the IMU (30 bytes)
143// followed by a timestamp, encoder values, and checksum
144// DIAG_STAT, X_GYRO_LOW, X_GYRO_OUT, Y_GYRO_LOW, Y_GYRO_OUT, Z_GYRO_LOW,
145// Z_GYRO_OUT, X_ACCL_LOW, X_ACCL_OUT, Y_ACCL_LOW, Y_ACCL_OUT, Z_ACCL_LOW,
146// Z_ACCL_OUT, TEMP_OUT, DATA_CNTR, TIMESTAMP (32 bit), ENC1_POS, ENC2_POS,
147// CHECKSUM (32-bit)
148
149// the staging buffer gets updated everytime new data is received
150static uint8_t pi_staging_buffer[PI_NUM_ITEMS];
151// the data from the staging buffer is latched into the sending buffer while the
152// pi is reading
153static uint8_t pi_sending_buffer[PI_NUM_ITEMS];
154
155// for now just recieves zeros
156// but is useful because directing the dma to a nullptr messes up the transfer
157// finished interrupt
158static uint8_t pi_recieve_buffer[PI_NUM_ITEMS];
159
160static dma_channel_config pi_tx_config;
161static dma_channel_config pi_rx_config;
162static uint pi_dma_tx;
163static uint pi_dma_rx;
164
165// zeroed yaw from the latest message from the imu
166static double yaw = 0;
167static double yaw_rate = 0;
168
169// TODO: fields for the janky, not encapsulated zeroing function
170static double yaw_rate_offset = 0;
171static bool yaw_zeroed = false;
172
173static int16_t encoder1_count = 0;
174static int16_t encoder2_count = 0;
175
176static uint32_t data_collect_timestamp = 0;
177
Ravago Jones23109002022-02-04 15:50:50 -0800178// if we need to reset the imu
179static bool reset_imu = false;
180// number of consectuive checksums that are mismatched or zero
181static uint suspicious_checksums = 0;
182
Ravago Jonesb83957c2021-12-29 19:57:34 -0800183// useful debug counters
Ravago Jones23109002022-02-04 15:50:50 -0800184static uint imu_reset_count = 0;
185static uint checksum_mismatch_count = 0;
186static uint message_recieved_count = 0;
187static uint message_sent_count = 0;
Ravago Jonesb83957c2021-12-29 19:57:34 -0800188// the number of times we had to defer sending new data because another
189// transfer was still in progress
Ravago Jones23109002022-02-04 15:50:50 -0800190static uint timing_overrun_count = 0;
Ravago Jonesb83957c2021-12-29 19:57:34 -0800191
192// the time it takes from servicing DR_IMU to finishing the transfer to the pi
193static int send_time = 0;
194
195void data_ready();
196void maybe_send_pi_packet();
197
198void gpio_irq_handler(uint gpio, uint32_t events) {
James Kuszmaulc1741012022-02-19 17:49:27 -0800199 if (gpio == SYNC_IMU && (events & GPIO_IRQ_EDGE_RISE)) {
200 // Grab a timestamp for when the data sample was actually collected.
201 data_collect_timestamp = time_us_32();
202 }
Ravago Jonesb83957c2021-12-29 19:57:34 -0800203 if (gpio == DR_IMU && (events & GPIO_IRQ_EDGE_RISE)) {
204 data_ready();
205 }
206}
207
208static inline void cs_select() {
209 gpio_put(CS_IMU, 0); // Active low
210 sleep_us(1);
211}
212
213static inline void cs_deselect() { gpio_put(CS_IMU, 1); }
214
215static uint16_t read_register(uint8_t reg_low) {
216 // For this particular device, we send the device the register we want to read
217 // first, then subsequently read from the device.
218 uint16_t output;
219
220 // The low byte of the register is first in the IMU's memory
221 uint16_t reg = ((uint16_t)reg_low) << 8;
222
223 cs_select();
224 spi_write16_blocking(SPI_IMU, &reg, 1);
225 cs_deselect();
226 sleep_us(20); // wait the stall period
227 cs_select();
228 spi_read16_blocking(SPI_IMU, 0x0000, &output, 1);
229 cs_deselect();
230
231 return output;
232}
233
234static void write_register(uint8_t reg, uint16_t value) {
235 uint16_t low_byte = ((uint16_t)value) & 0xFF;
236 uint16_t high_byte = ((uint16_t)value) >> 8;
237
238 uint16_t command = (((uint16_t)reg) << 8) | low_byte | WRITE_BIT;
239
240 cs_select();
241 spi_write16_blocking(SPI_IMU, &command, 1);
242 cs_deselect();
243
244 sleep_us(20); // wait the stall period
245
246 command = ((((uint16_t)reg) + 1) << 8) | high_byte | WRITE_BIT;
247
248 cs_select();
249 spi_write16_blocking(SPI_IMU, &command, 1);
250 cs_deselect();
251}
252
253static void adis16505_reset() {
254 gpio_put(RST_IMU, 0); // Active low
255 sleep_ms(10);
256 gpio_put(RST_IMU, 1); // Active low
257 sleep_ms(310);
258}
259
260static uint32_t calculate_crc32(uint8_t *data, size_t len) {
261 uint32_t crc = 0xFFFFFFFF;
262 for (size_t i = 0; i < len; i++) {
263 crc = kCrc32Table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8);
264 }
265 return crc;
266}
267
Ravago Jones23109002022-02-04 15:50:50 -0800268static uint16_t check_checksum(uint16_t *buf) {
Ravago Jonesb83957c2021-12-29 19:57:34 -0800269 uint16_t sum = 0;
270 for (int i = 1; i < IMU_NUM_ITEMS - 1; i++) {
271 uint16_t low = buf[i] & 0xff;
272 uint16_t high = (buf[i] >> 8) & 0xff;
273
274 sum += high + low;
275 }
276
Ravago Jones23109002022-02-04 15:50:50 -0800277 return sum;
Ravago Jonesb83957c2021-12-29 19:57:34 -0800278}
279
280static void zero_yaw(double yaw) {
281 static double yaw_buffer[YAW_BUF_LEN];
282 static int num_items;
283
284 if (num_items < YAW_BUF_LEN) {
285 yaw_buffer[num_items] = yaw;
286 num_items++;
287 } else if (!yaw_zeroed) {
288 double sum = 0;
289 for (int i = 0; i < YAW_BUF_LEN; i++) {
290 sum += yaw_buffer[i];
291 }
292 yaw_rate_offset = -sum / YAW_BUF_LEN;
293 yaw = 0;
294 printf("offset: %f\n", yaw_rate_offset);
295 yaw_zeroed = true;
296 }
297}
298
299void pack_pi_packet() {
300 // zero the buffer
301 for (int i = 0; i < PI_NUM_ITEMS; i++) {
302 pi_staging_buffer[i] = 0;
303 }
304
305 // skip empty item
306 uint8_t *imu_packet = (uint8_t *)(imu_data_buffer + 1);
307 // skip empty item and checksum and convert to bytes
308 const size_t imu_packet_len = (IMU_NUM_ITEMS - 2) * sizeof(uint16_t);
309
310 memcpy(pi_staging_buffer, imu_packet, imu_packet_len);
311 memcpy(pi_staging_buffer + imu_packet_len, &data_collect_timestamp, 4);
312 memcpy(pi_staging_buffer + imu_packet_len + 4, &encoder1_count, 2);
313 memcpy(pi_staging_buffer + imu_packet_len + 6, &encoder2_count, 2);
314
315 // exclude the part of the buffer that will be the checksum
316 uint32_t crc = calculate_crc32(pi_staging_buffer, PI_NUM_ITEMS - 4);
317 memcpy(pi_staging_buffer + imu_packet_len + 8, &crc, 4);
318
319 static_assert(PI_NUM_ITEMS == imu_packet_len +
320 sizeof(data_collect_timestamp) +
321 sizeof(encoder1_count) +
322 sizeof(encoder2_count) + sizeof(crc),
323 "PI_NUM_ITEMS needs to be able to hold the imu message + the "
324 "timestamp + the encoders + the checksum");
325}
326
327void data_ready() {
Ravago Jonesb83957c2021-12-29 19:57:34 -0800328 // read encoders
329 quadrature_encoder_request_count(pio0, 0);
330 quadrature_encoder_request_count(pio0, 1);
331
332 cs_select();
333 dma_channel_configure(imu_dma_tx, &imu_tx_config,
334 &spi_get_hw(SPI_IMU)->dr, // write address
335 &imu_write_buf, // read address
336 IMU_NUM_ITEMS, // element count (each element is of
337 // size transfer_data_size)
338 false); // don't start yet
339 dma_channel_configure(imu_dma_rx, &imu_rx_config,
340 &imu_data_buffer, // write address
341 &spi_get_hw(SPI_IMU)->dr, // read address
342 IMU_NUM_ITEMS, // element count (each element is of
343 // size transfer_data_size)
344 false); // don't start yet
345 dma_start_channel_mask((1u << imu_dma_tx) | (1u << imu_dma_rx));
346
347 encoder1_count = quadrature_encoder_fetch_count(pio0, 0);
348 encoder2_count = quadrature_encoder_fetch_count(pio0, 1);
349}
350
351void imu_read_finished() {
352 cs_deselect();
353
354 // TODO: check status and if necessary set flag to reset in main loop
355
356 message_recieved_count++;
Ravago Jones23109002022-02-04 15:50:50 -0800357 uint16_t computed_checksum = check_checksum(imu_data_buffer);
358 uint16_t given_checksum = imu_data_buffer[IMU_NUM_ITEMS - 1];
359
360 if (computed_checksum != given_checksum) {
Ravago Jonesb83957c2021-12-29 19:57:34 -0800361 checksum_mismatch_count++;
Ravago Jones23109002022-02-04 15:50:50 -0800362 for (size_t i = 0; i < IMU_NUM_ITEMS; i++) {
363 // make it clear that this data is bad
364 imu_data_buffer[i] = 0;
365 }
366 // and set an unused bit of DIAG_STAT
367 imu_data_buffer[1] = 1u << 0;
Ravago Jonesb83957c2021-12-29 19:57:34 -0800368 } else {
369 static const double dt = 0.0005; // seconds
370 int32_t z_gyro_out;
371 memcpy(&z_gyro_out, imu_data_buffer + 6, 4);
372 yaw_rate = (double)z_gyro_out / 655360.0 + yaw_rate_offset; // degrees
373 yaw += yaw_rate * dt;
374
375 // 50% is 0; -2000 deg/sec to 2000 deg/sec
Ravago Jones0e86e242022-02-12 18:38:14 -0800376 double scaled_rate = (std::clamp(yaw_rate, -2000.0, 2000.0) / 4000.0 + 0.5);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800377
378 // 0 to 360
Ravago Jonesa23a7942022-02-12 18:24:57 -0800379 double wrapped_heading = fmod(yaw, 360);
380 if (wrapped_heading < 0) {
381 wrapped_heading = wrapped_heading + 360;
382 }
383
Ravago Jones0e86e242022-02-12 18:38:14 -0800384 double scaled_heading = wrapped_heading / 360.0;
385
386 constexpr double kScaledRangeLow = 0.1;
387 constexpr double kScaledRangeHigh = 0.9;
388
389 uint16_t heading_level =
390 (scaled_heading * (kScaledRangeHigh - kScaledRangeLow) +
391 kScaledRangeLow) *
392 PWM_TOP;
393 uint16_t rate_level =
394 (scaled_rate * (kScaledRangeHigh - kScaledRangeLow) + kScaledRangeLow) *
395 PWM_TOP;
Ravago Jonesb83957c2021-12-29 19:57:34 -0800396 pwm_set_gpio_level(HEADING_PWM, heading_level);
Ravago Jones0e86e242022-02-12 18:38:14 -0800397 pwm_set_gpio_level(RATE_PWM, rate_level);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800398 }
399
Ravago Jones23109002022-02-04 15:50:50 -0800400 // if 5 or more consecutive checksums are zero, then something weird is going
401 // on with the imu
402 if (computed_checksum != given_checksum || computed_checksum == 0 ||
403 given_checksum == 0) {
404 suspicious_checksums++;
405 } else {
406 suspicious_checksums = 0;
407 }
408
409 if (suspicious_checksums >= 5) {
410 reset_imu = true;
411 }
412
413 // fill out message and add it to the queue
414 pack_pi_packet();
415
Ravago Jonesb83957c2021-12-29 19:57:34 -0800416 // TODO: this has a sleep in it
417 // stay in sync with the pi by resetting the spi fifos each transfer
418 spi_init(SPI_PI, 2000 * 1000);
419 spi_set_slave(SPI_PI, true);
420 // these settings were the most stable even though the PI is using
421 // polarity 1 and phase 1
422 spi_set_format(SPI_PI, 8, SPI_CPOL_0, SPI_CPHA_1, SPI_MSB_FIRST);
423
424 maybe_send_pi_packet();
425
426 // clear the interrupt
427 dma_hw->ints0 = 1u << imu_dma_rx;
428}
429
430void maybe_send_pi_packet() {
431 // active low; if the pi isn't connected/booted, this will
432 // also look active
433 bool cs_asserted_or_unplugged = !gpio_get(CS_PI);
434
435 if (cs_asserted_or_unplugged) {
436 // the pi is still recieving something else from us
437 timing_overrun_count++;
438 return;
439 }
440
Ravago Jonesb83957c2021-12-29 19:57:34 -0800441 memcpy(pi_sending_buffer, pi_staging_buffer, PI_NUM_ITEMS);
442
443 dma_channel_configure(pi_dma_tx, &pi_tx_config,
444 &spi_get_hw(SPI_PI)->dr, // write address
445 &pi_sending_buffer, // read address
446 PI_NUM_ITEMS, // element count (each element is
447 // of size transfer_data_size)
448 false); // don't start yet
449 dma_channel_configure(pi_dma_rx, &pi_rx_config,
450 &pi_recieve_buffer, // write address
451 &spi_get_hw(SPI_PI)->dr, // read address
452 PI_NUM_ITEMS, // element count (each element is of
453 // size transfer_data_size)
454 false); // don't start yet
455
456 // start hardware calculation of the CRC-32; currently calculated in software
457 dma_sniffer_enable(pi_dma_tx, 0x0, true);
458 dma_hw->sniff_data = 0;
459
460 // start both at exactly the same time
461 dma_start_channel_mask((1u << pi_dma_tx) | (1u << pi_dma_rx));
Ravago Jones23109002022-02-04 15:50:50 -0800462 gpio_put(DR_PI, 1);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800463}
464
465void pi_transfer_finished() {
466 message_sent_count++;
467 gpio_put(DR_PI, 0);
468
469 send_time = time_us_32() - data_collect_timestamp;
470
471 dma_hw->ints1 = 1u << pi_dma_rx;
472}
473
Ravago Jones23109002022-02-04 15:50:50 -0800474void setup_adis16505() {
James Kuszmaulc1741012022-02-19 17:49:27 -0800475 // Disable the interrupts from the data-ready/sync pins to avoid interrupts
476 // while attempting to reset the IMU.
Ravago Jones23109002022-02-04 15:50:50 -0800477 gpio_set_irq_enabled(DR_IMU, GPIO_IRQ_EDGE_RISE, false);
James Kuszmaulc1741012022-02-19 17:49:27 -0800478 gpio_set_irq_enabled(SYNC_IMU, GPIO_IRQ_EDGE_RISE, false);
Ravago Jones23109002022-02-04 15:50:50 -0800479
480 while (true) {
481 adis16505_reset();
482 // See if SPI is working - interrogate the device for its product ID
483 // number, should be 0x4079
484 uint16_t id = read_register(PROD_ID);
485 if (id == EXPECTED_PROD_ID) {
486 printf("Product id: 0x%04x == expected 0x%04x\n", id, EXPECTED_PROD_ID);
487 break;
488 } else {
489 printf("Got 0x%04x for prod id, expected 0x%04x\ntrying again\n", id,
490 EXPECTED_PROD_ID);
491 }
492 }
493
494 uint16_t firmware_revision = read_register(FIRM_REV);
495 uint16_t firmware_day_month = read_register(FIRM_DM);
496 uint16_t firmware_year = read_register(FIRM_Y);
497 uint16_t serial_number = read_register(SERIAL_NUM);
498
499 printf(
500 "Firmware revision: 0x%04x, \nFirmware day month: 0x%04x, \nFirmware "
501 "year: "
502 "0x%04x, \nSerial number: 0x%04x, \n",
503 firmware_revision, firmware_day_month, firmware_year, serial_number);
504
505 // run self test
506 int num_failures = 0;
507 while (true) {
508 write_register(GLOB_CMD, 1u << 2);
509 sleep_ms(24);
510 uint16_t diag_stat = read_register(DIAG_STAT);
511
512 // check the sensor failure bit
513 bool sensor_failure = diag_stat & (1u << 5);
514 printf("Diag stat: 0b%016b, \n", diag_stat);
515
516 if (sensor_failure) {
517 num_failures++;
518 printf("%d failures, trying again\n", num_failures);
519 } else {
520 break;
521 }
522 }
523
524 write_register(FILT_CTRL, 0 /* no filtering */);
525 write_register(
526 MSC_CTRL,
527 (1u << 9) /* enable 32-bit mode for burst reads */ |
528 (0u << 8) /* send gyro and accelerometer data in burst mode */ |
529 (1u << 7) /* enable gyro linear g compensation */ |
530 (1u << 6) /* enable point of percussion alignment */ |
James Kuszmaulc1741012022-02-19 17:49:27 -0800531 (11u << 2) /* output sync mode (uses internal 2kHz clock) */ |
532 (1u << 1) /* sync polarity, active high */ |
Ravago Jones23109002022-02-04 15:50:50 -0800533 (1u << 0) /* data ready is active high */);
534 // Rate of the output will be 2000 / (DEC_RATE + 1) Hz.
535 write_register(DEC_RATE, 0 /* no decimation */);
536
537 sleep_us(200);
538
539 imu_reset_count++;
540
James Kuszmaulc1741012022-02-19 17:49:27 -0800541 gpio_set_irq_enabled(SYNC_IMU, GPIO_IRQ_EDGE_RISE, true);
Ravago Jones23109002022-02-04 15:50:50 -0800542 gpio_set_irq_enabled_with_callback(DR_IMU, GPIO_IRQ_EDGE_RISE, true,
543 &gpio_irq_handler);
544}
545
Ravago Jonesb83957c2021-12-29 19:57:34 -0800546int main() {
547 stdio_init_all();
548
549 // Use 1MHz with the IMU as that is the limit for burst mode.
550 spi_init(SPI_IMU, 1000 * 1000);
551 spi_set_format(SPI_IMU, 16, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
552 gpio_set_function(DOUT_IMU, GPIO_FUNC_SPI);
553 gpio_set_function(SCLK_IMU, GPIO_FUNC_SPI);
554 gpio_set_function(DIN_IMU, GPIO_FUNC_SPI);
555 // Make the SPI pins available to picotool
556 bi_decl(bi_3pins_with_func(DOUT_IMU, DIN_IMU, SCLK_IMU, GPIO_FUNC_SPI));
557
558 // Chip select is active-low, so we'll initialise it to a driven-high state
559 gpio_init(CS_IMU);
560 gpio_set_dir(CS_IMU, GPIO_OUT);
561 gpio_put(CS_IMU, 1);
562 // Make the CS pin available to picotool
563 bi_decl(bi_1pin_with_name(CS_IMU, "IMU CS"));
564
565 // Reset is active-low, so we'll initialise it to a driven-high state
566 gpio_init(RST_IMU);
567 gpio_set_dir(RST_IMU, GPIO_OUT);
568 gpio_put(RST_IMU, 1);
569 // Make the RST pin available to picotool
570 bi_decl(bi_1pin_with_name(RST_IMU, "IMU RESET"));
571
572 imu_dma_tx = dma_claim_unused_channel(true);
573 imu_dma_rx = dma_claim_unused_channel(true);
574
575 // We set the outbound DMA to transfer from a memory buffer to the SPI
576 // transmit FIFO paced by the SPI TX FIFO DREQ The default is for the read
577 // address to increment every element (in this case 2 bytes - DMA_SIZE_16) and
578 // for the write address to remain unchanged.
579
580 imu_tx_config = dma_channel_get_default_config(imu_dma_tx);
581 channel_config_set_transfer_data_size(&imu_tx_config, DMA_SIZE_16);
582 channel_config_set_dreq(&imu_tx_config, spi_get_dreq(SPI_IMU, true));
583 channel_config_set_read_increment(&imu_tx_config, true);
584 channel_config_set_write_increment(&imu_tx_config, false);
585
586 // We set the inbound DMA to transfer from the SPI receive FIFO to a memory
587 // buffer paced by the SPI RX FIFO DREQ We configure the read address to
588 // remain unchanged for each element, but the write address to increment (so
589 // data is written throughout the buffer)
590 imu_rx_config = dma_channel_get_default_config(imu_dma_rx);
591 channel_config_set_transfer_data_size(&imu_rx_config, DMA_SIZE_16);
592 channel_config_set_dreq(&imu_rx_config, spi_get_dreq(SPI_IMU, false));
593 channel_config_set_read_increment(&imu_rx_config, false);
594 channel_config_set_write_increment(&imu_rx_config, true);
595
596 // Tell the DMA to raise IRQ line 0 when the channel finishes a block
597 dma_channel_set_irq0_enabled(imu_dma_rx, true);
598
599 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
600 irq_set_exclusive_handler(DMA_IRQ_0, imu_read_finished);
601 irq_set_enabled(DMA_IRQ_0, true);
602
603 // Use 2MHz with the PI as that is the maximum speed for the pico
604 gpio_set_function(MISO_PI, GPIO_FUNC_SPI);
605 gpio_set_function(MOSI_PI, GPIO_FUNC_SPI);
606 gpio_set_function(SCK_PI, GPIO_FUNC_SPI);
607 gpio_set_function(CS_PI, GPIO_FUNC_SPI);
608 // Make the SPI pins available to picotool
609 bi_decl(bi_3pins_with_func(DOUT_IMU, DIN_IMU, SCLK_IMU, GPIO_FUNC_SPI));
610
611 gpio_init(DR_PI);
612 gpio_set_dir(DR_PI, GPIO_OUT);
613 gpio_put(DR_PI, 0);
614 // Make the CS pin available to picotool
615 bi_decl(bi_1pin_with_name(DR_PI, "DATA READY PI"));
616
617 pi_dma_tx = dma_claim_unused_channel(true);
618 pi_dma_rx = dma_claim_unused_channel(true);
619
620 // We set the outbound DMA to transfer from a memory buffer to the SPI
621 // transmit FIFO paced by the SPI TX FIFO DREQ The default is for the read
622 // address to increment every element (in this case 2 bytes - DMA_SIZE_16) and
623 // for the write address to remain unchanged.
624
625 pi_tx_config = dma_channel_get_default_config(pi_dma_tx);
626 channel_config_set_transfer_data_size(&pi_tx_config, DMA_SIZE_8);
627 channel_config_set_dreq(&pi_tx_config, spi_get_dreq(SPI_PI, true));
628 channel_config_set_read_increment(&pi_tx_config, true);
629 channel_config_set_write_increment(&pi_tx_config, false);
630
631 // We set the inbound DMA to transfer from the SPI receive FIFO to a memory
632 // buffer paced by the SPI RX FIFO DREQ We configure the read address to
633 // remain unchanged for each element, but the write address to increment (so
634 // data is written throughout the buffer)
635 pi_rx_config = dma_channel_get_default_config(pi_dma_rx);
636 channel_config_set_transfer_data_size(&pi_rx_config, DMA_SIZE_8);
637 channel_config_set_dreq(&pi_rx_config, spi_get_dreq(SPI_PI, false));
638 channel_config_set_read_increment(&pi_rx_config, false);
639 channel_config_set_write_increment(&pi_rx_config, true);
640
641 // Tell the DMA to raise IRQ line 1 when the channel finishes a block
642 dma_channel_set_irq1_enabled(pi_dma_rx, true);
643
644 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
645 irq_set_exclusive_handler(DMA_IRQ_1, pi_transfer_finished);
646 irq_set_enabled(DMA_IRQ_1, true);
647
648 /* All IRQ priorities are initialized to PICO_DEFAULT_IRQ_PRIORITY by the pico
James Kuszmaulc1741012022-02-19 17:49:27 -0800649 * runtime at startup. As such, their priorities will correspond to their
650 * IRQ numbers (See Table 80 in the rp2040 datasheet). The interrupts are
651 * listed highest priority to lowest below--i.e., the sync/data ready
652 * interrupts are currently at the lowest priority.
653 * TODO(james): In the nominal case, the GPIO interrupts should never
654 * interfere with the SPI data transfer, but we may still want to up the
655 * GPIO priority using irq_set_priority() so that we are guaranteed good
656 * timestamps.
Ravago Jonesb83957c2021-12-29 19:57:34 -0800657 *
658 * Handler | Interrupt | Cause of interrupt
659 * --------------------|--------------|---------------------------------------
660 * imu_read_finished | DMA_IRQ_0 | When the dma read from the imu is done
661 * pi_transfer_finished| DMA_IRQ_1 | When the dma read to the pi is
662 * done data_ready | IO_IRQ_BANK0 | On the rising edge of DR_IMU
James Kuszmaulc1741012022-02-19 17:49:27 -0800663 * sync pin high | IO_IRQ_BANK0 | On the rising edge of SYNC_IMU
Ravago Jonesb83957c2021-12-29 19:57:34 -0800664 */
665
666 // Tell the GPIOs they are allocated to PWM
667 gpio_set_function(HEADING_PWM, GPIO_FUNC_PWM);
668 gpio_set_function(RATE_PWM, GPIO_FUNC_PWM);
669
670 // Find out which PWM slice is connected to each gpio pin
671 uint heading_slice = pwm_gpio_to_slice_num(HEADING_PWM);
672 uint rate_slice = pwm_gpio_to_slice_num(RATE_PWM);
673
674 /* frequency_pwm = f_sys / ((TOP + 1) * (CSR_PHASE_CORRECT + 1) * (DIV_INT +
675 * DIV_FRAC / 16))
676 *
677 * f_sys = 125 mhz
678 * CSR_PHASE_CORRECT = 0; no phase correct
679 * TARGET_FREQ = 200 hz
680 *
681 * 125 mhz / x = 200 hz * 62500
682 *
683 * TOP = 62499
684 * DIV_INT = 10
685 */
686
687 float divisor = clock_get_hz(clk_sys) / (PWM_TOP + 1) / PWM_FREQ_HZ;
688
689 pwm_config cfg = pwm_get_default_config();
690 pwm_config_set_clkdiv_mode(&cfg, PWM_DIV_FREE_RUNNING);
691 pwm_config_set_clkdiv(&cfg, divisor);
692 pwm_config_set_wrap(&cfg, PWM_TOP);
693
694 pwm_init(heading_slice, &cfg, true);
695 pwm_init(rate_slice, &cfg, true);
696
697 // the two state machine instances use the same program memory from pio0
698 uint offset = pio_add_program(pio0, &quadrature_encoder_program);
699 quadrature_encoder_program_init(pio0, 0, offset, ENC1_A, 0);
700 quadrature_encoder_program_init(pio0, 1, offset, ENC2_A, 0);
701
702 sleep_ms(3 * 1000);
703
704 printf("Hello ADIS16505\n");
705
706 printf(
707 "System clock: %d hz\n"
708 "PWM target frequency: %d hz, PWM clock divisor: "
709 "%f, PWM TOP: %d\n",
710 clock_get_hz(clk_sys), PWM_FREQ_HZ, divisor, PWM_TOP);
711
Ravago Jones23109002022-02-04 15:50:50 -0800712 setup_adis16505();
Ravago Jonesb83957c2021-12-29 19:57:34 -0800713
714 while (!yaw_zeroed) {
715 dma_channel_wait_for_finish_blocking(imu_dma_rx);
716 sleep_us(100);
717 zero_yaw(yaw_rate);
718 }
719
720 printf("Press q to enter bootloader\n");
721
722 while (1) {
723 dma_channel_wait_for_finish_blocking(imu_dma_rx);
724 // we want the interrupts to happen before or during the sleep so that we
725 // can get a good picture of what's going on without things moving around
726 sleep_us(100);
727
Ravago Jones23109002022-02-04 15:50:50 -0800728 if (reset_imu) {
729 printf("Triggered IMU reset, resetting\n");
730 setup_adis16505();
731 reset_imu = false;
732 }
733
Ravago Jonesb83957c2021-12-29 19:57:34 -0800734 // debug
735 // one printf is faster than many printfs
736 printf(
737 "Z pos is %f encoder: %d %d\n"
738 "Num failed checksums: %d, Total messages recieved: %d,\n"
739 "Num messages to pi: %d, Timing overrun count: %d,\n"
Ravago Jones23109002022-02-04 15:50:50 -0800740 "Send time: %d us, suspicious checksum count: %u,\n"
741 "IMU reset count: %d, checksum: %u,\n",
Ravago Jonesb83957c2021-12-29 19:57:34 -0800742 yaw, encoder1_count, encoder2_count, checksum_mismatch_count,
743 message_recieved_count, message_sent_count, timing_overrun_count,
Ravago Jones23109002022-02-04 15:50:50 -0800744 send_time, suspicious_checksums, imu_reset_count,
745 imu_data_buffer[IMU_NUM_ITEMS - 1]);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800746
747 // allow the user to enter the bootloader without removing power or having
748 // to install a reset button
749 char user_input = getchar_timeout_us(0);
750 if (user_input == 'q') {
751 printf("Going down! entering bootloader\n");
752 reset_usb_boot(0, 0);
753 }
754
755 sleep_ms(50);
756 }
757
758 printf("All good\n");
759 dma_channel_unclaim(imu_dma_rx);
760 dma_channel_unclaim(imu_dma_tx);
761 dma_channel_unclaim(pi_dma_rx);
762 dma_channel_unclaim(pi_dma_tx);
763 return 0;
764}