Send a CameraCommand from the roboRIO too

This will be triggered by buttons soon.

Change-Id: I99d5113e3be4cba57549e33263f958ca4d232705
diff --git a/y2019/jevois/spi.cc b/y2019/jevois/spi.cc
index 2d3e2f2..b6e6632 100644
--- a/y2019/jevois/spi.cc
+++ b/y2019/jevois/spi.cc
@@ -252,6 +252,8 @@
     memcpy(remaining_space.data(), &realtime_now, sizeof(realtime_now));
     remaining_space = remaining_space.subspan(sizeof(realtime_now));
   }
+  memcpy(remaining_space.data(), &message.camera_command, 1);
+  remaining_space = remaining_space.subspan(1);
   {
     uint16_t crc = jevois_crc_init();
     crc = jevois_crc_update(crc, transfer.data(),
@@ -281,6 +283,8 @@
         aos::realtime_clock::duration(realtime_now));
     remaining_input = remaining_input.subspan(sizeof(realtime_now));
   }
+  memcpy(&message.camera_command, remaining_input.data(), 1);
+  remaining_input = remaining_input.subspan(1);
   {
     uint16_t calculated_crc = jevois_crc_init();
     calculated_crc =
diff --git a/y2019/jevois/spi_test.cc b/y2019/jevois/spi_test.cc
index 8f08fcb..32551db 100644
--- a/y2019/jevois/spi_test.cc
+++ b/y2019/jevois/spi_test.cc
@@ -107,7 +107,28 @@
 
 // Tests packing and then unpacking an empty message.
 TEST(SpiToTeensyPackTest, Empty) {
+  RoborioToTeensy input_message{};
+  const SpiTransfer transfer = SpiPackToTeensy(input_message);
+  const auto output_message = SpiUnpackToTeensy(transfer);
+  ASSERT_TRUE(output_message);
+  EXPECT_EQ(input_message, output_message.value());
+}
+
+// Tests packing and then unpacking a message with all the fields set.
+TEST(SpiToTeensyPackTest, Full) {
   RoborioToTeensy input_message;
+  input_message.beacon_brightness[0] = 9;
+  input_message.beacon_brightness[1] = 7;
+  input_message.beacon_brightness[2] = 1;
+  input_message.light_rings[0] = 1;
+  input_message.light_rings[1] = 0;
+  input_message.light_rings[2] = 0;
+  input_message.light_rings[3] = 1;
+  input_message.light_rings[4] = 0;
+  input_message.realtime_now =
+      aos::realtime_clock::epoch() + std::chrono::seconds(971254);
+  input_message.camera_command = CameraCommand::kUsb;
+
   const SpiTransfer transfer = SpiPackToTeensy(input_message);
   const auto output_message = SpiUnpackToTeensy(transfer);
   ASSERT_TRUE(output_message);
diff --git a/y2019/jevois/structures.h b/y2019/jevois/structures.h
index 28da405..aa4fc07 100644
--- a/y2019/jevois/structures.h
+++ b/y2019/jevois/structures.h
@@ -106,17 +106,17 @@
   camera_duration age;
 };
 
+enum class CameraCommand : char {
+  // Stay in normal mode.
+  kNormal,
+  // Go to camera passthrough mode.
+  kCameraPassthrough,
+  // Go to being a useful USB device.
+  kUsb,
+};
+
 // This is all the information sent from the Teensy to each camera.
 struct CameraCalibration {
-  enum class CameraCommand : char {
-    // Stay in normal mode.
-    kNormal,
-    // Go to camera passthrough mode.
-    kCameraPassthrough,
-    // Go to being a useful USB device.
-    kUsb,
-  };
-
   bool operator==(const CameraCalibration &other) const {
     if (other.calibration != calibration) {
       return false;
@@ -194,6 +194,9 @@
 
   // The current time.
   aos::realtime_clock::time_point realtime_now;
+
+  // A command to send to all the cameras.
+  CameraCommand camera_command;
 };
 
 }  // namespace jevois
diff --git a/y2019/jevois/teensy.cc b/y2019/jevois/teensy.cc
index 44b2505..3df3758 100644
--- a/y2019/jevois/teensy.cc
+++ b/y2019/jevois/teensy.cc
@@ -639,7 +639,7 @@
         CameraCalibration calibration{};
         calibration.teensy_now = aos::monotonic_clock::now();
         calibration.realtime_now = aos::realtime_clock::min_time;
-        calibration.camera_command = CameraCalibration::CameraCommand::kNormal;
+        calibration.camera_command = CameraCommand::kNormal;
         // TODO(Brian): Actually fill out the calibration field.
         transmit_buffers[0].MaybeWritePacket(calibration);
         transmit_buffers[1].MaybeWritePacket(calibration);
diff --git a/y2019/jevois/uart_test.cc b/y2019/jevois/uart_test.cc
index 1e90d84..d669688 100644
--- a/y2019/jevois/uart_test.cc
+++ b/y2019/jevois/uart_test.cc
@@ -66,8 +66,7 @@
   input_message.teensy_now =
       aos::monotonic_clock::time_point(std::chrono::seconds(1678));
   input_message.realtime_now = aos::realtime_clock::min_time;
-  input_message.camera_command =
-      CameraCalibration::CameraCommand::kCameraPassthrough;
+  input_message.camera_command = CameraCommand::kCameraPassthrough;
   const UartToCameraBuffer buffer = UartPackToCamera(input_message);
   const auto output_message = UartUnpackToCamera(buffer);
   ASSERT_TRUE(output_message);
diff --git a/y2019/vision/debug_serial.cc b/y2019/vision/debug_serial.cc
index a095b14..857f20f 100644
--- a/y2019/vision/debug_serial.cc
+++ b/y2019/vision/debug_serial.cc
@@ -68,10 +68,9 @@
       if (n >= 1) {
         CameraCalibration calibration{};
         if (data[0] == 'p') {
-          calibration.camera_command =
-              CameraCalibration::CameraCommand::kCameraPassthrough;
+          calibration.camera_command = CameraCommand::kCameraPassthrough;
         } else {
-          calibration.camera_command = CameraCalibration::CameraCommand::kUsb;
+          calibration.camera_command = CameraCommand::kUsb;
         }
         if (write(itsDev, "\0", 1) == 1) {
           const auto out_data = frc971::jevois::UartPackToCamera(calibration);
diff --git a/y2019/vision/target_sender.cc b/y2019/vision/target_sender.cc
index be56e91..d6c5dc2 100644
--- a/y2019/vision/target_sender.cc
+++ b/y2019/vision/target_sender.cc
@@ -275,7 +275,7 @@
   (void)argc;
   (void)argv;
   using namespace y2019::vision;
-  using frc971::jevois::CameraCalibration;
+  using frc971::jevois::CameraCommand;
   // gflags::ParseCommandLineFlags(&argc, &argv, false);
   ::aos::logging::Init();
   ::aos::logging::AddImplementation(
@@ -382,11 +382,11 @@
           if (calibration_question) {
             const auto &calibration = *calibration_question;
             switch (calibration.camera_command) {
-              case CameraCalibration::CameraCommand::kNormal:
+              case CameraCommand::kNormal:
                 break;
-              case CameraCalibration::CameraCommand::kUsb:
+              case CameraCommand::kUsb:
                 return 0;
-              case CameraCalibration::CameraCommand::kCameraPassthrough:
+              case CameraCommand::kCameraPassthrough:
                 return system("touch /tmp/do_not_export_sd_card");
             }
           } else {
diff --git a/y2019/wpilib_interface.cc b/y2019/wpilib_interface.cc
index 29377c8..be6ee33 100644
--- a/y2019/wpilib_interface.cc
+++ b/y2019/wpilib_interface.cc
@@ -283,6 +283,7 @@
     using namespace frc971::jevois;
     RoborioToTeensy to_teensy{};
     to_teensy.realtime_now = aos::realtime_clock::now();
+    to_teensy.camera_command = CameraCommand::kNormal;
 
     std::array<char, spi_transfer_size() + 1> to_send{};
     {