blob: 4c31cab0d2dd984ba7d5b7e1d48fb28bb0562826 [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) {
199 if (gpio == DR_IMU && (events & GPIO_IRQ_EDGE_RISE)) {
200 data_ready();
201 }
202}
203
204static inline void cs_select() {
205 gpio_put(CS_IMU, 0); // Active low
206 sleep_us(1);
207}
208
209static inline void cs_deselect() { gpio_put(CS_IMU, 1); }
210
211static uint16_t read_register(uint8_t reg_low) {
212 // For this particular device, we send the device the register we want to read
213 // first, then subsequently read from the device.
214 uint16_t output;
215
216 // The low byte of the register is first in the IMU's memory
217 uint16_t reg = ((uint16_t)reg_low) << 8;
218
219 cs_select();
220 spi_write16_blocking(SPI_IMU, &reg, 1);
221 cs_deselect();
222 sleep_us(20); // wait the stall period
223 cs_select();
224 spi_read16_blocking(SPI_IMU, 0x0000, &output, 1);
225 cs_deselect();
226
227 return output;
228}
229
230static void write_register(uint8_t reg, uint16_t value) {
231 uint16_t low_byte = ((uint16_t)value) & 0xFF;
232 uint16_t high_byte = ((uint16_t)value) >> 8;
233
234 uint16_t command = (((uint16_t)reg) << 8) | low_byte | WRITE_BIT;
235
236 cs_select();
237 spi_write16_blocking(SPI_IMU, &command, 1);
238 cs_deselect();
239
240 sleep_us(20); // wait the stall period
241
242 command = ((((uint16_t)reg) + 1) << 8) | high_byte | WRITE_BIT;
243
244 cs_select();
245 spi_write16_blocking(SPI_IMU, &command, 1);
246 cs_deselect();
247}
248
249static void adis16505_reset() {
250 gpio_put(RST_IMU, 0); // Active low
251 sleep_ms(10);
252 gpio_put(RST_IMU, 1); // Active low
253 sleep_ms(310);
254}
255
256static uint32_t calculate_crc32(uint8_t *data, size_t len) {
257 uint32_t crc = 0xFFFFFFFF;
258 for (size_t i = 0; i < len; i++) {
259 crc = kCrc32Table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8);
260 }
261 return crc;
262}
263
Ravago Jones23109002022-02-04 15:50:50 -0800264static uint16_t check_checksum(uint16_t *buf) {
Ravago Jonesb83957c2021-12-29 19:57:34 -0800265 uint16_t sum = 0;
266 for (int i = 1; i < IMU_NUM_ITEMS - 1; i++) {
267 uint16_t low = buf[i] & 0xff;
268 uint16_t high = (buf[i] >> 8) & 0xff;
269
270 sum += high + low;
271 }
272
Ravago Jones23109002022-02-04 15:50:50 -0800273 return sum;
Ravago Jonesb83957c2021-12-29 19:57:34 -0800274}
275
276static void zero_yaw(double yaw) {
277 static double yaw_buffer[YAW_BUF_LEN];
278 static int num_items;
279
280 if (num_items < YAW_BUF_LEN) {
281 yaw_buffer[num_items] = yaw;
282 num_items++;
283 } else if (!yaw_zeroed) {
284 double sum = 0;
285 for (int i = 0; i < YAW_BUF_LEN; i++) {
286 sum += yaw_buffer[i];
287 }
288 yaw_rate_offset = -sum / YAW_BUF_LEN;
289 yaw = 0;
290 printf("offset: %f\n", yaw_rate_offset);
291 yaw_zeroed = true;
292 }
293}
294
295void pack_pi_packet() {
296 // zero the buffer
297 for (int i = 0; i < PI_NUM_ITEMS; i++) {
298 pi_staging_buffer[i] = 0;
299 }
300
301 // skip empty item
302 uint8_t *imu_packet = (uint8_t *)(imu_data_buffer + 1);
303 // skip empty item and checksum and convert to bytes
304 const size_t imu_packet_len = (IMU_NUM_ITEMS - 2) * sizeof(uint16_t);
305
306 memcpy(pi_staging_buffer, imu_packet, imu_packet_len);
307 memcpy(pi_staging_buffer + imu_packet_len, &data_collect_timestamp, 4);
308 memcpy(pi_staging_buffer + imu_packet_len + 4, &encoder1_count, 2);
309 memcpy(pi_staging_buffer + imu_packet_len + 6, &encoder2_count, 2);
310
311 // exclude the part of the buffer that will be the checksum
312 uint32_t crc = calculate_crc32(pi_staging_buffer, PI_NUM_ITEMS - 4);
313 memcpy(pi_staging_buffer + imu_packet_len + 8, &crc, 4);
314
315 static_assert(PI_NUM_ITEMS == imu_packet_len +
316 sizeof(data_collect_timestamp) +
317 sizeof(encoder1_count) +
318 sizeof(encoder2_count) + sizeof(crc),
319 "PI_NUM_ITEMS needs to be able to hold the imu message + the "
320 "timestamp + the encoders + the checksum");
321}
322
323void data_ready() {
324 // save timestamp
325 data_collect_timestamp = time_us_32();
326
327 // read encoders
328 quadrature_encoder_request_count(pio0, 0);
329 quadrature_encoder_request_count(pio0, 1);
330
331 cs_select();
332 dma_channel_configure(imu_dma_tx, &imu_tx_config,
333 &spi_get_hw(SPI_IMU)->dr, // write address
334 &imu_write_buf, // read address
335 IMU_NUM_ITEMS, // element count (each element is of
336 // size transfer_data_size)
337 false); // don't start yet
338 dma_channel_configure(imu_dma_rx, &imu_rx_config,
339 &imu_data_buffer, // write address
340 &spi_get_hw(SPI_IMU)->dr, // read address
341 IMU_NUM_ITEMS, // element count (each element is of
342 // size transfer_data_size)
343 false); // don't start yet
344 dma_start_channel_mask((1u << imu_dma_tx) | (1u << imu_dma_rx));
345
346 encoder1_count = quadrature_encoder_fetch_count(pio0, 0);
347 encoder2_count = quadrature_encoder_fetch_count(pio0, 1);
348}
349
350void imu_read_finished() {
351 cs_deselect();
352
353 // TODO: check status and if necessary set flag to reset in main loop
354
355 message_recieved_count++;
Ravago Jones23109002022-02-04 15:50:50 -0800356 uint16_t computed_checksum = check_checksum(imu_data_buffer);
357 uint16_t given_checksum = imu_data_buffer[IMU_NUM_ITEMS - 1];
358
359 if (computed_checksum != given_checksum) {
Ravago Jonesb83957c2021-12-29 19:57:34 -0800360 checksum_mismatch_count++;
Ravago Jones23109002022-02-04 15:50:50 -0800361 for (size_t i = 0; i < IMU_NUM_ITEMS; i++) {
362 // make it clear that this data is bad
363 imu_data_buffer[i] = 0;
364 }
365 // and set an unused bit of DIAG_STAT
366 imu_data_buffer[1] = 1u << 0;
Ravago Jonesb83957c2021-12-29 19:57:34 -0800367 } else {
368 static const double dt = 0.0005; // seconds
369 int32_t z_gyro_out;
370 memcpy(&z_gyro_out, imu_data_buffer + 6, 4);
371 yaw_rate = (double)z_gyro_out / 655360.0 + yaw_rate_offset; // degrees
372 yaw += yaw_rate * dt;
373
374 // 50% is 0; -2000 deg/sec to 2000 deg/sec
375 uint16_t rate_level =
376 (std::clamp(yaw_rate, -2000.0, 2000.0) / 4000.0 + 0.5) * PWM_TOP;
377 pwm_set_gpio_level(RATE_PWM, rate_level);
378
379 // 0 to 360
380 uint16_t heading_level = (int16_t)(fmod(yaw, 360) / 360.0 * PWM_TOP);
381 pwm_set_gpio_level(HEADING_PWM, heading_level);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800382 }
383
Ravago Jones23109002022-02-04 15:50:50 -0800384 // if 5 or more consecutive checksums are zero, then something weird is going
385 // on with the imu
386 if (computed_checksum != given_checksum || computed_checksum == 0 ||
387 given_checksum == 0) {
388 suspicious_checksums++;
389 } else {
390 suspicious_checksums = 0;
391 }
392
393 if (suspicious_checksums >= 5) {
394 reset_imu = true;
395 }
396
397 // fill out message and add it to the queue
398 pack_pi_packet();
399
Ravago Jonesb83957c2021-12-29 19:57:34 -0800400 // TODO: this has a sleep in it
401 // stay in sync with the pi by resetting the spi fifos each transfer
402 spi_init(SPI_PI, 2000 * 1000);
403 spi_set_slave(SPI_PI, true);
404 // these settings were the most stable even though the PI is using
405 // polarity 1 and phase 1
406 spi_set_format(SPI_PI, 8, SPI_CPOL_0, SPI_CPHA_1, SPI_MSB_FIRST);
407
408 maybe_send_pi_packet();
409
410 // clear the interrupt
411 dma_hw->ints0 = 1u << imu_dma_rx;
412}
413
414void maybe_send_pi_packet() {
415 // active low; if the pi isn't connected/booted, this will
416 // also look active
417 bool cs_asserted_or_unplugged = !gpio_get(CS_PI);
418
419 if (cs_asserted_or_unplugged) {
420 // the pi is still recieving something else from us
421 timing_overrun_count++;
422 return;
423 }
424
Ravago Jonesb83957c2021-12-29 19:57:34 -0800425 memcpy(pi_sending_buffer, pi_staging_buffer, PI_NUM_ITEMS);
426
427 dma_channel_configure(pi_dma_tx, &pi_tx_config,
428 &spi_get_hw(SPI_PI)->dr, // write address
429 &pi_sending_buffer, // read address
430 PI_NUM_ITEMS, // element count (each element is
431 // of size transfer_data_size)
432 false); // don't start yet
433 dma_channel_configure(pi_dma_rx, &pi_rx_config,
434 &pi_recieve_buffer, // write address
435 &spi_get_hw(SPI_PI)->dr, // read address
436 PI_NUM_ITEMS, // element count (each element is of
437 // size transfer_data_size)
438 false); // don't start yet
439
440 // start hardware calculation of the CRC-32; currently calculated in software
441 dma_sniffer_enable(pi_dma_tx, 0x0, true);
442 dma_hw->sniff_data = 0;
443
444 // start both at exactly the same time
445 dma_start_channel_mask((1u << pi_dma_tx) | (1u << pi_dma_rx));
Ravago Jones23109002022-02-04 15:50:50 -0800446 gpio_put(DR_PI, 1);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800447}
448
449void pi_transfer_finished() {
450 message_sent_count++;
451 gpio_put(DR_PI, 0);
452
453 send_time = time_us_32() - data_collect_timestamp;
454
455 dma_hw->ints1 = 1u << pi_dma_rx;
456}
457
Ravago Jones23109002022-02-04 15:50:50 -0800458void setup_adis16505() {
459 gpio_set_irq_enabled(DR_IMU, GPIO_IRQ_EDGE_RISE, false);
460
461 while (true) {
462 adis16505_reset();
463 // See if SPI is working - interrogate the device for its product ID
464 // number, should be 0x4079
465 uint16_t id = read_register(PROD_ID);
466 if (id == EXPECTED_PROD_ID) {
467 printf("Product id: 0x%04x == expected 0x%04x\n", id, EXPECTED_PROD_ID);
468 break;
469 } else {
470 printf("Got 0x%04x for prod id, expected 0x%04x\ntrying again\n", id,
471 EXPECTED_PROD_ID);
472 }
473 }
474
475 uint16_t firmware_revision = read_register(FIRM_REV);
476 uint16_t firmware_day_month = read_register(FIRM_DM);
477 uint16_t firmware_year = read_register(FIRM_Y);
478 uint16_t serial_number = read_register(SERIAL_NUM);
479
480 printf(
481 "Firmware revision: 0x%04x, \nFirmware day month: 0x%04x, \nFirmware "
482 "year: "
483 "0x%04x, \nSerial number: 0x%04x, \n",
484 firmware_revision, firmware_day_month, firmware_year, serial_number);
485
486 // run self test
487 int num_failures = 0;
488 while (true) {
489 write_register(GLOB_CMD, 1u << 2);
490 sleep_ms(24);
491 uint16_t diag_stat = read_register(DIAG_STAT);
492
493 // check the sensor failure bit
494 bool sensor_failure = diag_stat & (1u << 5);
495 printf("Diag stat: 0b%016b, \n", diag_stat);
496
497 if (sensor_failure) {
498 num_failures++;
499 printf("%d failures, trying again\n", num_failures);
500 } else {
501 break;
502 }
503 }
504
505 write_register(FILT_CTRL, 0 /* no filtering */);
506 write_register(
507 MSC_CTRL,
508 (1u << 9) /* enable 32-bit mode for burst reads */ |
509 (0u << 8) /* send gyro and accelerometer data in burst mode */ |
510 (1u << 7) /* enable gyro linear g compensation */ |
511 (1u << 6) /* enable point of percussion alignment */ |
512 (0u << 2) /* internal clock mode */ |
513 (0u << 1) /* sync polarity, doesn't matter */ |
514 (1u << 0) /* data ready is active high */);
515 // Rate of the output will be 2000 / (DEC_RATE + 1) Hz.
516 write_register(DEC_RATE, 0 /* no decimation */);
517
518 sleep_us(200);
519
520 imu_reset_count++;
521
522 gpio_set_irq_enabled_with_callback(DR_IMU, GPIO_IRQ_EDGE_RISE, true,
523 &gpio_irq_handler);
524}
525
Ravago Jonesb83957c2021-12-29 19:57:34 -0800526int main() {
527 stdio_init_all();
528
529 // Use 1MHz with the IMU as that is the limit for burst mode.
530 spi_init(SPI_IMU, 1000 * 1000);
531 spi_set_format(SPI_IMU, 16, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
532 gpio_set_function(DOUT_IMU, GPIO_FUNC_SPI);
533 gpio_set_function(SCLK_IMU, GPIO_FUNC_SPI);
534 gpio_set_function(DIN_IMU, GPIO_FUNC_SPI);
535 // Make the SPI pins available to picotool
536 bi_decl(bi_3pins_with_func(DOUT_IMU, DIN_IMU, SCLK_IMU, GPIO_FUNC_SPI));
537
538 // Chip select is active-low, so we'll initialise it to a driven-high state
539 gpio_init(CS_IMU);
540 gpio_set_dir(CS_IMU, GPIO_OUT);
541 gpio_put(CS_IMU, 1);
542 // Make the CS pin available to picotool
543 bi_decl(bi_1pin_with_name(CS_IMU, "IMU CS"));
544
545 // Reset is active-low, so we'll initialise it to a driven-high state
546 gpio_init(RST_IMU);
547 gpio_set_dir(RST_IMU, GPIO_OUT);
548 gpio_put(RST_IMU, 1);
549 // Make the RST pin available to picotool
550 bi_decl(bi_1pin_with_name(RST_IMU, "IMU RESET"));
551
552 imu_dma_tx = dma_claim_unused_channel(true);
553 imu_dma_rx = dma_claim_unused_channel(true);
554
555 // We set the outbound DMA to transfer from a memory buffer to the SPI
556 // transmit FIFO paced by the SPI TX FIFO DREQ The default is for the read
557 // address to increment every element (in this case 2 bytes - DMA_SIZE_16) and
558 // for the write address to remain unchanged.
559
560 imu_tx_config = dma_channel_get_default_config(imu_dma_tx);
561 channel_config_set_transfer_data_size(&imu_tx_config, DMA_SIZE_16);
562 channel_config_set_dreq(&imu_tx_config, spi_get_dreq(SPI_IMU, true));
563 channel_config_set_read_increment(&imu_tx_config, true);
564 channel_config_set_write_increment(&imu_tx_config, false);
565
566 // We set the inbound DMA to transfer from the SPI receive FIFO to a memory
567 // buffer paced by the SPI RX FIFO DREQ We configure the read address to
568 // remain unchanged for each element, but the write address to increment (so
569 // data is written throughout the buffer)
570 imu_rx_config = dma_channel_get_default_config(imu_dma_rx);
571 channel_config_set_transfer_data_size(&imu_rx_config, DMA_SIZE_16);
572 channel_config_set_dreq(&imu_rx_config, spi_get_dreq(SPI_IMU, false));
573 channel_config_set_read_increment(&imu_rx_config, false);
574 channel_config_set_write_increment(&imu_rx_config, true);
575
576 // Tell the DMA to raise IRQ line 0 when the channel finishes a block
577 dma_channel_set_irq0_enabled(imu_dma_rx, true);
578
579 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
580 irq_set_exclusive_handler(DMA_IRQ_0, imu_read_finished);
581 irq_set_enabled(DMA_IRQ_0, true);
582
583 // Use 2MHz with the PI as that is the maximum speed for the pico
584 gpio_set_function(MISO_PI, GPIO_FUNC_SPI);
585 gpio_set_function(MOSI_PI, GPIO_FUNC_SPI);
586 gpio_set_function(SCK_PI, GPIO_FUNC_SPI);
587 gpio_set_function(CS_PI, GPIO_FUNC_SPI);
588 // Make the SPI pins available to picotool
589 bi_decl(bi_3pins_with_func(DOUT_IMU, DIN_IMU, SCLK_IMU, GPIO_FUNC_SPI));
590
591 gpio_init(DR_PI);
592 gpio_set_dir(DR_PI, GPIO_OUT);
593 gpio_put(DR_PI, 0);
594 // Make the CS pin available to picotool
595 bi_decl(bi_1pin_with_name(DR_PI, "DATA READY PI"));
596
597 pi_dma_tx = dma_claim_unused_channel(true);
598 pi_dma_rx = dma_claim_unused_channel(true);
599
600 // We set the outbound DMA to transfer from a memory buffer to the SPI
601 // transmit FIFO paced by the SPI TX FIFO DREQ The default is for the read
602 // address to increment every element (in this case 2 bytes - DMA_SIZE_16) and
603 // for the write address to remain unchanged.
604
605 pi_tx_config = dma_channel_get_default_config(pi_dma_tx);
606 channel_config_set_transfer_data_size(&pi_tx_config, DMA_SIZE_8);
607 channel_config_set_dreq(&pi_tx_config, spi_get_dreq(SPI_PI, true));
608 channel_config_set_read_increment(&pi_tx_config, true);
609 channel_config_set_write_increment(&pi_tx_config, false);
610
611 // We set the inbound DMA to transfer from the SPI receive FIFO to a memory
612 // buffer paced by the SPI RX FIFO DREQ We configure the read address to
613 // remain unchanged for each element, but the write address to increment (so
614 // data is written throughout the buffer)
615 pi_rx_config = dma_channel_get_default_config(pi_dma_rx);
616 channel_config_set_transfer_data_size(&pi_rx_config, DMA_SIZE_8);
617 channel_config_set_dreq(&pi_rx_config, spi_get_dreq(SPI_PI, false));
618 channel_config_set_read_increment(&pi_rx_config, false);
619 channel_config_set_write_increment(&pi_rx_config, true);
620
621 // Tell the DMA to raise IRQ line 1 when the channel finishes a block
622 dma_channel_set_irq1_enabled(pi_dma_rx, true);
623
624 // Configure the processor to run dma_handler() when DMA IRQ 0 is asserted
625 irq_set_exclusive_handler(DMA_IRQ_1, pi_transfer_finished);
626 irq_set_enabled(DMA_IRQ_1, true);
627
628 /* All IRQ priorities are initialized to PICO_DEFAULT_IRQ_PRIORITY by the pico
629 * runtime at startup.
630 *
631 * Handler | Interrupt | Cause of interrupt
632 * --------------------|--------------|---------------------------------------
633 * imu_read_finished | DMA_IRQ_0 | When the dma read from the imu is done
634 * pi_transfer_finished| DMA_IRQ_1 | When the dma read to the pi is
635 * done data_ready | IO_IRQ_BANK0 | On the rising edge of DR_IMU
636 */
637
638 // Tell the GPIOs they are allocated to PWM
639 gpio_set_function(HEADING_PWM, GPIO_FUNC_PWM);
640 gpio_set_function(RATE_PWM, GPIO_FUNC_PWM);
641
642 // Find out which PWM slice is connected to each gpio pin
643 uint heading_slice = pwm_gpio_to_slice_num(HEADING_PWM);
644 uint rate_slice = pwm_gpio_to_slice_num(RATE_PWM);
645
646 /* frequency_pwm = f_sys / ((TOP + 1) * (CSR_PHASE_CORRECT + 1) * (DIV_INT +
647 * DIV_FRAC / 16))
648 *
649 * f_sys = 125 mhz
650 * CSR_PHASE_CORRECT = 0; no phase correct
651 * TARGET_FREQ = 200 hz
652 *
653 * 125 mhz / x = 200 hz * 62500
654 *
655 * TOP = 62499
656 * DIV_INT = 10
657 */
658
659 float divisor = clock_get_hz(clk_sys) / (PWM_TOP + 1) / PWM_FREQ_HZ;
660
661 pwm_config cfg = pwm_get_default_config();
662 pwm_config_set_clkdiv_mode(&cfg, PWM_DIV_FREE_RUNNING);
663 pwm_config_set_clkdiv(&cfg, divisor);
664 pwm_config_set_wrap(&cfg, PWM_TOP);
665
666 pwm_init(heading_slice, &cfg, true);
667 pwm_init(rate_slice, &cfg, true);
668
669 // the two state machine instances use the same program memory from pio0
670 uint offset = pio_add_program(pio0, &quadrature_encoder_program);
671 quadrature_encoder_program_init(pio0, 0, offset, ENC1_A, 0);
672 quadrature_encoder_program_init(pio0, 1, offset, ENC2_A, 0);
673
674 sleep_ms(3 * 1000);
675
676 printf("Hello ADIS16505\n");
677
678 printf(
679 "System clock: %d hz\n"
680 "PWM target frequency: %d hz, PWM clock divisor: "
681 "%f, PWM TOP: %d\n",
682 clock_get_hz(clk_sys), PWM_FREQ_HZ, divisor, PWM_TOP);
683
Ravago Jones23109002022-02-04 15:50:50 -0800684 setup_adis16505();
Ravago Jonesb83957c2021-12-29 19:57:34 -0800685
686 while (!yaw_zeroed) {
687 dma_channel_wait_for_finish_blocking(imu_dma_rx);
688 sleep_us(100);
689 zero_yaw(yaw_rate);
690 }
691
692 printf("Press q to enter bootloader\n");
693
694 while (1) {
695 dma_channel_wait_for_finish_blocking(imu_dma_rx);
696 // we want the interrupts to happen before or during the sleep so that we
697 // can get a good picture of what's going on without things moving around
698 sleep_us(100);
699
Ravago Jones23109002022-02-04 15:50:50 -0800700 if (reset_imu) {
701 printf("Triggered IMU reset, resetting\n");
702 setup_adis16505();
703 reset_imu = false;
704 }
705
Ravago Jonesb83957c2021-12-29 19:57:34 -0800706 // debug
707 // one printf is faster than many printfs
708 printf(
709 "Z pos is %f encoder: %d %d\n"
710 "Num failed checksums: %d, Total messages recieved: %d,\n"
711 "Num messages to pi: %d, Timing overrun count: %d,\n"
Ravago Jones23109002022-02-04 15:50:50 -0800712 "Send time: %d us, suspicious checksum count: %u,\n"
713 "IMU reset count: %d, checksum: %u,\n",
Ravago Jonesb83957c2021-12-29 19:57:34 -0800714 yaw, encoder1_count, encoder2_count, checksum_mismatch_count,
715 message_recieved_count, message_sent_count, timing_overrun_count,
Ravago Jones23109002022-02-04 15:50:50 -0800716 send_time, suspicious_checksums, imu_reset_count,
717 imu_data_buffer[IMU_NUM_ITEMS - 1]);
Ravago Jonesb83957c2021-12-29 19:57:34 -0800718
719 // allow the user to enter the bootloader without removing power or having
720 // to install a reset button
721 char user_input = getchar_timeout_us(0);
722 if (user_input == 'q') {
723 printf("Going down! entering bootloader\n");
724 reset_usb_boot(0, 0);
725 }
726
727 sleep_ms(50);
728 }
729
730 printf("All good\n");
731 dma_channel_unclaim(imu_dma_rx);
732 dma_channel_unclaim(imu_dma_tx);
733 dma_channel_unclaim(pi_dma_rx);
734 dma_channel_unclaim(pi_dma_tx);
735 return 0;
736}