got all of the basic cape code working
diff --git a/bbb_cape/src/bbb/packet_finder.cc b/bbb_cape/src/bbb/packet_finder.cc
index 298edc7..a6b108c 100644
--- a/bbb_cape/src/bbb/packet_finder.cc
+++ b/bbb_cape/src/bbb/packet_finder.cc
@@ -2,7 +2,6 @@
 
 #include <errno.h>
 #include <inttypes.h>
-#include <assert.h>
 
 #include <algorithm>
 
@@ -17,7 +16,7 @@
       packet_size_(packet_size),
       buf_(new AlignedChar[packet_size_]),
       unstuffed_data_(new AlignedChar[packet_size_ - 4]) {
-  assert((packet_size_ % 4) == 0);
+  CHECK((packet_size_ % 4) == 0);
 }
 
 PacketFinder::~PacketFinder() {
diff --git a/bbb_cape/src/bbb/uart_reader_main.cc b/bbb_cape/src/bbb/uart_reader_main.cc
index 5bda02c..94db8fc 100644
--- a/bbb_cape/src/bbb/uart_reader_main.cc
+++ b/bbb_cape/src/bbb/uart_reader_main.cc
@@ -7,24 +7,15 @@
 #include "aos/common/time.h"
 #include "bbb/gpios.h"
 #include "bbb/uart_reader.h"
+#include "bbb/packet_finder.h"
 
 using ::aos::time::Time;
 
-#define DO_RESET 0
-
 int main() {
   ::aos::Init();
 
-#if DO_RESET
-  // time since last good packet before we reset 
-  // the board.
-  static const Time kPacketTimeout = Time::InSeconds(1);
-
-  ::bbb::Pin reset_pin = bbb::Pin(1, 6);
-  reset_pin.MakeOutput();
-#endif
-
-  ::bbb::UartReader receiver(1500000);
+  ::bbb::UartReader reader(750000);
+  ::bbb::PacketFinder receiver(&reader, DATA_STRUCT_SEND_SIZE - 4);
   receiver.ReadPacket();
   // TODO(brians): Do this cleanly.
   int chrt_result = system(
@@ -38,17 +29,6 @@
 
   Time last_packet_time = Time::Now();
   while (true) {
-#if DO_RESET
-    if (!last_packet_time.IsWithin(Time::Now(), kPacketTimeout.ToNSec())) {
-      LOG(ERROR, "No good packets for too long. Resetting cape.\n");
-      reset_pin.Write(1);
-      ::aos::time::SleepFor(Time::InSeconds(1));
-      reset_pin.Write(0);
-      
-      last_packet_time = Time::Now();
-    }
-#endif
-
     if (!receiver.ReadPacket()) {
       LOG(WARNING, "Could not read a packet.\n");
       continue;
@@ -66,6 +46,10 @@
       LOG(DEBUG, "adc[%d]=%f (%" PRIx16 ")\n", i,
           3.3 * packet->test.analogs[i] / 0x3FF, packet->test.analogs[i]);
     }
+    LOG(DEBUG, "digitals=%x\n", packet->test.digitals);
+    LOG(DEBUG, "+=%" PRId32 "/%" PRIu8 " and -=%" PRId32 "/%" PRIu8 "\n",
+        packet->test.posedge_value, packet->test.posedge_count,
+        packet->test.negedge_value, packet->test.negedge_count);
   }
 
   ::aos::Cleanup();
diff --git a/bbb_cape/src/cape/data_struct.h b/bbb_cape/src/cape/data_struct.h
index 367c359..e4f0d78 100644
--- a/bbb_cape/src/cape/data_struct.h
+++ b/bbb_cape/src/cape/data_struct.h
@@ -44,16 +44,18 @@
   // We are 64-bit aligned at this point.
 
   union {
+    // This is for the test code that basically just sends all of the values
+    // over to make sure that everything is working.
     struct {
       int32_t encoders[8];
 
       uint16_t analogs[8];
 
       uint32_t digitals;
+
+      int32_t posedge_value, negedge_value;
+      uint8_t posedge_count, negedge_count;
     } test;
-    
-    struct {
-    } bot3;
   };
 } __attribute__((aligned(8)));
 #pragma pack(pop)
diff --git a/bbb_cape/src/cape/digital.c b/bbb_cape/src/cape/digital.c
index a15b00b..70fce99 100644
--- a/bbb_cape/src/cape/digital.c
+++ b/bbb_cape/src/cape/digital.c
@@ -33,8 +33,6 @@
 void digital_capture_12P(void) ALIAS_WEAK(digital_capture_default);
 void digital_capture_12N(void) ALIAS_WEAK(digital_capture_default);
 
-typedef void (*EXTIHandler)(uint32_t);
-
 void EXTI2_IRQHandler(void) {
   uint32_t inputs = GPIOB->IDR;
   EXTI->PR = EXTI_PR_PR2;
@@ -72,7 +70,7 @@
 }
 
 static void EXTI8_Handler(uint32_t inputs) {
-  if (inputs & (1 << 7)) {
+  if (inputs & (1 << 8)) {
     digital_capture_7N();
   } else {
     digital_capture_7P();
@@ -88,21 +86,21 @@
 }
 
 void EXTI9_5_IRQHandler(void) {
-  uint32_t inputs = GPIOC->IDR;
+  uint32_t a_inputs = GPIOA->IDR, b_inputs = GPIOB->IDR, c_inputs = GPIOC->IDR;
   uint32_t exti = __clz(EXTI->PR);
   EXTI->PR = (1 << 31) >> exti;
   switch (exti) {
     case 31 - 5:
-      EXTI5_Handler(inputs);
+      EXTI5_Handler(c_inputs);
       break;
     case 31 - 7:
-      EXTI7_Handler(inputs);
+      EXTI7_Handler(a_inputs);
       break;
     case 31 - 8:
-      EXTI8_Handler(inputs);
+      EXTI8_Handler(b_inputs);
       break;
     case 31 - 9:
-      EXTI9_Handler(inputs);
+      EXTI9_Handler(b_inputs);
       break;
   }
 }
@@ -156,27 +154,27 @@
 }
 
 void EXTI15_10_IRQHandler(void) {
-  uint32_t inputs = GPIOC->IDR;
+  uint32_t a_inputs = GPIOA->IDR, b_inputs = GPIOB->IDR, c_inputs = GPIOC->IDR;
   uint32_t exti = __clz(EXTI->PR);
   EXTI->PR = (1 << 31) >> exti;
   switch (exti) {
     case 31 - 10:
-      EXTI10_Handler(inputs);
+      EXTI10_Handler(b_inputs);
       break;
     case 31 - 11:
-      EXTI11_Handler(inputs);
+      EXTI11_Handler(a_inputs);
       break;
     case 31 - 12:
-      EXTI12_Handler(inputs);
+      EXTI12_Handler(a_inputs);
       break;
     case 31 - 13:
-      EXTI13_Handler(inputs);
+      EXTI13_Handler(c_inputs);
       break;
     case 31 - 14:
-      EXTI14_Handler(inputs);
+      EXTI14_Handler(c_inputs);
       break;
     case 31 - 15:
-      EXTI15_Handler(inputs);
+      EXTI15_Handler(c_inputs);
       break;
   }
 }
diff --git a/bbb_cape/src/cape/digital.h b/bbb_cape/src/cape/digital.h
index 4905c23..9743c3f 100644
--- a/bbb_cape/src/cape/digital.h
+++ b/bbb_cape/src/cape/digital.h
@@ -5,37 +5,80 @@
 
 void digital_init(void);
 
+// For all of the digital functions, a high voltage level on the input reads as
+// 1 (and a low to high transition is a positive edge).
+
 static inline int digital_read(int num) {
   switch (num) {
     case 0:
-      return GPIOC->IDR & (1 << 4);
+      return !(GPIOC->IDR & (1 << 4));
     case 1:
-      return GPIOC->IDR & (1 << 5);
+      return !(GPIOC->IDR & (1 << 5));
     case 2:
-      return GPIOC->IDR & (1 << 13);
+      return !(GPIOC->IDR & (1 << 13));
     case 3:
-      return GPIOC->IDR & (1 << 14);
+      return !(GPIOC->IDR & (1 << 14));
     case 4:
-      return GPIOC->IDR & (1 << 15);
+      return !(GPIOC->IDR & (1 << 15));
     case 5:
-      return GPIOB->IDR & (1 << 10);
+      return !(GPIOB->IDR & (1 << 10));
     case 6:
-      return GPIOB->IDR & (1 << 9);
+      return !(GPIOB->IDR & (1 << 9));
     case 7:
-      return GPIOB->IDR & (1 << 8);
+      return !(GPIOB->IDR & (1 << 8));
     case 8:
-      return GPIOA->IDR & (1 << 12);
+      return !(GPIOA->IDR & (1 << 12));
     case 9:
-      return GPIOA->IDR & (1 << 11);
+      return !(GPIOA->IDR & (1 << 11));
     case 10:
-      return GPIOA->IDR & (1 << 7);
+      return !(GPIOA->IDR & (1 << 7));
     case 11:
-      return GPIOB->IDR & (1 << 2);
+      return !(GPIOB->IDR & (1 << 2));
     default:
       return 0;
   }
 }
 
+// A helper function for implementing digital_capture_{disable,enable}.
+static inline enum IRQn digital_capture_getirqn(int num) {
+  switch (num) {
+    case 0:
+      return EXTI4_IRQn;
+    case 1:
+      return EXTI9_5_IRQn;
+    case 2:
+      return EXTI15_10_IRQn;
+    case 3:
+      return EXTI15_10_IRQn;
+    case 4:
+      return EXTI15_10_IRQn;
+    case 5:
+      return EXTI15_10_IRQn;
+    case 6:
+      return EXTI9_5_IRQn;
+    case 7:
+      return EXTI9_5_IRQn;
+    case 8:
+      return EXTI15_10_IRQn;
+    case 9:
+      return EXTI15_10_IRQn;
+    case 10:
+      return EXTI9_5_IRQn;
+    case 11:
+      return EXTI2_IRQn;
+    default:
+      __builtin_trap();
+  }
+}
+
+static inline void digital_capture_disable(int num) {
+  NVIC_DisableIRQ(digital_capture_getirqn(num));
+}
+
+static inline void digital_capture_enable(int num) {
+  NVIC_EnableIRQ(digital_capture_getirqn(num));
+}
+
 // These are the functions for handling edges on the inputs. They have
 // default (weak symbol) implementations that do nothing.
 //void digital_capture_0P(void);
diff --git a/bbb_cape/src/cape/fill_packet.c b/bbb_cape/src/cape/fill_packet.c
index d2dc01e..012b7e3 100644
--- a/bbb_cape/src/cape/fill_packet.c
+++ b/bbb_cape/src/cape/fill_packet.c
@@ -55,7 +55,7 @@
     struct DataStruct packet;
     uint8_t padding[DATA_STRUCT_SEND_SIZE - sizeof(struct DataStruct) - 12];
     uint32_t checksum;
-  } data __attribute__((aligned(4)));
+  } __attribute__((packed)) data __attribute__((aligned(4)));
   STATIC_ASSERT(sizeof(data) == DATA_STRUCT_SEND_SIZE - 8,
                 The_size_of_the_data_is_wrong);
   struct DataStruct *packet = &data.packet;
@@ -89,6 +89,6 @@
   led_set(LED_ERR, 0);
   gyro_init();
 
-  uart_common_configure(1500000);
+  uart_common_configure(750000);
   uart_dma_configure(DATA_STRUCT_SEND_SIZE, buffer1, buffer2);
 }
