blob: cda78439739efeea4c8762cf589fa6b8f02fde36 [file] [log] [blame]
Brian Silverman1e869f32013-10-25 18:00:20 -07001#ifndef FRC971_INPUT_USB_RECEIVER_H_
2#define FRC971_INPUT_USB_RECEIVER_H_
3
4#include <memory>
5
6#include "aos/common/time.h"
7#include "aos/common/util/wrapping_counter.h"
8
9#include "gyro_board/src/libusb-driver/libusb_wrap.h"
10#include "frc971/input/gyro_board_data.h"
11
12namespace frc971 {
13
14// TODO(brians): Figure out how to deal with the kernel bunching packets up on
15// us.
16class USBReceiver {
17 public:
18 USBReceiver();
19
20 void RunIteration();
21
22 protected:
23 GyroBoardData *data() { return &data_; }
24
25 private:
26 static const unsigned char kEndpoint = 0x83;
27 // 0 is unlimited
28 static constexpr ::aos::time::Time kReadTimeout =
29 ::aos::time::Time::InSeconds(1.5);
30 // vendor ID
31 static const int32_t kVid = 0x1424;
32 // product ID
33 static const int32_t kPid = 0xd243;
34
35 // A value to put into completed_transfer_ to indicate that it failed.
36 static constexpr libusb::Transfer *kTransferFailed =
37 reinterpret_cast<libusb::Transfer *>(-1);
38 // The kernel on the fitpc seems to miss ~11-15 packets in a row if it misses
39 // any with just 2, so 25 should be enough to ride over any holes.
40 static const int kNumTransfers = 25;
41
42 // How big of a buffer we're going to give the usb transfer stuff.
43 static const size_t kDataLength = 128;
44 static_assert(kDataLength >= sizeof(GyroBoardData), "buffer is too small");
45
46 static const int kPacketsPerLoopCycle = 10;
47
48 // How long "after" the control loops run we want to use a packet.
49 static constexpr ::aos::time::Time kDesiredOffset =
50 ::aos::time::Time::InSeconds(-0.003);
51
52 // How long without a good packet until we give up and Reset().
53 static constexpr ::aos::time::Time kResetTime =
54 ::aos::time::Time::InSeconds(0.25);
55
56 // Contains all of the complicated state and logic for locking onto the the
57 // correct phase.
58 class PhaseLocker {
59 public:
60 void Reset();
61
62 // Gets called for every packet received.
63 // Returns whether or not to process the values from this packet.
64 bool IsCurrentPacketGood(const ::aos::time::Time &received_time,
65 int32_t sequence);
66
67 private:
68 // How many times the packet we guessed has to be close to right to use the
69 // guess.
70 static const int kMinGoodGuessCycles = 30;
71 // How many times in a row we have to guess the wrong packet before trying
72 // again.
73 static const int kMaxBadGuessCycles = 3;
74
75 // How many times in a row a different packet has to be better than the one
76 // that we're using befor switching to it.
77 static const int kSwitchCycles = 15;
78
79 ::aos::time::Time last_good_packet_time_{0, 0};
80
81 int32_t last_good_sequence_;
82
83 const int kUnknownPhase = -11;
84 // kUnknownPhase or the sequence number (%kPacketsPerLoopCycle) to
85 // use or think about using.
86 // If not kUnknownPhase, 0 <= these < kPacketsPerLoopCycle.
87 int good_phase_, guess_phase_;
88 int guess_phase_good_, guess_phase_bad_;
89 ::aos::time::Time guess_phase_offset_{0, 0};
90 int good_phase_early_, good_phase_late_;
91 } phase_locker_;
92
93 static void StaticTransferCallback(libusb::Transfer *transfer, void *self);
94 void TransferCallback(libusb::Transfer *transfer);
95
96 // Returns true if receiving failed and we should try a Reset().
97 bool ReceiveData();
98
99 void Reset();
100
101 virtual void ProcessData() = 0;
102
103 GyroBoardData data_;
104
105 ::aos::util::WrappingCounter sequence_;
106
107 LibUSB libusb_;
108 ::std::unique_ptr<LibUSBDeviceHandle> dev_handle_;
109 ::std::unique_ptr<libusb::IsochronousTransfer> transfers_[kNumTransfers];
110 // "Temporary" variable for holding a completed transfer to communicate that
111 // information from the callback to the code that wants it.
112 libusb::Transfer *completed_transfer_;
113};
114
115} // namespace frc971
116
117#endif // FRC971_INPUT_USB_RECEIVER_H_