blob: 84b33cd9b9ece4a885db71e791705ab0d511d9c0 [file] [log] [blame]
Brian Silverman4787a6e2018-10-06 16:00:54 -07001#include "motors/print/uart.h"
2
3#include "motors/core/kinetis.h"
4
5#include <atomic>
6
7namespace frc971 {
8namespace motors {
9namespace {
10
11::std::atomic<teensy::InterruptBufferedUart *> global_stdout{nullptr};
12
13} // namespace
14
15::std::unique_ptr<PrintingImplementation> CreatePrinting(
16 const PrintingParameters &parameters) {
17 if (parameters.stdout_uart_module == nullptr) {
18 return ::std::unique_ptr<PrintingImplementation>(new NopPrinting());
19 }
20 if (parameters.stdout_uart_module_clock_frequency == 0) {
21 return ::std::unique_ptr<PrintingImplementation>(new NopPrinting());
22 }
23 if (parameters.stdout_uart_status_interrupt < 0) {
24 return ::std::unique_ptr<PrintingImplementation>(new NopPrinting());
25 }
26 return ::std::unique_ptr<PrintingImplementation>(
27 new UartPrinting(parameters));
28}
29
30extern "C" void uart0_status_isr(void) {
31 teensy::InterruptBufferedUart *const tty =
32 global_stdout.load(::std::memory_order_relaxed);
33 DisableInterrupts disable_interrupts;
34 tty->HandleInterrupt(disable_interrupts);
35}
36
37UartPrinting::UartPrinting(const PrintingParameters &parameters)
38 : stdout_uart_{parameters.stdout_uart_module,
39 parameters.stdout_uart_module_clock_frequency},
40 stdout_status_interrupt_(parameters.stdout_uart_status_interrupt) {
41 stdout_uart_.Initialize(parameters.stdout_uart_baud_rate);
42}
43
44UartPrinting::~UartPrinting() {
45 NVIC_DISABLE_IRQ(stdout_status_interrupt_);
46 global_stdout.store(nullptr, ::std::memory_order_release);
47}
48
49void UartPrinting::Initialize() {
50 global_stdout.store(&stdout_uart_, ::std::memory_order_release);
51 NVIC_ENABLE_IRQ(stdout_status_interrupt_);
52}
53
54int UartPrinting::WriteStdout(gsl::span<const char> buffer) {
55 stdout_uart_.Write(buffer);
56 return buffer.size();
57}
58
59extern "C" int _write(const int /*file*/, char *const ptr, const int len) {
60 teensy::InterruptBufferedUart *const tty =
61 global_stdout.load(::std::memory_order_acquire);
62 if (tty != nullptr) {
63 tty->Write(gsl::make_span(ptr, len));
64 }
65 return len;
66}
67
68} // namespace motors
69} // namespace frc971