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