Add a working CDC TTY USB device
I'm pretty sure it reliably moves data in both directions, but it has a
lot of TODOs left wrt error handling.
Change-Id: I1d96a63eea7bdc08f6ec78c868c4a1ccbfbda600
diff --git a/motors/usb/queue.h b/motors/usb/queue.h
new file mode 100644
index 0000000..669abe4
--- /dev/null
+++ b/motors/usb/queue.h
@@ -0,0 +1,69 @@
+#ifndef MOTORS_USB_QUEUE_H_
+#define MOTORS_USB_QUEUE_H_
+
+#include <memory>
+#include <atomic>
+
+namespace frc971 {
+namespace teensy {
+
+// A FIFO queue which reads/writes variable-sized chunks.
+//
+// Reading data happens-after it is written. However, external synchronization
+// between multiple readers/writers is required.
+class Queue {
+ public:
+ Queue(size_t size) : size_(size), data_(new char[size]) {}
+
+ // Writes as much of in_data as will fit to the queue. Returns the number of
+ // bytes written.
+ size_t Write(const char *in_data, size_t in_size);
+
+ // Reads up to out_size from the queue into out_data. Returns the number of
+ // bytes read.
+ size_t Read(char *out_data, size_t out_size);
+
+ size_t data_queued() const {
+ return space_used(read_cursor_.load(::std::memory_order_relaxed),
+ write_cursor_.load(::std::memory_order_relaxed));
+ }
+
+ size_t space_available() const {
+ return size_ - data_queued() - 1;
+ }
+
+ bool empty() const {
+ return read_cursor_.load(::std::memory_order_relaxed) ==
+ write_cursor_.load(::std::memory_order_relaxed);
+ }
+
+ private:
+ size_t space_used(size_t read_cursor, size_t write_cursor) const {
+ size_t r = write_cursor - read_cursor;
+ if (r > size_) {
+ r = size_ + r;
+ }
+ return r;
+ }
+
+ size_t wrap(size_t cursor) const {
+ if (cursor >= size_) {
+ return cursor - size_;
+ } else {
+ return cursor;
+ }
+ }
+
+ const size_t size_;
+ const ::std::unique_ptr<char[]> data_;
+
+ // The next index we're going to read from.
+ ::std::atomic<size_t> read_cursor_{0};
+ // The next index we're going to write to.
+ ::std::atomic<size_t> write_cursor_{0};
+};
+
+} // namespace teensy
+} // namespace frc971
+
+#endif // MOTORS_USB_QUEUE_H_