blob: ca9910ef880e7c8fb53f93ecb94ab581f7b3a0f4 [file] [log] [blame]
Brian Silverman54dd2fe2018-03-16 23:44:31 -07001// This file has the main for the Teensy on the simple receiver board.
2
3#include <inttypes.h>
4#include <stdio.h>
5#include <atomic>
6#include <cmath>
7
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/util.h"
15
16namespace frc971 {
17namespace motors {
18namespace {
19
20::std::atomic<teensy::AcmTty *> global_stdout{nullptr};
21
22} // namespace
23
24extern "C" {
25
26void *__stack_chk_guard = (void *)0x67111971;
27
28int _write(int /*file*/, char *ptr, int len) {
29 teensy::AcmTty *const tty = global_stdout.load(::std::memory_order_acquire);
30 if (tty != nullptr) {
31 return tty->Write(ptr, len);
32 }
33 return 0;
34}
35
36void __stack_chk_fail(void);
37
38void DoTest() {
39 uint32_t time = micros();
40 while (true) {
41 for (int i = 0; i < 6; ++i) {
42 const uint32_t end = time_add(time, 500000);
43 while (true) {
44 const bool done = time_after(micros(), end);
45 double current;
46 if (done) {
47 current = -6;
48 } else {
49 current = 6;
50 }
51 const int32_t current_int = current * 1000;
52 uint32_t id = CAN_EFF_FLAG;
53 id |= i;
54 id |= (0x01 /* SET_CURRENT */) << 8;
55 uint8_t data[4] = {
56 static_cast<uint8_t>((current_int >> 24) & 0xFF),
57 static_cast<uint8_t>((current_int >> 16) & 0xFF),
58 static_cast<uint8_t>((current_int >> 8) & 0xFF),
59 static_cast<uint8_t>((current_int >> 0) & 0xFF),
60 };
61 can_send(id, data, sizeof(data), 2);
62 if (done) {
63 break;
64 }
65 delay(5);
66 }
67 time = end;
68 }
69 }
70}
71
72} // extern "C"
73
74extern "C" int main(void) {
75 // for background about this startup delay, please see these conversations
76 // https://forum.pjrc.com/threads/36606-startup-time-(400ms)?p=113980&viewfull=1#post113980
77 // https://forum.pjrc.com/threads/31290-Teensey-3-2-Teensey-Loader-1-24-Issues?p=87273&viewfull=1#post87273
78 delay(400);
79
80 // Set all interrupts to the second-lowest priority to start with.
81 for (int i = 0; i < NVIC_NUM_INTERRUPTS; i++) NVIC_SET_SANE_PRIORITY(i, 0xD);
82
83 // Now set priorities for all the ones we care about. They only have meaning
84 // relative to each other, which means centralizing them here makes it a lot
85 // more manageable.
86 NVIC_SET_SANE_PRIORITY(IRQ_USBOTG, 0x7);
87
88 // Builtin LED.
89 PERIPHERAL_BITBAND(GPIOC_PDOR, 5) = 1;
90 PORTC_PCR5 = PORT_PCR_DSE | PORT_PCR_SRE | PORT_PCR_MUX(1);
91 PERIPHERAL_BITBAND(GPIOC_PDDR, 5) = 1;
92
93 // Set up the CAN pins.
94 PORTA_PCR12 = PORT_PCR_DSE | PORT_PCR_MUX(2);
95 PORTA_PCR13 = PORT_PCR_DSE | PORT_PCR_MUX(2);
96
97 delay(100);
98
99 teensy::UsbDevice usb_device(0, 0x16c0, 0x0492);
100 usb_device.SetManufacturer("Seems Reasonable LLC");
101 usb_device.SetProduct("Simple Receiver Board");
102
103 teensy::AcmTty tty0(&usb_device);
104 global_stdout.store(&tty0, ::std::memory_order_release);
105 usb_device.Initialize();
106
107 can_init(0, 1);
108 salsa::AdcInitJoystick();
109
110 // Leave the LEDs on for a bit longer.
111 delay(300);
112 printf("Done starting up\n");
113
114 // Done starting up, now turn the LED off.
115 PERIPHERAL_BITBAND(GPIOC_PDOR, 5) = 0;
116
117 DoTest();
118
119 return 0;
120}
121
122void __stack_chk_fail(void) {
123 while (true) {
124 GPIOC_PSOR = (1 << 5);
125 printf("Stack corruption detected\n");
126 delay(1000);
127 GPIOC_PCOR = (1 << 5);
128 delay(1000);
129 }
130}
131
132} // namespace motors
133} // namespace frc971