added a checksum of the data structure to the gyro board data
diff --git a/frc971/input/input.gyp b/frc971/input/input.gyp
index 23dfda6..5558618 100644
--- a/frc971/input/input.gyp
+++ b/frc971/input/input.gyp
@@ -56,6 +56,9 @@
         '<(DEPTH)/gyro_board/src/libusb-driver/libusb-driver.gyp:libusb_wrap',
         '<(AOS)/common/common.gyp:time',
       ],
+      'defines': [
+        'GYRO_BOARD_DATA_CHECKSUM=<!(<(DEPTH)/gyro_board/src/usb/data_struct_checksum.sh)',
+      ],
     },
   ],
 }
diff --git a/frc971/input/usb_receiver.cc b/frc971/input/usb_receiver.cc
index b70ff61..81b960e 100644
--- a/frc971/input/usb_receiver.cc
+++ b/frc971/input/usb_receiver.cc
@@ -18,23 +18,29 @@
   if (ReceiveData()) {
     Reset();
   } else {
-    if (phase_locker_.IsCurrentPacketGood(transfer_received_time_, frame_number_)) {
-      static const int kCountsPerSecond = 100000;
-      const ::aos::time::Time timestamp =
-          ::aos::time::Time(data()->timestamp / kCountsPerSecond,
-                            (data()->timestamp * ::aos::time::Time::kNSecInSec /
-                             kCountsPerSecond) %
-                                ::aos::time::Time::kNSecInSec);
+    static const int kCountsPerSecond = 100000;
+    const ::aos::time::Time timestamp =
+        ::aos::time::Time(data()->timestamp / kCountsPerSecond,
+                          (data()->timestamp * ::aos::time::Time::kNSecInSec /
+                           kCountsPerSecond) %
+                          ::aos::time::Time::kNSecInSec);
 
-      if (data()->robot_id != expected_robot_id_) {
-        LOG(ERROR, "gyro board sent data for robot id %hhd instead of %hhd!"
-            " dip switches are %hhx\n",
-            data()->robot_id, expected_robot_id_, data()->dip_switches);
-        return;
-      } else {
-        LOG(DEBUG, "processing dips %hhx frame %" PRId32 " at %f\n",
-            data()->dip_switches, data()->frame_number, timestamp.ToSeconds());
-      }
+    if (data()->robot_id != expected_robot_id_) {
+      LOG(ERROR, "gyro board sent data for robot id %hhd instead of %hhd!"
+          " dip switches are %hhx\n",
+          data()->robot_id, expected_robot_id_, data()->dip_switches);
+      return;
+    }
+    if (data()->checksum != GYRO_BOARD_DATA_CHECKSUM) {
+      LOG(ERROR,
+          "gyro board sent checksum %" PRIu16 " instead of %" PRIu16 "!\n",
+          data()->checksum, GYRO_BOARD_DATA_CHECKSUM);
+      return;
+    }
+
+    if (phase_locker_.IsCurrentPacketGood(transfer_received_time_, frame_number_)) {
+      LOG(DEBUG, "processing dips %hhx frame %" PRId32 " at %f\n",
+          data()->dip_switches, data()->frame_number, timestamp.ToSeconds());
 
       ProcessData(timestamp);
     }
diff --git a/gyro_board/src/usb/Makefile b/gyro_board/src/usb/Makefile
index da8a4c5..e2f81f4 100644
--- a/gyro_board/src/usb/Makefile
+++ b/gyro_board/src/usb/Makefile
@@ -49,13 +49,15 @@
 	gyro.c \
 	LPCUSB/usbstdreq.c
 
+DATA_STRUCT_CHECKSUM=$(shell ./data_struct_checksum.sh)
+
 all: $(NAME).hex
 
 $(NAME).elf: Makefile $(SOURCES:.c=.o) $(LDSCRIPT)
 	$(CC) $(CFLAGS) -nostartfiles -nostdlib -T $(LDSCRIPT) -o $@ -L$(TOOLS_PREFIX)/lib/gcc/arm-eabi/4.5.1/ $(SOURCES:.c=.o) -Wa,-Map -Wa,main.map -lgcc
 
-%.o: %.c Makefile
-	$(CC) $(CFLAGS) -nostartfiles -nostdlib -c -o $@ $< -Wall -std=gnu99
+%.o: %.c Makefile data_struct_checksum.sh
+	$(CC) $(CFLAGS) -nostartfiles -nostdlib -c -o $@ $< -Wall -std=gnu99 -DDATA_STRUCT_CHECKSUM=$(DATA_STRUCT_CHECKSUM)
 
 run: deploy
 	$(FLASHER) -termonly -control $(NAME).hex $(PORT) $(SPEED) $(OSC)
diff --git a/gyro_board/src/usb/data_struct.h b/gyro_board/src/usb/data_struct.h
index 718d19c..50eb7a9 100644
--- a/gyro_board/src/usb/data_struct.h
+++ b/gyro_board/src/usb/data_struct.h
@@ -26,6 +26,11 @@
       // dealing with it reset.
       int32_t frame_number;
 
+      // Checksum of this file calculated with sum(1).
+      // The gyro board sets this and then the fitpc checks it to make sure that
+      // they're both using the same version of this file.
+      uint16_t checksum;
+
       // Which robot (+version) the gyro board is sending out data for.
       // We should keep this in the same place for all gyro board software
       // versions so that the fitpc can detect when it's reading from a gyro
@@ -62,7 +67,9 @@
         uint8_t unknown_frame : 1;
       };
     };
-    uint64_t header;
+    struct {
+      uint64_t header0, header1;
+    };
   };
 
   // We are 64-bit aligned at this point.
diff --git a/gyro_board/src/usb/data_struct_checksum.sh b/gyro_board/src/usb/data_struct_checksum.sh
new file mode 100755
index 0000000..147a365
--- /dev/null
+++ b/gyro_board/src/usb/data_struct_checksum.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+
+sum $(dirname $0)/data_struct.h | sed 's/^\([0-9]*\) .*$/\1/'
diff --git a/gyro_board/src/usb/encoder.c b/gyro_board/src/usb/encoder.c
index 77344fb..ef5af7f 100644
--- a/gyro_board/src/usb/encoder.c
+++ b/gyro_board/src/usb/encoder.c
@@ -517,6 +517,8 @@
   packet->timestamp = ((uint64_t)sensor_timing_wraps << 32) | TIM1->TC;
   NVIC_EnableIRQ(TIMER1_IRQn);
 
+  packet->checksum = DATA_STRUCT_CHECKSUM;
+
   packet->dip_switch0 = dip_switch(0);
   packet->dip_switch1 = dip_switch(1);
   packet->dip_switch2 = dip_switch(2);