used the async interface for reading sensor packets
diff --git a/frc971/input/gyro_sensor_receiver.cc b/frc971/input/gyro_sensor_receiver.cc
index 8b5604a..3d95758 100644
--- a/frc971/input/gyro_sensor_receiver.cc
+++ b/frc971/input/gyro_sensor_receiver.cc
@@ -184,8 +184,8 @@
::aos::sensors::SensorUnpackerInterface<GyroBoardData> *unpacker)
: ::aos::sensors::SensorReceiver<GyroBoardData>(unpacker),
start_time_(0, 0) {
- static_assert(sizeof(GyroBoardData) <= sizeof(data_),
- "the buffer is too small");
+ static_assert(sizeof(GyroBoardData) <= kDataLength,
+ "the buffer will be too small");
}
private:
@@ -199,29 +199,27 @@
// product ID
static const int32_t kPid = 0xd243;
+ // How big of a buffer to give the function.
+ static const size_t kDataLength = 64;
+
virtual void DoReceiveData() {
// Loop and then return once we get a good one.
while (true) {
- int read_bytes;
- ::aos::time::SleepFor(::aos::time::Time::InSeconds(0.0005));
- int r = dev_handle_->interrupt_transfer(
- kEndpoint, data_, sizeof(data_), &read_bytes, kReadTimeout);
-
- if (r != 0) {
- if (r == LIBUSB_ERROR_TIMEOUT) {
- LOG(ERROR, "read timed out\n");
- continue;
- }
- LOG(FATAL, "libusb gave error %d\n", r);
+ completed_transfer_ = NULL;
+ while (completed_transfer_ == NULL) {
+ libusb_.HandleEvents();
}
+ LOG(DEBUG, "processing transfer %p\n", completed_transfer_);
- if (read_bytes < static_cast<ssize_t>(sizeof(GyroBoardData))) {
+ if (completed_transfer_->read_bytes() <
+ static_cast<ssize_t>(sizeof(GyroBoardData))) {
LOG(ERROR, "read %d bytes instead of at least %zd\n",
- read_bytes, sizeof(GyroBoardData));
+ completed_transfer_->read_bytes(), sizeof(GyroBoardData));
continue;
}
- memcpy(&data()->values, data_, sizeof(GyroBoardData));
+ memcpy(&data()->values, completed_transfer_->data(),
+ sizeof(GyroBoardData));
if (data()->count == 0) {
start_time_ = ::aos::time::Time::Now();
data()->count = 1;
@@ -235,27 +233,57 @@
}
virtual void Reset() {
+ transfer1_.reset();
+ transfer2_.reset();
dev_handle_ = ::std::unique_ptr<LibUSBDeviceHandle>(
libusb_.FindDeviceWithVIDPID(kVid, kPid));
if (!dev_handle_) {
LOG(FATAL, "couldn't find device\n");
}
+ transfer1_ = ::std::unique_ptr<libusb::Transfer>(
+ new libusb::Transfer(kDataLength, StaticTransferCallback, this));
+ transfer2_ = ::std::unique_ptr<libusb::Transfer>(
+ new libusb::Transfer(kDataLength, StaticTransferCallback, this));
+ transfer1_->FillInterrupt(dev_handle_.get(), kEndpoint, kReadTimeout);
+ transfer2_->FillInterrupt(dev_handle_.get(), kEndpoint, kReadTimeout);
+ transfer1_->Submit();
+ transfer2_->Submit();
+
data()->count = 0;
}
+ static void StaticTransferCallback(libusb::Transfer *transfer, void *self) {
+ static_cast<GyroSensorReceiver *>(self)->TransferCallback(transfer);
+ }
+ void TransferCallback(libusb::Transfer *transfer) {
+ if (transfer->status() == LIBUSB_TRANSFER_COMPLETED) {
+ LOG(DEBUG, "transfer %p completed\n", transfer);
+ completed_transfer_ = transfer;
+ } else if (transfer->status() == LIBUSB_TRANSFER_TIMED_OUT) {
+ LOG(WARNING, "transfer %p timed out\n", transfer);
+ } else if (transfer->status() == LIBUSB_TRANSFER_CANCELLED) {
+ LOG(DEBUG, "transfer %p cancelled\n", transfer);
+ } else {
+ LOG(FATAL, "transfer %p has status %d\n", transfer, transfer->status());
+ }
+ transfer->Submit();
+ }
+
virtual void Synchronized(::aos::time::Time start_time) {
- LOG(INFO, "offset %f\n", (::aos::time::Time::Now() - start_time).ToSeconds());
+ // Subtract off how many packets it read while synchronizing from the time.
start_time_ = start_time -
::aos::sensors::kSensorSendFrequency * data()->count;
}
::std::unique_ptr<LibUSBDeviceHandle> dev_handle_;
+ ::std::unique_ptr<libusb::Transfer> transfer1_, transfer2_;
+ // Temporary variable for holding a completed transfer to communicate that
+ // information from the callback to the code that wants it.
+ libusb::Transfer *completed_transfer_;
::aos::time::Time start_time_;
LibUSB libusb_;
-
- uint8_t data_[64];
};
} // namespace frc971