diff --git a/bbb_cape/src/cape/robot_test.c b/bbb_cape/src/cape/robot_test.c
index 85074c3..f329790 100644
--- a/bbb_cape/src/cape/robot_test.c
+++ b/bbb_cape/src/cape/robot_test.c
@@ -4,6 +4,25 @@
 #include "cape/analog.h"
 #include "cape/digital.h"
 
+#define CAPTURE_NUM 11
+
+#define CAPTURE(num, np) digital_capture_ ## num ## np
+#define CAPTURE2(num, np) CAPTURE(num, np)
+#define CAPTURE_P CAPTURE2(CAPTURE_NUM, P)
+#define CAPTURE_N CAPTURE2(CAPTURE_NUM, N)
+
+static int32_t posedge_value, negedge_value;
+static uint8_t posedge_count = 0, negedge_count = 0;
+
+void CAPTURE_P(void) {
+  ++posedge_count;
+  posedge_value = encoder_read(1);
+}
+void CAPTURE_N(void) {
+  ++negedge_count;
+  negedge_value = encoder_read(1);
+}
+
 void robot_fill_packet(struct DataStruct *packet) {
   packet->test.encoders[0] = encoder_read(0);
   packet->test.encoders[1] = encoder_read(1);
@@ -20,8 +39,13 @@
 
   packet->test.digitals = 0;
   for (int i = 0; i < 12; ++i) {
-    SET_BITS(packet->test.digitals, 1, !!digital_read(i), i);
+    SET_BITS(packet->test.digitals, 1, digital_read(i), i);
   }
 
-  // TODO(brians): digitals
+  digital_capture_disable(CAPTURE_NUM);
+  packet->test.posedge_count = posedge_count;
+  packet->test.posedge_value = posedge_value;
+  packet->test.negedge_count = negedge_count;
+  packet->test.negedge_value = negedge_value;
+  digital_capture_enable(CAPTURE_NUM);
 }