Brian Silverman | f91524f | 2017-09-23 13:15:55 -0400 | [diff] [blame^] | 1 | #ifndef MOTORS_USB_CONSTANTS_H_ |
| 2 | #define MOTORS_USB_CONSTANTS_H_ |
| 3 | |
| 4 | #include <stdint.h> |
| 5 | |
| 6 | namespace frc971 { |
| 7 | namespace teensy { |
| 8 | |
| 9 | enum class Direction : uint32_t { |
| 10 | kTx = 1 << 1, |
| 11 | kRx = 0, |
| 12 | }; |
| 13 | |
| 14 | enum class EvenOdd : uint32_t { |
| 15 | kOdd = 1 << 0, |
| 16 | kEven = 0, |
| 17 | }; |
| 18 | |
| 19 | constexpr 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. |
| 26 | constexpr 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 | |
| 31 | enum 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. |
| 54 | constexpr 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. |
| 59 | constexpr 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). |
| 66 | constexpr 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). |
| 73 | constexpr 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). |
| 80 | constexpr 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). |
| 92 | constexpr 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 | |
| 101 | enum class Data01 : uint32_t { |
| 102 | kData1 = 1 << 6, |
| 103 | kData0 = 0, |
| 104 | }; |
| 105 | |
| 106 | constexpr 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_ |