blob: 58c9eccceec15a196bc59237ea495d239d99e94b [file] [log] [blame]
Brian Silvermanf91524f2017-09-23 13:15:55 -04001#ifndef MOTORS_USB_CONSTANTS_H_
2#define MOTORS_USB_CONSTANTS_H_
3
4#include <stdint.h>
5
6namespace frc971 {
7namespace teensy {
8
9enum class Direction : uint32_t {
10 kTx = 1 << 1,
11 kRx = 0,
12};
13
14enum class EvenOdd : uint32_t {
15 kOdd = 1 << 0,
16 kEven = 0,
17};
18
19constexpr static inline EvenOdd EvenOddInverse(EvenOdd odd) {
20 return static_cast<EvenOdd>(static_cast<uint32_t>(odd) ^
21 static_cast<uint32_t>(EvenOdd::kOdd));
22}
23
24// Returns 0 for kEven and 1 for kOdd. This is useful for indexing into arrays
25// and similar things.
26constexpr static inline int EvenOddIndex(EvenOdd odd) {
27 static_assert(static_cast<int>(EvenOdd::kOdd) == 1, "Value changed");
28 return static_cast<int>(odd);
29}
30
31enum class EndpointBufferState : int {
32 // The values are chosen carefully so bit arithmetic can efficiently
33 // manipulate these values. This math is all encapsulated in methods
34 // immediately following.
35 // Bit 0 is even full.
36 // Bit 1 is odd full.
37 // Bit 2 is which one to fill next (1 for odd).
38 // Bit 3 is which one to empty next (1 for odd).
39
40 // Both are empty and we should fill the even one first.
41 kBothEmptyEvenFirst = 0x0,
42 kBothEmptyOddFirst = 0xC,
43 kEvenFull = 0x5,
44 kOddFull = 0xA,
45 // Both are full and we should empty the even one first.
46 kBothFullEvenFirst = 0x3,
47 kBothFullOddFirst = 0xF,
48};
49
50// kBothEmptyEvenFirst fill even kEvenFull fill odd kBothFullEvenFirst
51// empty even kOddFull empty odd kBothEmptyEvenFirst
52
53// Returns true if state has at least one empty buffer.
54constexpr static inline bool BufferStateHasEmpty(EndpointBufferState state) {
55 return (static_cast<int>(state) & 0x3) != 0x3;
56}
57
58// Returns true if state has at least one full buffer.
59constexpr static inline bool BufferStateHasFull(EndpointBufferState state) {
60 return (static_cast<int>(state) & 0x3) != 0;
61}
62
63// Returns the next buffer to fill from state.
64//
65// This won't make sense if !BufferStateHasEmpty(state).
66constexpr static inline EvenOdd BufferStateToFill(EndpointBufferState state) {
67 return (static_cast<int>(state) & 0x4) ? EvenOdd::kOdd : EvenOdd::kEven;
68}
69
70// Returns the next buffer to empty from state.
71//
72// This won't make sense if !BufferStateHasFull(state).
73constexpr static inline EvenOdd BufferStateToEmpty(EndpointBufferState state) {
74 return (static_cast<int>(state) & 0x8) ? EvenOdd::kOdd : EvenOdd::kEven;
75}
76
77// Returns the new state after filling BufferStateToFill(state).
78//
79// This won't make sense if !BufferStateHasEmpty(state).
80constexpr static inline EndpointBufferState BufferStateAfterFill(
81 EndpointBufferState state) {
82 return static_cast<EndpointBufferState>(
83 // XOR with bit 2 to toggle which is next.
84 (static_cast<int>(state) ^ 0x4) |
85 // Set the bit corresponding to the buffer which was filled.
86 (1 << EvenOddIndex(BufferStateToFill(state))));
87}
88
89// Returns the new state after emptying BufferStateToEmpty(state).
90//
91// This won't make sense if !BufferStateHasFull(state).
92constexpr static inline EndpointBufferState BufferStateAfterEmpty(
93 EndpointBufferState state) {
94 return static_cast<EndpointBufferState>(
95 // XOR with bit 3 to toggle which is next.
96 (static_cast<int>(state) ^ 0x8) &
97 // Clear the bit corresponding to the buffer which was emptied.
98 ~(1 << EvenOddIndex(BufferStateToEmpty(state))));
99}
100
101enum class Data01 : uint32_t {
102 kData1 = 1 << 6,
103 kData0 = 0,
104};
105
106constexpr static inline Data01 Data01Inverse(Data01 toggle) {
107 return static_cast<Data01>(static_cast<uint32_t>(toggle) ^
108 static_cast<uint32_t>(Data01::kData1));
109}
110
111} // namespace teensy
112} // namespace frc971
113
114#endif // MOTORS_USB_CONSTANTS_H_