blob: 9ed77a9c3810d57e3e0de01444360f7502d1cac3 [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
376 uint16_t rate_level =
377 (std::clamp(yaw_rate, -2000.0, 2000.0) / 4000.0 + 0.5) * PWM_TOP;
378 pwm_set_gpio_level(RATE_PWM, rate_level);
379
380 // 0 to 360
Ravago Jonesa23a7942022-02-12 18:24:57 -0800381 double wrapped_heading = fmod(yaw, 360);
382 if (wrapped_heading < 0) {
383 wrapped_heading = wrapped_heading + 360;
384 }
385
386 uint16_t heading_level = (int16_t)(wrapped_heading / 360.0 * PWM_TOP);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800387 pwm_set_gpio_level(HEADING_PWM, heading_level);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800388 }
389
Ravago Jones23109002022-02-04 15:50:50 -0800390 // if 5 or more consecutive checksums are zero, then something weird is going
391 // on with the imu
392 if (computed_checksum != given_checksum || computed_checksum == 0 ||
393 given_checksum == 0) {
394 suspicious_checksums++;
395 } else {
396 suspicious_checksums = 0;
397 }
398
399 if (suspicious_checksums >= 5) {
400 reset_imu = true;
401 }
402
403 // fill out message and add it to the queue
404 pack_pi_packet();
405
Ravago Jonesb83957c2021-12-29 19:57:34 -0800406 // TODO: this has a sleep in it
407 // stay in sync with the pi by resetting the spi fifos each transfer
408 spi_init(SPI_PI, 2000 * 1000);
409 spi_set_slave(SPI_PI, true);
410 // these settings were the most stable even though the PI is using
411 // polarity 1 and phase 1
412 spi_set_format(SPI_PI, 8, SPI_CPOL_0, SPI_CPHA_1, SPI_MSB_FIRST);
413
414 maybe_send_pi_packet();
415
416 // clear the interrupt
417 dma_hw->ints0 = 1u << imu_dma_rx;
418}
419
420void maybe_send_pi_packet() {
421 // active low; if the pi isn't connected/booted, this will
422 // also look active
423 bool cs_asserted_or_unplugged = !gpio_get(CS_PI);
424
425 if (cs_asserted_or_unplugged) {
426 // the pi is still recieving something else from us
427 timing_overrun_count++;
428 return;
429 }
430
Ravago Jonesb83957c2021-12-29 19:57:34 -0800431 memcpy(pi_sending_buffer, pi_staging_buffer, PI_NUM_ITEMS);
432
433 dma_channel_configure(pi_dma_tx, &pi_tx_config,
434 &spi_get_hw(SPI_PI)->dr, // write address
435 &pi_sending_buffer, // read address
436 PI_NUM_ITEMS, // element count (each element is
437 // of size transfer_data_size)
438 false); // don't start yet
439 dma_channel_configure(pi_dma_rx, &pi_rx_config,
440 &pi_recieve_buffer, // write address
441 &spi_get_hw(SPI_PI)->dr, // read address
442 PI_NUM_ITEMS, // element count (each element is of
443 // size transfer_data_size)
444 false); // don't start yet
445
446 // start hardware calculation of the CRC-32; currently calculated in software
447 dma_sniffer_enable(pi_dma_tx, 0x0, true);
448 dma_hw->sniff_data = 0;
449
450 // start both at exactly the same time
451 dma_start_channel_mask((1u << pi_dma_tx) | (1u << pi_dma_rx));
Ravago Jones23109002022-02-04 15:50:50 -0800452 gpio_put(DR_PI, 1);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800453}
454
455void pi_transfer_finished() {
456 message_sent_count++;
457 gpio_put(DR_PI, 0);
458
459 send_time = time_us_32() - data_collect_timestamp;
460
461 dma_hw->ints1 = 1u << pi_dma_rx;
462}
463
Ravago Jones23109002022-02-04 15:50:50 -0800464void setup_adis16505() {
James Kuszmaulc1741012022-02-19 17:49:27 -0800465 // Disable the interrupts from the data-ready/sync pins to avoid interrupts
466 // while attempting to reset the IMU.
Ravago Jones23109002022-02-04 15:50:50 -0800467 gpio_set_irq_enabled(DR_IMU, GPIO_IRQ_EDGE_RISE, false);
James Kuszmaulc1741012022-02-19 17:49:27 -0800468 gpio_set_irq_enabled(SYNC_IMU, GPIO_IRQ_EDGE_RISE, false);
Ravago Jones23109002022-02-04 15:50:50 -0800469
470 while (true) {
471 adis16505_reset();
472 // See if SPI is working - interrogate the device for its product ID
473 // number, should be 0x4079
474 uint16_t id = read_register(PROD_ID);
475 if (id == EXPECTED_PROD_ID) {
476 printf("Product id: 0x%04x == expected 0x%04x\n", id, EXPECTED_PROD_ID);
477 break;
478 } else {
479 printf("Got 0x%04x for prod id, expected 0x%04x\ntrying again\n", id,
480 EXPECTED_PROD_ID);
481 }
482 }
483
484 uint16_t firmware_revision = read_register(FIRM_REV);
485 uint16_t firmware_day_month = read_register(FIRM_DM);
486 uint16_t firmware_year = read_register(FIRM_Y);
487 uint16_t serial_number = read_register(SERIAL_NUM);
488
489 printf(
490 "Firmware revision: 0x%04x, \nFirmware day month: 0x%04x, \nFirmware "
491 "year: "
492 "0x%04x, \nSerial number: 0x%04x, \n",
493 firmware_revision, firmware_day_month, firmware_year, serial_number);
494
495 // run self test
496 int num_failures = 0;
497 while (true) {
498 write_register(GLOB_CMD, 1u << 2);
499 sleep_ms(24);
500 uint16_t diag_stat = read_register(DIAG_STAT);
501
502 // check the sensor failure bit
503 bool sensor_failure = diag_stat & (1u << 5);
504 printf("Diag stat: 0b%016b, \n", diag_stat);
505
506 if (sensor_failure) {
507 num_failures++;
508 printf("%d failures, trying again\n", num_failures);
509 } else {
510 break;
511 }
512 }
513
514 write_register(FILT_CTRL, 0 /* no filtering */);
515 write_register(
516 MSC_CTRL,
517 (1u << 9) /* enable 32-bit mode for burst reads */ |
518 (0u << 8) /* send gyro and accelerometer data in burst mode */ |
519 (1u << 7) /* enable gyro linear g compensation */ |
520 (1u << 6) /* enable point of percussion alignment */ |
James Kuszmaulc1741012022-02-19 17:49:27 -0800521 (11u << 2) /* output sync mode (uses internal 2kHz clock) */ |
522 (1u << 1) /* sync polarity, active high */ |
Ravago Jones23109002022-02-04 15:50:50 -0800523 (1u << 0) /* data ready is active high */);
524 // Rate of the output will be 2000 / (DEC_RATE + 1) Hz.
525 write_register(DEC_RATE, 0 /* no decimation */);
526
527 sleep_us(200);
528
529 imu_reset_count++;
530
James Kuszmaulc1741012022-02-19 17:49:27 -0800531 gpio_set_irq_enabled(SYNC_IMU, GPIO_IRQ_EDGE_RISE, true);
Ravago Jones23109002022-02-04 15:50:50 -0800532 gpio_set_irq_enabled_with_callback(DR_IMU, GPIO_IRQ_EDGE_RISE, true,
533 &gpio_irq_handler);
534}
535
Ravago Jonesb83957c2021-12-29 19:57:34 -0800536int main() {
537 stdio_init_all();
538
539 // Use 1MHz with the IMU as that is the limit for burst mode.
540 spi_init(SPI_IMU, 1000 * 1000);
541 spi_set_format(SPI_IMU, 16, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
542 gpio_set_function(DOUT_IMU, GPIO_FUNC_SPI);
543 gpio_set_function(SCLK_IMU, GPIO_FUNC_SPI);
544 gpio_set_function(DIN_IMU, GPIO_FUNC_SPI);
545 // Make the SPI pins available to picotool
546 bi_decl(bi_3pins_with_func(DOUT_IMU, DIN_IMU, SCLK_IMU, GPIO_FUNC_SPI));
547
548 // Chip select is active-low, so we'll initialise it to a driven-high state
549 gpio_init(CS_IMU);
550 gpio_set_dir(CS_IMU, GPIO_OUT);
551 gpio_put(CS_IMU, 1);
552 // Make the CS pin available to picotool
553 bi_decl(bi_1pin_with_name(CS_IMU, "IMU CS"));
554
555 // Reset is active-low, so we'll initialise it to a driven-high state
556 gpio_init(RST_IMU);
557 gpio_set_dir(RST_IMU, GPIO_OUT);
558 gpio_put(RST_IMU, 1);
559 // Make the RST pin available to picotool
560 bi_decl(bi_1pin_with_name(RST_IMU, "IMU RESET"));
561
562 imu_dma_tx = dma_claim_unused_channel(true);
563 imu_dma_rx = dma_claim_unused_channel(true);
564
565 // We set the outbound DMA to transfer from a memory buffer to the SPI
566 // transmit FIFO paced by the SPI TX FIFO DREQ The default is for the read
567 // address to increment every element (in this case 2 bytes - DMA_SIZE_16) and
568 // for the write address to remain unchanged.
569
570 imu_tx_config = dma_channel_get_default_config(imu_dma_tx);
571 channel_config_set_transfer_data_size(&imu_tx_config, DMA_SIZE_16);
572 channel_config_set_dreq(&imu_tx_config, spi_get_dreq(SPI_IMU, true));
573 channel_config_set_read_increment(&imu_tx_config, true);
574 channel_config_set_write_increment(&imu_tx_config, false);
575
576 // We set the inbound DMA to transfer from the SPI receive FIFO to a memory
577 // buffer paced by the SPI RX FIFO DREQ We configure the read address to
578 // remain unchanged for each element, but the write address to increment (so
579 // data is written throughout the buffer)
580 imu_rx_config = dma_channel_get_default_config(imu_dma_rx);
581 channel_config_set_transfer_data_size(&imu_rx_config, DMA_SIZE_16);
582 channel_config_set_dreq(&imu_rx_config, spi_get_dreq(SPI_IMU, false));
583 channel_config_set_read_increment(&imu_rx_config, false);
584 channel_config_set_write_increment(&imu_rx_config, true);
585
586 // Tell the DMA to raise IRQ line 0 when the channel finishes a block
587 dma_channel_set_irq0_enabled(imu_dma_rx, true);
588
589 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
590 irq_set_exclusive_handler(DMA_IRQ_0, imu_read_finished);
591 irq_set_enabled(DMA_IRQ_0, true);
592
593 // Use 2MHz with the PI as that is the maximum speed for the pico
594 gpio_set_function(MISO_PI, GPIO_FUNC_SPI);
595 gpio_set_function(MOSI_PI, GPIO_FUNC_SPI);
596 gpio_set_function(SCK_PI, GPIO_FUNC_SPI);
597 gpio_set_function(CS_PI, GPIO_FUNC_SPI);
598 // Make the SPI pins available to picotool
599 bi_decl(bi_3pins_with_func(DOUT_IMU, DIN_IMU, SCLK_IMU, GPIO_FUNC_SPI));
600
601 gpio_init(DR_PI);
602 gpio_set_dir(DR_PI, GPIO_OUT);
603 gpio_put(DR_PI, 0);
604 // Make the CS pin available to picotool
605 bi_decl(bi_1pin_with_name(DR_PI, "DATA READY PI"));
606
607 pi_dma_tx = dma_claim_unused_channel(true);
608 pi_dma_rx = dma_claim_unused_channel(true);
609
610 // We set the outbound DMA to transfer from a memory buffer to the SPI
611 // transmit FIFO paced by the SPI TX FIFO DREQ The default is for the read
612 // address to increment every element (in this case 2 bytes - DMA_SIZE_16) and
613 // for the write address to remain unchanged.
614
615 pi_tx_config = dma_channel_get_default_config(pi_dma_tx);
616 channel_config_set_transfer_data_size(&pi_tx_config, DMA_SIZE_8);
617 channel_config_set_dreq(&pi_tx_config, spi_get_dreq(SPI_PI, true));
618 channel_config_set_read_increment(&pi_tx_config, true);
619 channel_config_set_write_increment(&pi_tx_config, false);
620
621 // We set the inbound DMA to transfer from the SPI receive FIFO to a memory
622 // buffer paced by the SPI RX FIFO DREQ We configure the read address to
623 // remain unchanged for each element, but the write address to increment (so
624 // data is written throughout the buffer)
625 pi_rx_config = dma_channel_get_default_config(pi_dma_rx);
626 channel_config_set_transfer_data_size(&pi_rx_config, DMA_SIZE_8);
627 channel_config_set_dreq(&pi_rx_config, spi_get_dreq(SPI_PI, false));
628 channel_config_set_read_increment(&pi_rx_config, false);
629 channel_config_set_write_increment(&pi_rx_config, true);
630
631 // Tell the DMA to raise IRQ line 1 when the channel finishes a block
632 dma_channel_set_irq1_enabled(pi_dma_rx, true);
633
634 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
635 irq_set_exclusive_handler(DMA_IRQ_1, pi_transfer_finished);
636 irq_set_enabled(DMA_IRQ_1, true);
637
638 /* All IRQ priorities are initialized to PICO_DEFAULT_IRQ_PRIORITY by the pico
James Kuszmaulc1741012022-02-19 17:49:27 -0800639 * runtime at startup. As such, their priorities will correspond to their
640 * IRQ numbers (See Table 80 in the rp2040 datasheet). The interrupts are
641 * listed highest priority to lowest below--i.e., the sync/data ready
642 * interrupts are currently at the lowest priority.
643 * TODO(james): In the nominal case, the GPIO interrupts should never
644 * interfere with the SPI data transfer, but we may still want to up the
645 * GPIO priority using irq_set_priority() so that we are guaranteed good
646 * timestamps.
Ravago Jonesb83957c2021-12-29 19:57:34 -0800647 *
648 * Handler | Interrupt | Cause of interrupt
649 * --------------------|--------------|---------------------------------------
650 * imu_read_finished | DMA_IRQ_0 | When the dma read from the imu is done
651 * pi_transfer_finished| DMA_IRQ_1 | When the dma read to the pi is
652 * done data_ready | IO_IRQ_BANK0 | On the rising edge of DR_IMU
James Kuszmaulc1741012022-02-19 17:49:27 -0800653 * sync pin high | IO_IRQ_BANK0 | On the rising edge of SYNC_IMU
Ravago Jonesb83957c2021-12-29 19:57:34 -0800654 */
655
656 // Tell the GPIOs they are allocated to PWM
657 gpio_set_function(HEADING_PWM, GPIO_FUNC_PWM);
658 gpio_set_function(RATE_PWM, GPIO_FUNC_PWM);
659
660 // Find out which PWM slice is connected to each gpio pin
661 uint heading_slice = pwm_gpio_to_slice_num(HEADING_PWM);
662 uint rate_slice = pwm_gpio_to_slice_num(RATE_PWM);
663
664 /* frequency_pwm = f_sys / ((TOP + 1) * (CSR_PHASE_CORRECT + 1) * (DIV_INT +
665 * DIV_FRAC / 16))
666 *
667 * f_sys = 125 mhz
668 * CSR_PHASE_CORRECT = 0; no phase correct
669 * TARGET_FREQ = 200 hz
670 *
671 * 125 mhz / x = 200 hz * 62500
672 *
673 * TOP = 62499
674 * DIV_INT = 10
675 */
676
677 float divisor = clock_get_hz(clk_sys) / (PWM_TOP + 1) / PWM_FREQ_HZ;
678
679 pwm_config cfg = pwm_get_default_config();
680 pwm_config_set_clkdiv_mode(&cfg, PWM_DIV_FREE_RUNNING);
681 pwm_config_set_clkdiv(&cfg, divisor);
682 pwm_config_set_wrap(&cfg, PWM_TOP);
683
684 pwm_init(heading_slice, &cfg, true);
685 pwm_init(rate_slice, &cfg, true);
686
687 // the two state machine instances use the same program memory from pio0
688 uint offset = pio_add_program(pio0, &quadrature_encoder_program);
689 quadrature_encoder_program_init(pio0, 0, offset, ENC1_A, 0);
690 quadrature_encoder_program_init(pio0, 1, offset, ENC2_A, 0);
691
692 sleep_ms(3 * 1000);
693
694 printf("Hello ADIS16505\n");
695
696 printf(
697 "System clock: %d hz\n"
698 "PWM target frequency: %d hz, PWM clock divisor: "
699 "%f, PWM TOP: %d\n",
700 clock_get_hz(clk_sys), PWM_FREQ_HZ, divisor, PWM_TOP);
701
Ravago Jones23109002022-02-04 15:50:50 -0800702 setup_adis16505();
Ravago Jonesb83957c2021-12-29 19:57:34 -0800703
704 while (!yaw_zeroed) {
705 dma_channel_wait_for_finish_blocking(imu_dma_rx);
706 sleep_us(100);
707 zero_yaw(yaw_rate);
708 }
709
710 printf("Press q to enter bootloader\n");
711
712 while (1) {
713 dma_channel_wait_for_finish_blocking(imu_dma_rx);
714 // we want the interrupts to happen before or during the sleep so that we
715 // can get a good picture of what's going on without things moving around
716 sleep_us(100);
717
Ravago Jones23109002022-02-04 15:50:50 -0800718 if (reset_imu) {
719 printf("Triggered IMU reset, resetting\n");
720 setup_adis16505();
721 reset_imu = false;
722 }
723
Ravago Jonesb83957c2021-12-29 19:57:34 -0800724 // debug
725 // one printf is faster than many printfs
726 printf(
727 "Z pos is %f encoder: %d %d\n"
728 "Num failed checksums: %d, Total messages recieved: %d,\n"
729 "Num messages to pi: %d, Timing overrun count: %d,\n"
Ravago Jones23109002022-02-04 15:50:50 -0800730 "Send time: %d us, suspicious checksum count: %u,\n"
731 "IMU reset count: %d, checksum: %u,\n",
Ravago Jonesb83957c2021-12-29 19:57:34 -0800732 yaw, encoder1_count, encoder2_count, checksum_mismatch_count,
733 message_recieved_count, message_sent_count, timing_overrun_count,
Ravago Jones23109002022-02-04 15:50:50 -0800734 send_time, suspicious_checksums, imu_reset_count,
735 imu_data_buffer[IMU_NUM_ITEMS - 1]);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800736
737 // allow the user to enter the bootloader without removing power or having
738 // to install a reset button
739 char user_input = getchar_timeout_us(0);
740 if (user_input == 'q') {
741 printf("Going down! entering bootloader\n");
742 reset_usb_boot(0, 0);
743 }
744
745 sleep_ms(50);
746 }
747
748 printf("All good\n");
749 dma_channel_unclaim(imu_dma_rx);
750 dma_channel_unclaim(imu_dma_tx);
751 dma_channel_unclaim(pi_dma_rx);
752 dma_channel_unclaim(pi_dma_tx);
753 return 0;
754}