blob: d52a698075ddd5dbc246964caf019372d5b35d41 [file] [log] [blame]
Brian Silverman49876942013-10-11 17:50:26 -07001#include "gyro.h"
2
3#include <stdio.h>
4#include <inttypes.h>
5
6#include "FreeRTOS.h"
7#include "task.h"
8#include "partest.h"
9
10struct GyroOutput gyro_output;
11
12static void gyro_disable_csel(void) {
13 // Set the CSEL pin high to deselect it.
14 GPIO0->FIOSET = 1 << 16;
15}
16
17static void gyro_enable_csel(void) {
18 // Clear the CSEL pin to select it.
19 GPIO0->FIOCLR = 1 << 16;
20}
21
22// Blocks until there is data available.
23static uint16_t spi_read(void) {
24 while (!(SSP0->SR & (1 << 2))) {}
25 return SSP0->DR;
26}
27
28// Blocks until there is space to enqueue data.
29static void spi_write(uint16_t data) {
30 while (!(SSP0->SR & (1 << 1))) {}
31 SSP0->DR = data;
32}
33
34static uint32_t do_gyro_read(uint32_t data, int *parity_error) {
35 *parity_error = 0;
36
37 gyro_enable_csel();
38 spi_write(data >> 16);
39 if (__builtin_parity(data & ~1) == 0) data |= 1;
40 spi_write(data);
41
42 uint16_t high_value = spi_read();
43 if (__builtin_parity(high_value) != 1) {
44 printf("high value 0x%"PRIx16" parity error\n", high_value);
45 *parity_error = 1;
46 }
47 uint16_t low_value = spi_read();
48 gyro_disable_csel();
49 if (__builtin_parity(low_value) != 1) {
50 printf("low value 0x%"PRIx16" parity error\n", high_value);
51 *parity_error = 1;
52 }
53
54 return high_value << 16 | low_value;
55}
56
57// Returns all of the non-data bits in the "header" except the parity from
58// value.
59static uint8_t gyro_status(uint32_t value) {
60 return (value >> 26) & ~4;
61}
62
63// Returns all of the error bits in the "footer" from value.
64static uint8_t gyro_errors(uint32_t value) {
65 return (value >> 1) & 0x7F;
66}
67
68// Performs a read from the gyro.
69// Sets *bad_reading to 1 if the result is potentially bad and *bad_gyro to 1 if
70// the gyro is bad and we're not going to get any more readings.
71static int16_t gyro_read(int *bad_reading, int *bad_gyro) {
72 *bad_reading = *bad_gyro = 0;
73
74 int parity_error;
75 uint32_t value = do_gyro_read(0x20000000, &parity_error);
76
77 if (parity_error) {
78 *bad_reading = 1;
79 return 0;
80 }
81
82 // This check assumes that the sequence bits are all 0, but they should be
83 // because that's all we send.
84 if (gyro_status(value) != 1) {
85 uint8_t status = gyro_status(value);
86 if (status == 0) {
87 printf("gyro says sensor data is bad\n");
88 } else {
89 printf("gyro gave weird status 0x%"PRIx8"\n", status);
90 }
91 *bad_reading = 1;
92 }
93
94 if (gyro_errors(value) != 0) {
95 uint8_t errors = gyro_errors(value);
96 if (errors & ~(1 << 1)) {
97 *bad_reading = 1;
98 // Error 1 (continuous self-test error) will set status to 0 if it's bad
99 // enough by itself.
100 }
101 if (errors & (1 << 6)) {
102 printf("gyro PLL error\n");
103 }
104 if (errors & (1 << 5)) {
105 printf("gyro quadrature error\n");
106 }
107 if (errors & (1 << 4)) {
108 printf("gyro non-volatile memory error\n");
109 *bad_gyro = 1;
110 }
111 if (errors & (1 << 3)) {
112 printf("gyro volatile memory error\n");
113 *bad_gyro = 1;
114 }
115 if (errors & (1 << 2)) {
116 printf("gyro power error\n");
117 }
118 if (errors & (1 << 1)) {
119 printf("gyro continuous self-test error\n");
120 }
121 if (errors & 1) {
122 printf("gyro unexpected self check mode\n");
123 }
124 }
125 if (*bad_gyro) {
126 *bad_reading = 1;
127 return 0;
128 } else {
129 return -(int16_t)(value >> 10 & 0xFFFF);
130 }
131}
132
133// Returns 1 if the setup failed or 0 if it succeeded.
134static int gyro_setup(void) {
135 for (int i = 0; i < 100; ++i) {
136 portTickType wait_time = xTaskGetTickCount();
137 int parity_error;
138
139 // Wait for it to start up.
140 vTaskDelayUntil(&wait_time, 100 / portTICK_RATE_MS);
141 // Get it started doing a check.
142 uint32_t value = do_gyro_read(0x20000003, &parity_error);
143 if (parity_error) continue;
144 // Its initial response is hardcoded to 1.
145 if (value != 1) {
146 printf("gyro unexpected initial response 0x%"PRIx32"\n", value);
147 // There's a chance that we're retrying because of a parity error
148 // previously, so keep going.
149 }
150
151 // Wait for it to assert the fault conditions.
152 vTaskDelayUntil(&wait_time, 50 / portTICK_RATE_MS);
153 // Dummy read to clear the old latched state.
154 do_gyro_read(0x20000000, &parity_error);
155 if (parity_error) continue;
156
157 // Wait for it to clear the fault conditions.
158 vTaskDelayUntil(&wait_time, 50 / portTICK_RATE_MS);
159 value = do_gyro_read(0x20000000, &parity_error);
160 if (parity_error) continue;
161 // If it's not reporting self test data.
162 if (gyro_status(value) != 2) {
163 printf("gyro first value 0x%"PRIx32" not self test data\n", value);
164 continue;
165 }
166 // If we don't see all of the errors.
167 if (gyro_errors(value) != 0x7F) {
168 printf("gyro self test value 0x%"PRIx32" is bad\n", value);
169 return 1;
170 }
171
172 // Wait for the sequential transfer delay.
173 vTaskDelayUntil(&wait_time, 1 / portTICK_RATE_MS);
174 value = do_gyro_read(0x20000000, &parity_error);
175 if (parity_error) continue;
176 // It should still be reporting self test data.
177 if (gyro_status(value) != 2) {
178 printf("gyro second value 0x%"PRIx32" not self test data\n", value);
179 continue;
180 }
181 return 0;
182 }
183 return 1;
184}
185
186static portTASK_FUNCTION(gyro_read_task, pvParameters) {
187 // How many times per second to read the gyro value.
188 static const int kGyroReadFrequency = 200;
189 // How many times per second to flash the LED.
190 // Must evenly divide kGyroReadFrequency.
191 static const int kFlashFrequency = 10;
192
193 static const int kStartupCycles = kGyroReadFrequency * 2;
194 static const int kZeroingCycles = kGyroReadFrequency * 6;
195
196 // An accumulator for all of the values read while zeroing.
197 int32_t zero_bias = 0;
198
199 int startup_cycles_left = kStartupCycles;
200 int zeroing_cycles_left = kZeroingCycles;
201
202 // These are a pair that hold the offset calculated while zeroing.
203 // full_units_ is the base (in ticks) and remainder_ ranges between 0 and
204 // kZeroingCycles (like struct timespec). remainder_ is used to calculate which
205 // cycles to add an additional unit to the result.
206 int32_t full_units_offset = 0;
207 int32_t remainder_offset = 0;
208 // This keeps track of when to add 1 to the read value (using _offset).
209 int32_t remainder_sum = 0;
210
211 int32_t led_flash = 0;
212 vParTestSetLED(0, 0);
213
214 portTickType xLastGyroReadTime = xTaskGetTickCount();
215
216 for (;;) {
217 ++led_flash;
218 if (led_flash < kGyroReadFrequency / kFlashFrequency / 2) {
219 vParTestSetLED(1, 0);
220 } else {
221 vParTestSetLED(1, 1);
222 }
223 if (led_flash >= kGyroReadFrequency / kFlashFrequency) {
224 led_flash = 0;
225 }
226
227 vTaskDelayUntil(&xLastGyroReadTime,
228 1000 / kGyroReadFrequency / portTICK_RATE_MS);
229
230 int bad_reading, bad_gyro;
231 int16_t gyro_value = gyro_read(&bad_reading, &bad_gyro);
232 if (bad_gyro) {
233 // We're just going to give up if this happens (write out that we're
234 // giving up and then never run anything else in this task).
235 vParTestSetLED(0, 1);
236 printf("gyro read task giving up because of bad gyro\n");
237 portENTER_CRITICAL();
238 gyro_output.gyro_bad = 1;
239 gyro_output.last_reading_bad = 1;
240 gyro_output.angle = 0;
241 portEXIT_CRITICAL();
242 vTaskDelete(NULL);
243 while (1) {}
244 }
245
246 if (startup_cycles_left) {
247 vParTestSetLED(2, 0);
248 --startup_cycles_left;
249 if (bad_reading) {
250 printf("gyro retrying startup wait because of bad reading\n");
251 startup_cycles_left = kStartupCycles;
252 }
253 } else if (zeroing_cycles_left) {
254 vParTestSetLED(2, 1);
255 --zeroing_cycles_left;
256 if (bad_reading) {
257 printf("gyro restarting zeroing because of bad reading\n");
258 zeroing_cycles_left = kZeroingCycles;
259 zero_bias = 0;
260 } else {
261 zero_bias -= gyro_value;
262 if (zeroing_cycles_left == 0) {
263 // Do all the nice math
264 full_units_offset = zero_bias / kZeroingCycles;
265 remainder_offset = zero_bias % kZeroingCycles;
266 if (remainder_offset < 0) {
267 remainder_offset += kZeroingCycles;
268 --full_units_offset;
269 }
270 }
271 }
272 } else {
273 vParTestSetLED(2, 0);
274
275 int64_t new_angle = gyro_output.angle;
276 if (!bad_reading) new_angle += gyro_value + full_units_offset;
277 if (remainder_sum >= kZeroingCycles) {
278 remainder_sum -= kZeroingCycles;
279 new_angle += 1;
280 }
281 portENTER_CRITICAL();
282 gyro_output.angle = new_angle;
283 gyro_output.last_reading_bad = bad_reading;
284 portEXIT_CRITICAL();
285 remainder_sum += remainder_offset;
286 }
287 }
288}
289
290void gyro_init(void) {
291 // Connect power and clock.
292 SC->PCONP |= PCONP_PCSSP0;
293 SC->PCLKSEL1 &= ~(3 << 10);
294 SC->PCLKSEL1 |= 1 << 10;
295
296 // Set up SSEL.
297 // It's is just a GPIO pin because we're the master (it would be special if we
298 // were a slave).
299 gyro_disable_csel();
300 GPIO0->FIODIR |= 1 << 16;
301 PINCON->PINSEL1 &= ~(3 << 0);
302 PINCON->PINSEL1 |= 0 << 0;
303
304 // Set up MISO0 and MOSI0.
305 PINCON->PINSEL1 &= ~(3 << 2 | 3 << 4);
306 PINCON->PINSEL1 |= 2 << 2 | 2 << 2;
307
308 // Set up SCK0.
309 PINCON->PINSEL0 &= ~(3 << 30);
310 PINCON->PINSEL0 |= (2 << 30);
311
312 // Make sure it's disabled.
313 SSP0->CR1 = 0;
314 SSP0->CR0 =
315 0xF /* 16 bit transfer */ |
316 0 << 4 /* SPI mode */ |
317 0 << 6 /* CPOL = 0 */ |
318 0 << 7 /* CPHA = 0 */;
319 // 14 clocks per cycle. This works out to a ~7.2MHz bus.
320 // The gyro is rated for a maximum of 8.08MHz.
321 SSP0->CPSR = 14;
322 // Set it to master mode.
323 SSP0->CR1 |= 1 << 2;
324 // Finally, enable it.
325 // This has to be done after we're done messing with everything else.
326 SSP0->CR1 |= 1 << 1;
327
328 if (gyro_setup()) {
329 printf("gyro setup failed. not starting task\n");
330 gyro_output.angle = 0;
331 gyro_output.last_reading_bad = gyro_output.gyro_bad = 1;
332 return;
333 }
334
335 gyro_output.angle = 0;
336 gyro_output.last_reading_bad = 1; // until we're started up
337 gyro_output.gyro_bad = 0;
338
339 xTaskCreate(gyro_read_task, (signed char *) "gyro",
340 configMINIMAL_STACK_SIZE + 100, NULL,
341 tskIDLE_PRIORITY + 2, NULL);
342}