started writing actual cape code
diff --git a/bbb_cape/src/cape/data_struct.h b/bbb_cape/src/cape/data_struct.h
new file mode 100644
index 0000000..051095e
--- /dev/null
+++ b/bbb_cape/src/cape/data_struct.h
@@ -0,0 +1,107 @@
+// This isn't really a header file. It's designed to be #included directly into
+// other code (possibly in a namespace or whatever), so it doesn't have include
+// guards.
+// This means that it can not #include anything else because it (sometimes) gets
+// #included inside a namespace.
+// <stdint.h> must be #included by the containing file.
+// In the cape code, fill_packet.h #includes this file.
+// In the fitpc code, frc971/input/gyro_board_data.h #includes this file.
+
+#pragma pack(push, 1)
+// Be careful with declaration order in here. ARM doesn't like unaligned
+// accesses!
+struct DATA_STRUCT_NAME {
+  int64_t gyro_angle;
+
+  union {
+    struct {
+      // In us since the cape last reset.
+      uint64_t timestamp;
+
+      struct {
+        // If the current gyro_angle has been not updated because of a bad
+        // reading from the sensor.
+        uint8_t old_gyro_reading : 1;
+        // If we're not going to get any more good gyro_angles.
+        uint8_t bad_gyro : 1;
+      };
+    };
+    struct {
+      uint64_t header1, header2;
+    };
+  };
+
+  // We are 64-bit aligned at this point.
+
+  union {
+    struct {
+      int32_t left_drive;
+      int32_t right_drive;
+      int32_t shooter_angle;
+      int32_t shooter;
+      int32_t indexer;
+      int32_t wrist;
+
+      int32_t capture_top_rise;
+      int32_t capture_top_fall;
+      int32_t capture_bottom_fall_delay;
+      int32_t capture_wrist_rise;
+      int32_t capture_shooter_angle_rise;
+
+      uint16_t battery_voltage;
+      uint16_t left_drive_hall;
+      uint16_t right_drive_hall;
+
+      int8_t top_rise_count;
+
+      int8_t top_fall_count;
+
+      int8_t bottom_rise_count;
+
+      int8_t bottom_fall_delay_count;
+      int8_t bottom_fall_count;
+
+      int8_t wrist_rise_count;
+
+      int8_t shooter_angle_rise_count;
+
+      struct {
+        uint8_t wrist_hall_effect : 1;
+        uint8_t angle_adjust_bottom_hall_effect : 1;
+        uint8_t top_disc : 1;
+        uint8_t bottom_disc : 1;
+        uint8_t loader_top : 1;
+        uint8_t loader_bottom : 1;
+      };
+    } main;
+    
+    struct {
+      union {
+        struct {
+        };
+        uint16_t booleans;
+      };
+    } bot3;
+  };
+} __attribute__((aligned(8)));
+#pragma pack(pop)
+
+// The number of bytes that we actually send (so it stays consistent) (including
+// the byte-stuffing overhead and the CRC on the end).
+#define DATA_STRUCT_SEND_SIZE 200
+
+#ifdef __cplusplus
+#define STATIC_ASSERT(cond, msg) static_assert(cond, #msg)
+#endif
+// 4 bytes of 0s at the beginning, 4 bytes of byte-stuffing overhead, and 4
+// bytes of CRC on the end.
+STATIC_ASSERT(
+    (sizeof(struct DATA_STRUCT_NAME) + 8 + 4) <= DATA_STRUCT_SEND_SIZE,
+    The_sensor_data_structure_is_too_big);
+// The byte-stuffing and CRC both work in chunks of 4 bytes, so it has to be a
+// multiple of that in size.
+STATIC_ASSERT((sizeof(struct DATA_STRUCT_NAME) % 4) == 0,
+              The_sensor_data_structure_is_not_a_multiple_of_4_bytes);
+#ifdef __cplusplus
+#undef STATIC_ASSERT
+#endif