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