blob: 4b440a96588fa1bb7a3897f18c8dc34bf855fadd [file] [log] [blame]
Brian Silverman07ec88e2014-12-28 00:13:08 -08001#include "frc971/wpilib/gyro_interface.h"
2
3#include <inttypes.h>
4
5#include "aos/common/logging/logging.h"
6#include "aos/common/time.h"
7
8#ifndef M_PI
9#define M_PI 3.14159265358979323846
10#endif
11
12namespace frc971 {
13namespace wpilib {
14
15GyroInterface::GyroInterface() : gyro_(new SPI(SPI::kOnboardCS0)) {
16 // The gyro goes up to 8.08MHz.
17 // The myRIO goes up to 4MHz, so the roboRIO probably does too.
18 gyro_->SetClockRate(4e6);
19 gyro_->SetChipSelectActiveLow();
20 gyro_->SetClockActiveHigh();
21 gyro_->SetSampleDataOnRising();
22 gyro_->SetMSBFirst();
23}
24
25bool GyroInterface::InitializeGyro() {
26 uint32_t result;
27 if (!DoTransaction(0x20000003, &result)) {
28 LOG(WARNING, "failed to start a self-check\n");
29 return false;
30 }
31 if (result != 1) {
32 // We might have hit a parity error or something and are now retrying, so
33 // this isn't a very big deal.
34 LOG(INFO, "gyro unexpected initial response 0x%" PRIx32 "\n", result);
35 }
36
37 // Wait for it to assert the fault conditions before reading them.
38 ::aos::time::SleepFor(::aos::time::Time::InMS(50));
39
40 if (!DoTransaction(0x20000000, &result)) {
41 LOG(WARNING, "failed to clear latched non-fault data\n");
42 return false;
43 }
44 LOG(DEBUG, "gyro dummy response is 0x%" PRIx32 "\n", result);
45
46 if (!DoTransaction(0x20000000, &result)) {
47 LOG(WARNING, "failed to read self-test data\n");
48 return false;
49 }
50 if (ExtractStatus(result) != 2) {
51 LOG(WARNING, "gyro first value 0x%" PRIx32 " not self-test data\n", result);
52 return false;
53 }
54 if (ExtractErrors(result) != 0x7F) {
55 LOG(WARNING, "gyro first value 0x%" PRIx32 " does not have all errors\n",
56 result);
57 return false;
58 }
59
60 if (!DoTransaction(0x20000000, &result)) {
61 LOG(WARNING, "failed to clear latched self-test data\n");
62 return false;
63 }
64 if (ExtractStatus(result) != 2) {
65 LOG(WARNING, "gyro second value 0x%" PRIx32 " not self-test data\n",
66 result);
67 return false;
68 }
69
70 return true;
71}
72
73bool GyroInterface::DoTransaction(uint32_t to_write, uint32_t *result) {
74 static const uint8_t kBytes = 4;
75 static_assert(kBytes == sizeof(to_write),
76 "need the same number of bytes as sizeof(the data)");
77
78 if (__builtin_parity(to_write & ~1) == 0) to_write |= 1;
79
80 uint8_t to_send[kBytes], to_receive[kBytes];
81 const uint32_t to_write_flipped = __builtin_bswap32(to_write);
82 memcpy(to_send, &to_write_flipped, kBytes);
83
84 switch (gyro_->Transaction(to_send, to_receive, kBytes)) {
85 case -1:
86 LOG(INFO, "SPI::Transaction failed\n");
87 return false;
88 case kBytes:
89 break;
90 default:
91 LOG(FATAL, "SPI::Transaction returned something weird\n");
92 }
93
94 memcpy(result, to_receive, kBytes);
95 if (__builtin_parity(*result & 0xFFFF) != 1) {
96 LOG(INFO, "high byte parity failure\n");
97 return false;
98 }
99 if (__builtin_parity(*result) != 1) {
100 LOG(INFO, "whole value parity failure\n");
101 return false;
102 }
103
104 *result = __builtin_bswap32(*result);
105 return true;
106}
107
108uint16_t GyroInterface::DoRead(uint8_t address) {
109 const uint32_t command = (0x8 << 28) | (address << 17);
110 uint32_t response;
111 while (true) {
112 if (!DoTransaction(command, &response)) {
113 LOG(WARNING, "reading 0x%" PRIx8 " failed\n", address);
114 continue;
115 }
116 if ((response & 0xEFE00000) != 0x4E000000) {
117 LOG(WARNING, "gyro read from 0x%" PRIx8
118 " gave unexpected response 0x%" PRIx32 "\n",
119 address, response);
120 continue;
121 }
122 return (response >> 5) & 0xFFFF;
123 }
124}
125
126double GyroInterface::ExtractAngle(uint32_t value) {
127 const int16_t reading = -(int16_t)(value >> 10 & 0xFFFF);
128 return static_cast<double>(reading) * 2.0 * M_PI / 360.0 / 80.0;
129}
130
131uint32_t GyroInterface::ReadPartID() {
132 return (DoRead(0x0E) << 16) | DoRead(0x10);
133}
134
135uint32_t GyroInterface::GetReading() {
136 uint32_t result;
137 if (!DoTransaction(0x20000000, &result)) {
138 return 0;
139 }
140 return result;
141}
142
143} // namespace wpilib
144} // namespace frc971