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