blob: f4943b03f1a8996536adee5612d10ba326f0fbde [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
Ravago Jones8f9ed852023-03-04 21:36:37 -0800165// yaw velocity from the latest message from the imu
Ravago Jonesb83957c2021-12-29 19:57:34 -0800166static double yaw_rate = 0;
167
Ravago Jonesb83957c2021-12-29 19:57:34 -0800168static int16_t encoder1_count = 0;
169static int16_t encoder2_count = 0;
170
171static uint32_t data_collect_timestamp = 0;
172
Ravago Jones23109002022-02-04 15:50:50 -0800173// if we need to reset the imu
174static bool reset_imu = false;
175// number of consectuive checksums that are mismatched or zero
176static uint suspicious_checksums = 0;
177
Ravago Jonesb83957c2021-12-29 19:57:34 -0800178// useful debug counters
Ravago Jones23109002022-02-04 15:50:50 -0800179static uint imu_reset_count = 0;
180static uint checksum_mismatch_count = 0;
181static uint message_recieved_count = 0;
182static uint message_sent_count = 0;
Ravago Jonesb83957c2021-12-29 19:57:34 -0800183// the number of times we had to defer sending new data because another
184// transfer was still in progress
Ravago Jones23109002022-02-04 15:50:50 -0800185static uint timing_overrun_count = 0;
Ravago Jonesb83957c2021-12-29 19:57:34 -0800186
187// the time it takes from servicing DR_IMU to finishing the transfer to the pi
188static int send_time = 0;
189
190void data_ready();
191void maybe_send_pi_packet();
192
193void gpio_irq_handler(uint gpio, uint32_t events) {
James Kuszmaulc1741012022-02-19 17:49:27 -0800194 if (gpio == SYNC_IMU && (events & GPIO_IRQ_EDGE_RISE)) {
195 // Grab a timestamp for when the data sample was actually collected.
196 data_collect_timestamp = time_us_32();
197 }
Ravago Jonesb83957c2021-12-29 19:57:34 -0800198 if (gpio == DR_IMU && (events & GPIO_IRQ_EDGE_RISE)) {
199 data_ready();
200 }
201}
202
203static inline void cs_select() {
204 gpio_put(CS_IMU, 0); // Active low
205 sleep_us(1);
206}
207
208static inline void cs_deselect() { gpio_put(CS_IMU, 1); }
209
210static uint16_t read_register(uint8_t reg_low) {
211 // For this particular device, we send the device the register we want to read
212 // first, then subsequently read from the device.
213 uint16_t output;
214
215 // The low byte of the register is first in the IMU's memory
216 uint16_t reg = ((uint16_t)reg_low) << 8;
217
218 cs_select();
219 spi_write16_blocking(SPI_IMU, &reg, 1);
220 cs_deselect();
221 sleep_us(20); // wait the stall period
222 cs_select();
223 spi_read16_blocking(SPI_IMU, 0x0000, &output, 1);
224 cs_deselect();
225
226 return output;
227}
228
229static void write_register(uint8_t reg, uint16_t value) {
230 uint16_t low_byte = ((uint16_t)value) & 0xFF;
231 uint16_t high_byte = ((uint16_t)value) >> 8;
232
233 uint16_t command = (((uint16_t)reg) << 8) | low_byte | WRITE_BIT;
234
235 cs_select();
236 spi_write16_blocking(SPI_IMU, &command, 1);
237 cs_deselect();
238
239 sleep_us(20); // wait the stall period
240
241 command = ((((uint16_t)reg) + 1) << 8) | high_byte | WRITE_BIT;
242
243 cs_select();
244 spi_write16_blocking(SPI_IMU, &command, 1);
245 cs_deselect();
246}
247
248static void adis16505_reset() {
249 gpio_put(RST_IMU, 0); // Active low
250 sleep_ms(10);
251 gpio_put(RST_IMU, 1); // Active low
252 sleep_ms(310);
253}
254
255static uint32_t calculate_crc32(uint8_t *data, size_t len) {
256 uint32_t crc = 0xFFFFFFFF;
257 for (size_t i = 0; i < len; i++) {
258 crc = kCrc32Table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8);
259 }
260 return crc;
261}
262
Ravago Jones23109002022-02-04 15:50:50 -0800263static uint16_t check_checksum(uint16_t *buf) {
Ravago Jonesb83957c2021-12-29 19:57:34 -0800264 uint16_t sum = 0;
265 for (int i = 1; i < IMU_NUM_ITEMS - 1; i++) {
266 uint16_t low = buf[i] & 0xff;
267 uint16_t high = (buf[i] >> 8) & 0xff;
268
269 sum += high + low;
270 }
271
Ravago Jones23109002022-02-04 15:50:50 -0800272 return sum;
Ravago Jonesb83957c2021-12-29 19:57:34 -0800273}
274
Ravago Jonesb83957c2021-12-29 19:57:34 -0800275void pack_pi_packet() {
276 // zero the buffer
277 for (int i = 0; i < PI_NUM_ITEMS; i++) {
278 pi_staging_buffer[i] = 0;
279 }
280
281 // skip empty item
282 uint8_t *imu_packet = (uint8_t *)(imu_data_buffer + 1);
283 // skip empty item and checksum and convert to bytes
284 const size_t imu_packet_len = (IMU_NUM_ITEMS - 2) * sizeof(uint16_t);
285
286 memcpy(pi_staging_buffer, imu_packet, imu_packet_len);
287 memcpy(pi_staging_buffer + imu_packet_len, &data_collect_timestamp, 4);
288 memcpy(pi_staging_buffer + imu_packet_len + 4, &encoder1_count, 2);
289 memcpy(pi_staging_buffer + imu_packet_len + 6, &encoder2_count, 2);
290
291 // exclude the part of the buffer that will be the checksum
292 uint32_t crc = calculate_crc32(pi_staging_buffer, PI_NUM_ITEMS - 4);
293 memcpy(pi_staging_buffer + imu_packet_len + 8, &crc, 4);
294
295 static_assert(PI_NUM_ITEMS == imu_packet_len +
296 sizeof(data_collect_timestamp) +
297 sizeof(encoder1_count) +
298 sizeof(encoder2_count) + sizeof(crc),
299 "PI_NUM_ITEMS needs to be able to hold the imu message + the "
300 "timestamp + the encoders + the checksum");
301}
302
303void data_ready() {
Ravago Jonesb83957c2021-12-29 19:57:34 -0800304 // read encoders
305 quadrature_encoder_request_count(pio0, 0);
306 quadrature_encoder_request_count(pio0, 1);
307
308 cs_select();
309 dma_channel_configure(imu_dma_tx, &imu_tx_config,
310 &spi_get_hw(SPI_IMU)->dr, // write address
311 &imu_write_buf, // read address
312 IMU_NUM_ITEMS, // element count (each element is of
313 // size transfer_data_size)
314 false); // don't start yet
315 dma_channel_configure(imu_dma_rx, &imu_rx_config,
316 &imu_data_buffer, // write address
317 &spi_get_hw(SPI_IMU)->dr, // read address
318 IMU_NUM_ITEMS, // element count (each element is of
319 // size transfer_data_size)
320 false); // don't start yet
321 dma_start_channel_mask((1u << imu_dma_tx) | (1u << imu_dma_rx));
322
323 encoder1_count = quadrature_encoder_fetch_count(pio0, 0);
324 encoder2_count = quadrature_encoder_fetch_count(pio0, 1);
325}
326
327void imu_read_finished() {
328 cs_deselect();
329
330 // TODO: check status and if necessary set flag to reset in main loop
331
332 message_recieved_count++;
Ravago Jones23109002022-02-04 15:50:50 -0800333 uint16_t computed_checksum = check_checksum(imu_data_buffer);
334 uint16_t given_checksum = imu_data_buffer[IMU_NUM_ITEMS - 1];
335
336 if (computed_checksum != given_checksum) {
Ravago Jonesb83957c2021-12-29 19:57:34 -0800337 checksum_mismatch_count++;
Ravago Jones23109002022-02-04 15:50:50 -0800338 for (size_t i = 0; i < IMU_NUM_ITEMS; i++) {
339 // make it clear that this data is bad
340 imu_data_buffer[i] = 0;
341 }
342 // and set an unused bit of DIAG_STAT
343 imu_data_buffer[1] = 1u << 0;
Ravago Jonesb83957c2021-12-29 19:57:34 -0800344 } else {
Ravago Jonesb83957c2021-12-29 19:57:34 -0800345 int32_t z_gyro_out;
346 memcpy(&z_gyro_out, imu_data_buffer + 6, 4);
Ravago Jones8f9ed852023-03-04 21:36:37 -0800347 yaw_rate = (double)z_gyro_out / 655360.0; // degrees
Ravago Jonesb83957c2021-12-29 19:57:34 -0800348
349 // 50% is 0; -2000 deg/sec to 2000 deg/sec
Ravago Jones0e86e242022-02-12 18:38:14 -0800350 double scaled_rate = (std::clamp(yaw_rate, -2000.0, 2000.0) / 4000.0 + 0.5);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800351
Ravago Jones0e86e242022-02-12 18:38:14 -0800352 constexpr double kScaledRangeLow = 0.1;
353 constexpr double kScaledRangeHigh = 0.9;
354
Ravago Jones0e86e242022-02-12 18:38:14 -0800355 uint16_t rate_level =
356 (scaled_rate * (kScaledRangeHigh - kScaledRangeLow) + kScaledRangeLow) *
357 PWM_TOP;
Ravago Jones0e86e242022-02-12 18:38:14 -0800358 pwm_set_gpio_level(RATE_PWM, rate_level);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800359 }
360
Ravago Jones23109002022-02-04 15:50:50 -0800361 // if 5 or more consecutive checksums are zero, then something weird is going
362 // on with the imu
363 if (computed_checksum != given_checksum || computed_checksum == 0 ||
364 given_checksum == 0) {
365 suspicious_checksums++;
366 } else {
367 suspicious_checksums = 0;
368 }
369
370 if (suspicious_checksums >= 5) {
371 reset_imu = true;
372 }
373
374 // fill out message and add it to the queue
375 pack_pi_packet();
376
Ravago Jonesb83957c2021-12-29 19:57:34 -0800377 // TODO: this has a sleep in it
378 // stay in sync with the pi by resetting the spi fifos each transfer
379 spi_init(SPI_PI, 2000 * 1000);
380 spi_set_slave(SPI_PI, true);
381 // these settings were the most stable even though the PI is using
382 // polarity 1 and phase 1
383 spi_set_format(SPI_PI, 8, SPI_CPOL_0, SPI_CPHA_1, SPI_MSB_FIRST);
384
385 maybe_send_pi_packet();
386
387 // clear the interrupt
388 dma_hw->ints0 = 1u << imu_dma_rx;
389}
390
391void maybe_send_pi_packet() {
392 // active low; if the pi isn't connected/booted, this will
393 // also look active
394 bool cs_asserted_or_unplugged = !gpio_get(CS_PI);
395
396 if (cs_asserted_or_unplugged) {
397 // the pi is still recieving something else from us
398 timing_overrun_count++;
399 return;
400 }
401
Ravago Jonesb83957c2021-12-29 19:57:34 -0800402 memcpy(pi_sending_buffer, pi_staging_buffer, PI_NUM_ITEMS);
403
404 dma_channel_configure(pi_dma_tx, &pi_tx_config,
405 &spi_get_hw(SPI_PI)->dr, // write address
406 &pi_sending_buffer, // read address
407 PI_NUM_ITEMS, // element count (each element is
408 // of size transfer_data_size)
409 false); // don't start yet
410 dma_channel_configure(pi_dma_rx, &pi_rx_config,
411 &pi_recieve_buffer, // write address
412 &spi_get_hw(SPI_PI)->dr, // read address
413 PI_NUM_ITEMS, // element count (each element is of
414 // size transfer_data_size)
415 false); // don't start yet
416
417 // start hardware calculation of the CRC-32; currently calculated in software
418 dma_sniffer_enable(pi_dma_tx, 0x0, true);
419 dma_hw->sniff_data = 0;
420
421 // start both at exactly the same time
422 dma_start_channel_mask((1u << pi_dma_tx) | (1u << pi_dma_rx));
Ravago Jones23109002022-02-04 15:50:50 -0800423 gpio_put(DR_PI, 1);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800424}
425
426void pi_transfer_finished() {
427 message_sent_count++;
428 gpio_put(DR_PI, 0);
429
430 send_time = time_us_32() - data_collect_timestamp;
431
432 dma_hw->ints1 = 1u << pi_dma_rx;
433}
434
Ravago Jones23109002022-02-04 15:50:50 -0800435void setup_adis16505() {
James Kuszmaulc1741012022-02-19 17:49:27 -0800436 // Disable the interrupts from the data-ready/sync pins to avoid interrupts
437 // while attempting to reset the IMU.
Ravago Jones23109002022-02-04 15:50:50 -0800438 gpio_set_irq_enabled(DR_IMU, GPIO_IRQ_EDGE_RISE, false);
James Kuszmaulc1741012022-02-19 17:49:27 -0800439 gpio_set_irq_enabled(SYNC_IMU, GPIO_IRQ_EDGE_RISE, false);
Ravago Jones23109002022-02-04 15:50:50 -0800440
441 while (true) {
442 adis16505_reset();
443 // See if SPI is working - interrogate the device for its product ID
444 // number, should be 0x4079
445 uint16_t id = read_register(PROD_ID);
446 if (id == EXPECTED_PROD_ID) {
447 printf("Product id: 0x%04x == expected 0x%04x\n", id, EXPECTED_PROD_ID);
448 break;
449 } else {
450 printf("Got 0x%04x for prod id, expected 0x%04x\ntrying again\n", id,
451 EXPECTED_PROD_ID);
452 }
453 }
454
455 uint16_t firmware_revision = read_register(FIRM_REV);
456 uint16_t firmware_day_month = read_register(FIRM_DM);
457 uint16_t firmware_year = read_register(FIRM_Y);
458 uint16_t serial_number = read_register(SERIAL_NUM);
459
460 printf(
461 "Firmware revision: 0x%04x, \nFirmware day month: 0x%04x, \nFirmware "
462 "year: "
463 "0x%04x, \nSerial number: 0x%04x, \n",
464 firmware_revision, firmware_day_month, firmware_year, serial_number);
465
466 // run self test
467 int num_failures = 0;
468 while (true) {
469 write_register(GLOB_CMD, 1u << 2);
470 sleep_ms(24);
471 uint16_t diag_stat = read_register(DIAG_STAT);
472
473 // check the sensor failure bit
474 bool sensor_failure = diag_stat & (1u << 5);
475 printf("Diag stat: 0b%016b, \n", diag_stat);
476
477 if (sensor_failure) {
478 num_failures++;
479 printf("%d failures, trying again\n", num_failures);
480 } else {
481 break;
482 }
483 }
484
485 write_register(FILT_CTRL, 0 /* no filtering */);
486 write_register(
487 MSC_CTRL,
488 (1u << 9) /* enable 32-bit mode for burst reads */ |
489 (0u << 8) /* send gyro and accelerometer data in burst mode */ |
490 (1u << 7) /* enable gyro linear g compensation */ |
491 (1u << 6) /* enable point of percussion alignment */ |
James Kuszmaulc1741012022-02-19 17:49:27 -0800492 (11u << 2) /* output sync mode (uses internal 2kHz clock) */ |
493 (1u << 1) /* sync polarity, active high */ |
Ravago Jones23109002022-02-04 15:50:50 -0800494 (1u << 0) /* data ready is active high */);
495 // Rate of the output will be 2000 / (DEC_RATE + 1) Hz.
496 write_register(DEC_RATE, 0 /* no decimation */);
497
498 sleep_us(200);
499
500 imu_reset_count++;
501
James Kuszmaulc1741012022-02-19 17:49:27 -0800502 gpio_set_irq_enabled(SYNC_IMU, GPIO_IRQ_EDGE_RISE, true);
Ravago Jones23109002022-02-04 15:50:50 -0800503 gpio_set_irq_enabled_with_callback(DR_IMU, GPIO_IRQ_EDGE_RISE, true,
504 &gpio_irq_handler);
505}
506
Ravago Jonesb83957c2021-12-29 19:57:34 -0800507int main() {
508 stdio_init_all();
509
510 // Use 1MHz with the IMU as that is the limit for burst mode.
511 spi_init(SPI_IMU, 1000 * 1000);
512 spi_set_format(SPI_IMU, 16, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
513 gpio_set_function(DOUT_IMU, GPIO_FUNC_SPI);
514 gpio_set_function(SCLK_IMU, GPIO_FUNC_SPI);
515 gpio_set_function(DIN_IMU, GPIO_FUNC_SPI);
516 // Make the SPI pins available to picotool
517 bi_decl(bi_3pins_with_func(DOUT_IMU, DIN_IMU, SCLK_IMU, GPIO_FUNC_SPI));
518
519 // Chip select is active-low, so we'll initialise it to a driven-high state
520 gpio_init(CS_IMU);
521 gpio_set_dir(CS_IMU, GPIO_OUT);
522 gpio_put(CS_IMU, 1);
523 // Make the CS pin available to picotool
524 bi_decl(bi_1pin_with_name(CS_IMU, "IMU CS"));
525
526 // Reset is active-low, so we'll initialise it to a driven-high state
527 gpio_init(RST_IMU);
528 gpio_set_dir(RST_IMU, GPIO_OUT);
529 gpio_put(RST_IMU, 1);
530 // Make the RST pin available to picotool
531 bi_decl(bi_1pin_with_name(RST_IMU, "IMU RESET"));
532
533 imu_dma_tx = dma_claim_unused_channel(true);
534 imu_dma_rx = dma_claim_unused_channel(true);
535
536 // We set the outbound DMA to transfer from a memory buffer to the SPI
537 // transmit FIFO paced by the SPI TX FIFO DREQ The default is for the read
538 // address to increment every element (in this case 2 bytes - DMA_SIZE_16) and
539 // for the write address to remain unchanged.
540
541 imu_tx_config = dma_channel_get_default_config(imu_dma_tx);
542 channel_config_set_transfer_data_size(&imu_tx_config, DMA_SIZE_16);
543 channel_config_set_dreq(&imu_tx_config, spi_get_dreq(SPI_IMU, true));
544 channel_config_set_read_increment(&imu_tx_config, true);
545 channel_config_set_write_increment(&imu_tx_config, false);
546
547 // We set the inbound DMA to transfer from the SPI receive FIFO to a memory
548 // buffer paced by the SPI RX FIFO DREQ We configure the read address to
549 // remain unchanged for each element, but the write address to increment (so
550 // data is written throughout the buffer)
551 imu_rx_config = dma_channel_get_default_config(imu_dma_rx);
552 channel_config_set_transfer_data_size(&imu_rx_config, DMA_SIZE_16);
553 channel_config_set_dreq(&imu_rx_config, spi_get_dreq(SPI_IMU, false));
554 channel_config_set_read_increment(&imu_rx_config, false);
555 channel_config_set_write_increment(&imu_rx_config, true);
556
557 // Tell the DMA to raise IRQ line 0 when the channel finishes a block
558 dma_channel_set_irq0_enabled(imu_dma_rx, true);
559
560 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
561 irq_set_exclusive_handler(DMA_IRQ_0, imu_read_finished);
562 irq_set_enabled(DMA_IRQ_0, true);
563
564 // Use 2MHz with the PI as that is the maximum speed for the pico
565 gpio_set_function(MISO_PI, GPIO_FUNC_SPI);
566 gpio_set_function(MOSI_PI, GPIO_FUNC_SPI);
567 gpio_set_function(SCK_PI, GPIO_FUNC_SPI);
568 gpio_set_function(CS_PI, GPIO_FUNC_SPI);
569 // Make the SPI pins available to picotool
570 bi_decl(bi_3pins_with_func(DOUT_IMU, DIN_IMU, SCLK_IMU, GPIO_FUNC_SPI));
571
572 gpio_init(DR_PI);
573 gpio_set_dir(DR_PI, GPIO_OUT);
574 gpio_put(DR_PI, 0);
575 // Make the CS pin available to picotool
576 bi_decl(bi_1pin_with_name(DR_PI, "DATA READY PI"));
577
578 pi_dma_tx = dma_claim_unused_channel(true);
579 pi_dma_rx = dma_claim_unused_channel(true);
580
581 // We set the outbound DMA to transfer from a memory buffer to the SPI
582 // transmit FIFO paced by the SPI TX FIFO DREQ The default is for the read
583 // address to increment every element (in this case 2 bytes - DMA_SIZE_16) and
584 // for the write address to remain unchanged.
585
586 pi_tx_config = dma_channel_get_default_config(pi_dma_tx);
587 channel_config_set_transfer_data_size(&pi_tx_config, DMA_SIZE_8);
588 channel_config_set_dreq(&pi_tx_config, spi_get_dreq(SPI_PI, true));
589 channel_config_set_read_increment(&pi_tx_config, true);
590 channel_config_set_write_increment(&pi_tx_config, false);
591
592 // We set the inbound DMA to transfer from the SPI receive FIFO to a memory
593 // buffer paced by the SPI RX FIFO DREQ We configure the read address to
594 // remain unchanged for each element, but the write address to increment (so
595 // data is written throughout the buffer)
596 pi_rx_config = dma_channel_get_default_config(pi_dma_rx);
597 channel_config_set_transfer_data_size(&pi_rx_config, DMA_SIZE_8);
598 channel_config_set_dreq(&pi_rx_config, spi_get_dreq(SPI_PI, false));
599 channel_config_set_read_increment(&pi_rx_config, false);
600 channel_config_set_write_increment(&pi_rx_config, true);
601
602 // Tell the DMA to raise IRQ line 1 when the channel finishes a block
603 dma_channel_set_irq1_enabled(pi_dma_rx, true);
604
605 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
606 irq_set_exclusive_handler(DMA_IRQ_1, pi_transfer_finished);
607 irq_set_enabled(DMA_IRQ_1, true);
608
609 /* All IRQ priorities are initialized to PICO_DEFAULT_IRQ_PRIORITY by the pico
James Kuszmaulc1741012022-02-19 17:49:27 -0800610 * runtime at startup. As such, their priorities will correspond to their
611 * IRQ numbers (See Table 80 in the rp2040 datasheet). The interrupts are
612 * listed highest priority to lowest below--i.e., the sync/data ready
613 * interrupts are currently at the lowest priority.
614 * TODO(james): In the nominal case, the GPIO interrupts should never
615 * interfere with the SPI data transfer, but we may still want to up the
616 * GPIO priority using irq_set_priority() so that we are guaranteed good
617 * timestamps.
Ravago Jonesb83957c2021-12-29 19:57:34 -0800618 *
619 * Handler | Interrupt | Cause of interrupt
620 * --------------------|--------------|---------------------------------------
621 * imu_read_finished | DMA_IRQ_0 | When the dma read from the imu is done
622 * pi_transfer_finished| DMA_IRQ_1 | When the dma read to the pi is
623 * done data_ready | IO_IRQ_BANK0 | On the rising edge of DR_IMU
James Kuszmaulc1741012022-02-19 17:49:27 -0800624 * sync pin high | IO_IRQ_BANK0 | On the rising edge of SYNC_IMU
Ravago Jonesb83957c2021-12-29 19:57:34 -0800625 */
626
627 // Tell the GPIOs they are allocated to PWM
628 gpio_set_function(HEADING_PWM, GPIO_FUNC_PWM);
629 gpio_set_function(RATE_PWM, GPIO_FUNC_PWM);
630
631 // Find out which PWM slice is connected to each gpio pin
632 uint heading_slice = pwm_gpio_to_slice_num(HEADING_PWM);
633 uint rate_slice = pwm_gpio_to_slice_num(RATE_PWM);
634
635 /* frequency_pwm = f_sys / ((TOP + 1) * (CSR_PHASE_CORRECT + 1) * (DIV_INT +
636 * DIV_FRAC / 16))
637 *
638 * f_sys = 125 mhz
639 * CSR_PHASE_CORRECT = 0; no phase correct
640 * TARGET_FREQ = 200 hz
641 *
642 * 125 mhz / x = 200 hz * 62500
643 *
644 * TOP = 62499
645 * DIV_INT = 10
646 */
647
648 float divisor = clock_get_hz(clk_sys) / (PWM_TOP + 1) / PWM_FREQ_HZ;
649
650 pwm_config cfg = pwm_get_default_config();
651 pwm_config_set_clkdiv_mode(&cfg, PWM_DIV_FREE_RUNNING);
652 pwm_config_set_clkdiv(&cfg, divisor);
653 pwm_config_set_wrap(&cfg, PWM_TOP);
654
655 pwm_init(heading_slice, &cfg, true);
656 pwm_init(rate_slice, &cfg, true);
657
658 // the two state machine instances use the same program memory from pio0
659 uint offset = pio_add_program(pio0, &quadrature_encoder_program);
660 quadrature_encoder_program_init(pio0, 0, offset, ENC1_A, 0);
661 quadrature_encoder_program_init(pio0, 1, offset, ENC2_A, 0);
662
663 sleep_ms(3 * 1000);
664
665 printf("Hello ADIS16505\n");
666
667 printf(
668 "System clock: %d hz\n"
669 "PWM target frequency: %d hz, PWM clock divisor: "
670 "%f, PWM TOP: %d\n",
671 clock_get_hz(clk_sys), PWM_FREQ_HZ, divisor, PWM_TOP);
672
Ravago Jones23109002022-02-04 15:50:50 -0800673 setup_adis16505();
Ravago Jonesb83957c2021-12-29 19:57:34 -0800674
Ravago Jonesb83957c2021-12-29 19:57:34 -0800675 printf("Press q to enter bootloader\n");
676
677 while (1) {
678 dma_channel_wait_for_finish_blocking(imu_dma_rx);
679 // we want the interrupts to happen before or during the sleep so that we
680 // can get a good picture of what's going on without things moving around
681 sleep_us(100);
682
Ravago Jones23109002022-02-04 15:50:50 -0800683 if (reset_imu) {
684 printf("Triggered IMU reset, resetting\n");
685 setup_adis16505();
686 reset_imu = false;
687 }
688
Ravago Jonesb83957c2021-12-29 19:57:34 -0800689 // debug
690 // one printf is faster than many printfs
691 printf(
Ravago Jones8f9ed852023-03-04 21:36:37 -0800692 "z vel: %f, encoder: %d %d\n"
Ravago Jonesb83957c2021-12-29 19:57:34 -0800693 "Num failed checksums: %d, Total messages recieved: %d,\n"
694 "Num messages to pi: %d, Timing overrun count: %d,\n"
Ravago Jones23109002022-02-04 15:50:50 -0800695 "Send time: %d us, suspicious checksum count: %u,\n"
696 "IMU reset count: %d, checksum: %u,\n",
Ravago Jones8f9ed852023-03-04 21:36:37 -0800697 yaw_rate, encoder1_count, encoder2_count, checksum_mismatch_count,
Ravago Jonesb83957c2021-12-29 19:57:34 -0800698 message_recieved_count, message_sent_count, timing_overrun_count,
Ravago Jones23109002022-02-04 15:50:50 -0800699 send_time, suspicious_checksums, imu_reset_count,
700 imu_data_buffer[IMU_NUM_ITEMS - 1]);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800701
702 // allow the user to enter the bootloader without removing power or having
703 // to install a reset button
704 char user_input = getchar_timeout_us(0);
705 if (user_input == 'q') {
706 printf("Going down! entering bootloader\n");
707 reset_usb_boot(0, 0);
708 }
709
710 sleep_ms(50);
711 }
712
713 printf("All good\n");
714 dma_channel_unclaim(imu_dma_rx);
715 dma_channel_unclaim(imu_dma_tx);
716 dma_channel_unclaim(pi_dma_rx);
717 dma_channel_unclaim(pi_dma_tx);
718 return 0;
719}