 }
 
 // direction helpers
-//convert to matrix
-int16_t getAdjustment(uint8_t pinH, uint8_t pinL, int8_t adj) // get control input
-{
-  switch (digitalRead(pinH) ? HIGH : (digitalRead(pinL) ? LOW : NEUTRAL))
+uint16_t helmReadMatrix()
+{
+  uint16_t matrix = 0;
+  uint8_t row = 0, col = 0;
+
+  for (row = PIN_HELM_MAT_ROW; row < PIN_HELM_MAT_ROWS; row++)
+  {
+    digitalWrite(row, LOW); // turn on the active-low row
+
+    for (col = PIN_HELM_MAT_COL; col < PIN_HELM_MAT_COLS; col++)
+    {
+      matrix <<= digitalRead(col); // shift in the next column bit
+    }
+
+    digitalWrite(row, HIGH); // turn off the active-low row
+  }
+
+  return (matrix);
+}
+
+int16_t helmGetAdjustment(uint8_t high, uint8_t low, int8_t adj) // get control input
+{
+  switch (high ? HIGH : (low ? LOW : NEUTRAL)) // high trumps low
   {
     case HIGH: // pitch up / roll right / yaw right
       if (adj++ > RAMP_MAX)

#define DELAY_START 30
#define DELAY_OP 100
#define DELAY_CTRL 100
#define DELAY_MATRIX 3 // this is in microseconds

// misc
#define OPS 16 // Action 1-10, stage, gear, light, rcs, brake, abort


void updateHelm()
{
  // get the matrix state used in the pitch/roll/yaw masks below
  uint16_t helm = helmReadMatrix();

  // update control surface inputs
  pitchAdjust = helmGetAdjustment(MASKED_PITCH_U, MASKED_PITCH_D, pitchAdjust);
  pitch = helmGetDirection(pitch, pitchAdjust, MASKED_PITCH_S);
  Serial.println(pitch);

  rollAdjust = helmGetAdjustment(MASKED_ROLL_R, MASKED_ROLL_L, rollAdjust);
  roll = helmGetDirection(roll, rollAdjust, MASKED_ROLL_S);
  Serial.println(roll);

  yawAdjust = helmGetAdjustment(MASKED_YAW_R, MASKED_YAW_L, yawAdjust);
  yaw = helmGetDirection(yaw, yawAdjust, MASKED_YAW_S);
  Serial.println(yaw);

  // update our current throttle input level
