blob: 7e4a43ca5f25754ffe06597740f79d38b9ee92d9 [file] [log] [blame]
Brian Silverman259c4432018-01-15 14:34:21 -08001// This file has the main for the Teensy on the button board.
2
Brian Silverman259c4432018-01-15 14:34:21 -08003#include <inttypes.h>
Austin Schuh75c6af42018-03-09 21:16:07 -08004#include <stdio.h>
Brian Silverman259c4432018-01-15 14:34:21 -08005#include <atomic>
Austin Schuh75c6af42018-03-09 21:16:07 -08006#include <cmath>
Brian Silverman259c4432018-01-15 14:34:21 -08007
8#include "motors/core/time.h"
9#include "motors/core/kinetis.h"
10#include "motors/peripheral/adc.h"
11#include "motors/peripheral/can.h"
12#include "motors/usb/usb.h"
13#include "motors/usb/cdc.h"
14#include "motors/usb/hid.h"
15#include "motors/util.h"
16
17namespace frc971 {
18namespace motors {
19namespace {
20
21::std::atomic<teensy::AcmTty *> global_stdout{nullptr};
22
23// The HID report descriptor we use.
Austin Schuh75c6af42018-03-09 21:16:07 -080024constexpr char kReportDescriptor1[] = {
Brian Silverman259c4432018-01-15 14:34:21 -080025 0x05, 0x01, // Usage Page (Generic Desktop),
26 0x09, 0x04, // Usage (Joystick),
27 0xA1, 0x01, // Collection (Application),
28 0x75, 0x08, // Report Size (8),
29 0x95, 0x04, // Report Count (4),
30 0x15, 0x00, // Logical Minimum (0),
31 0x26, 0xFF, 0x00, // Logical Maximum (255),
32 0x35, 0x00, // Physical Minimum (0),
33 0x46, 0xFF, 0x00, // Physical Maximum (255),
34 0x09, 0x30, // Usage (X),
35 0x09, 0x31, // Usage (Y),
36 0x09, 0x32, // Usage (Z),
37 0x09, 0x33, // Usage (Rz),
38 0x81, 0x02, // Input (Variable),
39 0x75, 0x01, // Report Size (1),
Austin Schuh75c6af42018-03-09 21:16:07 -080040 0x95, 0x10, // Report Count (16),
Brian Silverman259c4432018-01-15 14:34:21 -080041 0x25, 0x01, // Logical Maximum (1),
42 0x45, 0x01, // Physical Maximum (1),
43 0x05, 0x09, // Usage Page (Button),
44 0x19, 0x01, // Usage Minimum (01),
Austin Schuh75c6af42018-03-09 21:16:07 -080045 0x29, 0x10, // Usage Maximum (16),
Brian Silverman259c4432018-01-15 14:34:21 -080046 0x81, 0x02, // Input (Variable),
Brian Silverman259c4432018-01-15 14:34:21 -080047 0xC0 // End Collection
48};
49
Austin Schuh75c6af42018-03-09 21:16:07 -080050constexpr uint16_t report_size() { return 1 * 4 + 2; }
Brian Silverman259c4432018-01-15 14:34:21 -080051
Austin Schuh75c6af42018-03-09 21:16:07 -080052char DecodeAnalog(int analog) {
53 // None: 132
54 // Far: 71
55 // Near: 103
56 // Both: 0
57 if (analog < 30) {
58 return 0x3;
59 } else if (::std::abs(analog - 71) < 10) {
60 return 0x2;
61 } else if (::std::abs(analog - 103) < 10) {
62 return 0x1;
63 } else {
64 return 0x0;
65 }
66}
67
68void SendJoystickData(teensy::HidFunction *joystick0,
69 teensy::HidFunction *joystick1) {
Brian Silverman259c4432018-01-15 14:34:21 -080070 uint32_t start = micros();
71 while (true) {
72 salsa::JoystickAdcReadings adc;
Austin Schuh75c6af42018-03-09 21:16:07 -080073 char report0[report_size()];
74 char report1[report_size()];
Brian Silverman259c4432018-01-15 14:34:21 -080075 {
76 DisableInterrupts disable_interrupts;
77 adc = salsa::AdcReadJoystick(disable_interrupts);
78 }
79
80 FTM0->C1V = adc.analog0 / 4;
81 FTM0->C0V = adc.analog1 / 4;
82 FTM0->C4V = adc.analog2 / 4;
83 FTM0->C3V = adc.analog3 / 4;
84 FTM0->PWMLOAD = FTM_PWMLOAD_LDOK;
Austin Schuh75c6af42018-03-09 21:16:07 -080085 report0[0] = report1[0] = adc.analog0 / 16;
86 report0[1] = report1[1] = adc.analog1 / 16;
87 report0[2] = report1[2] = adc.analog2 / 16;
88 report0[3] = report1[3] = adc.analog3 / 16;
Brian Silverman259c4432018-01-15 14:34:21 -080089
Brian Silverman33eb5fa2018-02-11 18:36:19 -050090 report0[4] = ((PERIPHERAL_BITBAND(GPIOD_PDIR, 5) << 0) |
91 (PERIPHERAL_BITBAND(GPIOD_PDIR, 6) << 1) |
92 (PERIPHERAL_BITBAND(GPIOB_PDIR, 0) << 2) |
93 (PERIPHERAL_BITBAND(GPIOB_PDIR, 1) << 3) |
94 (PERIPHERAL_BITBAND(GPIOA_PDIR, 14) << 4) |
95 (PERIPHERAL_BITBAND(GPIOE_PDIR, 26) << 5) |
96 (PERIPHERAL_BITBAND(GPIOA_PDIR, 16) << 6) |
97 (PERIPHERAL_BITBAND(GPIOA_PDIR, 15) << 7)) ^
Austin Schuh75c6af42018-03-09 21:16:07 -080098 0xff;
Brian Silverman259c4432018-01-15 14:34:21 -080099
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500100 report0[5] = ((PERIPHERAL_BITBAND(GPIOE_PDIR, 25) << 0) |
101 (PERIPHERAL_BITBAND(GPIOE_PDIR, 24) << 1) |
102 (PERIPHERAL_BITBAND(GPIOC_PDIR, 3) << 2) |
103 (PERIPHERAL_BITBAND(GPIOC_PDIR, 7) << 3) |
104 (PERIPHERAL_BITBAND(GPIOD_PDIR, 3) << 4) |
105 (PERIPHERAL_BITBAND(GPIOD_PDIR, 2) << 5) |
106 (PERIPHERAL_BITBAND(GPIOD_PDIR, 7) << 6) |
107 (PERIPHERAL_BITBAND(GPIOA_PDIR, 13) << 7)) ^
Austin Schuh75c6af42018-03-09 21:16:07 -0800108 0xff;
Brian Silverman259c4432018-01-15 14:34:21 -0800109
Austin Schuh75c6af42018-03-09 21:16:07 -0800110 report1[4] =
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500111 ((PERIPHERAL_BITBAND(GPIOA_PDIR, 12) << 0) |
112 (PERIPHERAL_BITBAND(GPIOD_PDIR, 0) << 1) |
113 (PERIPHERAL_BITBAND(GPIOB_PDIR, 17) << 2) |
114 (PERIPHERAL_BITBAND(GPIOB_PDIR, 16) << 3) | (DecodeAnalog(report1[0]) << 4) |
Austin Schuh75c6af42018-03-09 21:16:07 -0800115 (DecodeAnalog(report1[1]) << 6)) ^
116 0x0f;
117 report1[5] = (DecodeAnalog(report1[2])) | (DecodeAnalog(report1[3]) << 2);
Brian Silverman259c4432018-01-15 14:34:21 -0800118
119 {
120 DisableInterrupts disable_interrupts;
Austin Schuh75c6af42018-03-09 21:16:07 -0800121 joystick0->UpdateReport(report0, sizeof(report0), disable_interrupts);
122 joystick1->UpdateReport(report1, sizeof(report1), disable_interrupts);
Brian Silverman259c4432018-01-15 14:34:21 -0800123 }
124
125 start = delay_from(start, 1);
126 }
127}
128
129void SetupLedFtm(BigFTM *ftm) {
130 // PWMSYNC doesn't matter because we set SYNCMODE down below.
131 ftm->MODE = FTM_MODE_WPDIS;
132 ftm->MODE = FTM_MODE_WPDIS | FTM_MODE_FTMEN;
133 ftm->SC = FTM_SC_CLKS(0) /* Disable counting for now */;
134
135 // Use center-aligned high-true for all the channels.
136 ftm->C0SC = FTM_CSC_ELSB;
137 ftm->C0V = 0;
138 ftm->C1SC = FTM_CSC_ELSB;
139 ftm->C1V = 0;
140 ftm->C2SC = FTM_CSC_ELSB;
141 ftm->C2V = 0;
142 ftm->C3SC = FTM_CSC_ELSB;
143 ftm->C3V = 0;
144 ftm->C4SC = FTM_CSC_ELSB;
145 ftm->C4V = 0;
146 ftm->C5SC = FTM_CSC_ELSB;
147 ftm->C5V = 0;
148 ftm->C6SC = FTM_CSC_ELSB;
149 ftm->C6V = 0;
150 ftm->C7SC = FTM_CSC_ELSB;
151 ftm->C7V = 0;
152
153 ftm->COMBINE = FTM_COMBINE_SYNCEN3 /* Synchronize updates usefully */ |
154 FTM_COMBINE_SYNCEN2 /* Synchronize updates usefully */ |
155 FTM_COMBINE_SYNCEN1 /* Synchronize updates usefully */ |
156 FTM_COMBINE_SYNCEN0 /* Synchronize updates usefully */;
157
158 ftm->CNTIN = 0;
159 ftm->CNT = 0;
160 ftm->MOD = 1024;
161 ftm->OUTINIT = 0;
162 ftm->POL = 0;
163 ftm->SYNCONF =
164 FTM_SYNCONF_HWWRBUF /* Hardware trigger flushes switching points */ |
165 FTM_SYNCONF_SWWRBUF /* Software trigger flushes switching points */ |
166 FTM_SYNCONF_SWRSTCNT /* Software trigger resets the count */ |
167 FTM_SYNCONF_SYNCMODE /* Use the new synchronization mode */;
168 // Don't want any intermediate loading points.
169 ftm->PWMLOAD = 0;
170
171 ftm->SYNC = FTM_SYNC_SWSYNC /* Flush everything out right now */;
172 // Wait for the software synchronization to finish.
173 while (ftm->SYNC & FTM_SYNC_SWSYNC) {
174 }
175 ftm->SC = FTM_SC_CPWMS /* Center-aligned PWM */ |
176 FTM_SC_CLKS(1) /* Use the system clock */ |
Brian Silverman5ffd2c22018-03-23 22:26:17 -0400177 FTM_SC_PS(6) /* Prescaler=64 */;
Brian Silverman259c4432018-01-15 14:34:21 -0800178
179 ftm->MODE &= ~FTM_MODE_WPDIS;
180}
181
182} // namespace
183
184extern "C" {
185
186void *__stack_chk_guard = (void *)0x67111971;
187
188int _write(int /*file*/, char *ptr, int len) {
189 teensy::AcmTty *const tty = global_stdout.load(::std::memory_order_acquire);
190 if (tty != nullptr) {
191 return tty->Write(ptr, len);
192 }
193 return 0;
194}
195
196void __stack_chk_fail(void);
197
198} // extern "C"
199
200extern "C" int main(void) {
201 // for background about this startup delay, please see these conversations
202 // https://forum.pjrc.com/threads/36606-startup-time-(400ms)?p=113980&viewfull=1#post113980
203 // https://forum.pjrc.com/threads/31290-Teensey-3-2-Teensey-Loader-1-24-Issues?p=87273&viewfull=1#post87273
204 delay(400);
205
206 // Set all interrupts to the second-lowest priority to start with.
207 for (int i = 0; i < NVIC_NUM_INTERRUPTS; i++) NVIC_SET_SANE_PRIORITY(i, 0xD);
208
209 // Now set priorities for all the ones we care about. They only have meaning
210 // relative to each other, which means centralizing them here makes it a lot
211 // more manageable.
212 NVIC_SET_SANE_PRIORITY(IRQ_USBOTG, 0x7);
213
214 // Set all the LED pins to output, slew rate controlled, high drive strength.
215 // Builtin
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500216 PERIPHERAL_BITBAND(GPIOC_PDOR, 5) = 1;
Brian Silverman259c4432018-01-15 14:34:21 -0800217 PORTC_PCR5 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(1);
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500218 PERIPHERAL_BITBAND(GPIOC_PDDR, 5) = 1;
Brian Silverman259c4432018-01-15 14:34:21 -0800219 // LED0 FTM0_CH1
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500220 PERIPHERAL_BITBAND(GPIOC_PDOR, 2) = 0;
Brian Silverman259c4432018-01-15 14:34:21 -0800221 PORTC_PCR2 = PORT_PCR_DSE | PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_MUX(4);
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500222 PERIPHERAL_BITBAND(GPIOC_PDDR, 2) = 1;
Brian Silverman259c4432018-01-15 14:34:21 -0800223 // LED1 FTM0_CH0
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500224 PERIPHERAL_BITBAND(GPIOC_PDOR, 1) = 0;
Brian Silverman259c4432018-01-15 14:34:21 -0800225 PORTC_PCR1 = PORT_PCR_DSE | PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_MUX(4);
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500226 PERIPHERAL_BITBAND(GPIOC_PDDR, 1) = 1;
Brian Silverman259c4432018-01-15 14:34:21 -0800227 // LED2 FTM0_CH4
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500228 PERIPHERAL_BITBAND(GPIOD_PDOR, 4) = 0;
Brian Silverman259c4432018-01-15 14:34:21 -0800229 PORTD_PCR4 = PORT_PCR_DSE | PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_MUX(4);
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500230 PERIPHERAL_BITBAND(GPIOD_PDDR, 4) = 1;
Brian Silverman259c4432018-01-15 14:34:21 -0800231 // LED3 FTM0_CH3
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500232 PERIPHERAL_BITBAND(GPIOC_PDOR, 4) = 0;
Brian Silverman259c4432018-01-15 14:34:21 -0800233 PORTC_PCR4 = PORT_PCR_DSE | PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_MUX(4);
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500234 PERIPHERAL_BITBAND(GPIOC_PDDR, 4) = 1;
Brian Silverman259c4432018-01-15 14:34:21 -0800235 // LED4 FTM3_CH4 yellow
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500236 PERIPHERAL_BITBAND(GPIOC_PDOR, 8) = 0;
Brian Silverman259c4432018-01-15 14:34:21 -0800237 PORTC_PCR8 = PORT_PCR_DSE | PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_MUX(1);
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500238 PERIPHERAL_BITBAND(GPIOC_PDDR, 8) = 1;
Brian Silverman259c4432018-01-15 14:34:21 -0800239 // LED5 FTM3_CH5 green
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500240 PERIPHERAL_BITBAND(GPIOC_PDOR, 9) = 0;
Brian Silverman259c4432018-01-15 14:34:21 -0800241 PORTC_PCR9 = PORT_PCR_DSE | PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_MUX(1);
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500242 PERIPHERAL_BITBAND(GPIOC_PDDR, 9) = 1;
Brian Silverman259c4432018-01-15 14:34:21 -0800243 // LED6 FTM3_CH6 red
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500244 PERIPHERAL_BITBAND(GPIOC_PDOR, 10) = 0;
Brian Silverman259c4432018-01-15 14:34:21 -0800245 PORTC_PCR10 = PORT_PCR_DSE | PORT_PCR_ODE | PORT_PCR_SRE | PORT_PCR_MUX(1);
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500246 PERIPHERAL_BITBAND(GPIOC_PDDR, 10) = 1;
Brian Silverman259c4432018-01-15 14:34:21 -0800247
248 // Set up the CAN pins.
249 PORTB_PCR18 = PORT_PCR_DSE | PORT_PCR_MUX(2);
250 PORTB_PCR19 = PORT_PCR_DSE | PORT_PCR_MUX(2);
251
Brian Silvermanff7b3872018-03-10 18:08:30 -0800252 // .1ms filter time.
253 PORTA_DFWR = PORTB_DFWR = PORTC_DFWR = PORTD_DFWR = PORTE_DFWR = 6000;
254
Brian Silverman259c4432018-01-15 14:34:21 -0800255 // Set up the buttons. The LEDs pull them up to 5V, so the Teensy needs to not
256 // be set to pull up.
257 // BTN0
258 PORTD_PCR5 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800259 PORTD_DFER |= 1 << 5;
Brian Silverman259c4432018-01-15 14:34:21 -0800260 // BTN1
261 PORTD_PCR6 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800262 PORTD_DFER |= 1 << 6;
Brian Silverman259c4432018-01-15 14:34:21 -0800263 // BTN2
Brian Silverman772a3482018-02-05 23:54:00 -0500264 PORTB_PCR0 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800265 PORTB_DFER |= 1 << 0;
Brian Silverman259c4432018-01-15 14:34:21 -0800266 // BTN3
267 PORTB_PCR1 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800268 PORTB_DFER |= 1 << 1;
Brian Silverman259c4432018-01-15 14:34:21 -0800269 // BTN4
270 PORTA_PCR14 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800271 PORTA_DFER |= 1 << 14;
Brian Silverman259c4432018-01-15 14:34:21 -0800272 // BTN5
273 PORTE_PCR26 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800274 PORTE_DFER |= 1 << 26;
Brian Silverman259c4432018-01-15 14:34:21 -0800275 // BTN6
276 PORTA_PCR16 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800277 PORTA_DFER |= 1 << 16;
Brian Silverman259c4432018-01-15 14:34:21 -0800278 // BTN7
279 PORTA_PCR15 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800280 PORTA_DFER |= 1 << 15;
Brian Silverman259c4432018-01-15 14:34:21 -0800281 // BTN8
282 PORTE_PCR25 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800283 PORTE_DFER |= 1 << 25;
Brian Silverman259c4432018-01-15 14:34:21 -0800284 // BTN9
285 PORTE_PCR24 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800286 PORTE_DFER |= 1 << 24;
Brian Silverman259c4432018-01-15 14:34:21 -0800287 // BTN10
288 PORTC_PCR3 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800289 PORTC_DFER |= 1 << 3;
Brian Silverman259c4432018-01-15 14:34:21 -0800290 // BTN11
291 PORTC_PCR7 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800292 PORTC_DFER |= 1 << 7;
Brian Silverman259c4432018-01-15 14:34:21 -0800293 // BTN12
294 PORTD_PCR3 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800295 PORTD_DFER |= 1 << 3;
Brian Silverman259c4432018-01-15 14:34:21 -0800296 // BTN13
297 PORTD_PCR2 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800298 PORTD_DFER |= 1 << 2;
Brian Silverman259c4432018-01-15 14:34:21 -0800299 // BTN14
300 PORTD_PCR7 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800301 PORTD_DFER |= 1 << 7;
Brian Silverman259c4432018-01-15 14:34:21 -0800302 // BTN15
303 PORTA_PCR13 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800304 PORTA_DFER |= 1 << 13;
Brian Silverman259c4432018-01-15 14:34:21 -0800305 // BTN16
306 PORTA_PCR12 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800307 PORTA_DFER |= 1 << 12;
Brian Silverman259c4432018-01-15 14:34:21 -0800308 // BTN17
309 PORTD_PCR0 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800310 PORTD_DFER |= 1 << 0;
Brian Silverman259c4432018-01-15 14:34:21 -0800311 // BTN18
312 PORTB_PCR17 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800313 PORTB_DFER |= 1 << 17;
Brian Silverman259c4432018-01-15 14:34:21 -0800314 // BTN19
315 PORTB_PCR16 = PORT_PCR_MUX(1);
Brian Silvermanff7b3872018-03-10 18:08:30 -0800316 PORTB_DFER |= 1 << 16;
Brian Silverman259c4432018-01-15 14:34:21 -0800317
318 delay(100);
319
320 teensy::UsbDevice usb_device(0, 0x16c0, 0x0492);
321 usb_device.SetManufacturer("FRC 971 Spartan Robotics");
322 usb_device.SetProduct("Spartan Joystick Board");
Austin Schuh75c6af42018-03-09 21:16:07 -0800323
324 teensy::HidFunction joystick0(&usb_device, report_size());
325 joystick0.set_report_descriptor(
326 ::std::string(kReportDescriptor1, sizeof(kReportDescriptor1)));
327
328 teensy::HidFunction joystick1(&usb_device, report_size());
329 joystick1.set_report_descriptor(
330 ::std::string(kReportDescriptor1, sizeof(kReportDescriptor1)));
331
Brian Silverman259c4432018-01-15 14:34:21 -0800332 teensy::AcmTty tty1(&usb_device);
333 global_stdout.store(&tty1, ::std::memory_order_release);
334 usb_device.Initialize();
335
336 can_init(0, 1);
337 salsa::AdcInitJoystick();
338 SetupLedFtm(FTM0);
339 SetupLedFtm(FTM3);
340
341 // Leave the LEDs on for a bit longer.
342 delay(300);
343 printf("Done starting up\n");
344
345 // Done starting up, now turn all the LEDs off.
Brian Silverman33eb5fa2018-02-11 18:36:19 -0500346 PERIPHERAL_BITBAND(GPIOC_PDOR, 5) = 0;
347 PERIPHERAL_BITBAND(GPIOC_PDOR, 2) = 1;
348 PERIPHERAL_BITBAND(GPIOC_PDOR, 1) = 1;
349 PERIPHERAL_BITBAND(GPIOD_PDOR, 4) = 1;
350 PERIPHERAL_BITBAND(GPIOC_PDOR, 4) = 1;
351 PERIPHERAL_BITBAND(GPIOC_PDOR, 8) = 1;
352 PERIPHERAL_BITBAND(GPIOC_PDOR, 9) = 1;
353 PERIPHERAL_BITBAND(GPIOC_PDOR, 10) = 1;
Brian Silverman259c4432018-01-15 14:34:21 -0800354
Austin Schuh75c6af42018-03-09 21:16:07 -0800355 SendJoystickData(&joystick0, &joystick1);
Brian Silverman259c4432018-01-15 14:34:21 -0800356
357 return 0;
358}
359
360void __stack_chk_fail(void) {
361 while (true) {
362 GPIOC_PSOR = (1 << 5);
363 printf("Stack corruption detected\n");
364 delay(1000);
365 GPIOC_PCOR = (1 << 5);
366 delay(1000);
367 }
368}
369
370} // namespace motors
371} // namespace frc971