 
 static bool hold = false;
 static bool finished = false;
+
+static FatFile tasFile;
+
+//static unsigned int progressPos = 0;
+static unsigned long numFrames = 0, curFrame = 0;
+static int edgesRead = 0;
+static int incompleteCommand = 0;
+
+static SdFatSdioEX sd;
+
+template<class T> void lockedPrintln(const T& input)
+{
+  noInterrupts();
+  Serial.println(input);
+  interrupts();
+}
+
+template<class A, class B> void lockedPrintln(const A& a, const B& b)
+{
+  noInterrupts();
+  Serial.print(a);
+  Serial.println(b);
+  interrupts();
+}
+
+static void startTimer()
+{
+  ARM_DWT_CYCCNT = 0;
+}
+
+static long readTimer()
+{
+  return ARM_DWT_CYCCNT;
+}
 
 static size_t getNextRegion(size_t& size) {
   size_t currentPos = bufferPos;

    Serial.println("AP:NAK");
}

bool skippingInput = false;
static String inputString;

static void handleCommand(const String& cmd)
{
  if (cmd.startsWith("M:")) {
    openTAS(cmd.substring(2));
  } else if (cmd.startsWith("O:")) {
    //dummy
  } else if (cmd.startsWith("L:")) {
    emitList(cmd.substring(2));
  } else if (cmd.startsWith("MK:")) {
    lockedPrintln("MK:", sd.mkdir(cmd.substring(3).c_str()));
  } else if (cmd.startsWith("CR:")) {
    if (writeFile.isOpen()) {
      writeFile.close();
    }
    if (writeFile.open(&sd, cmd.substring(3).c_str(), O_WRITE | O_CREAT | O_TRUNC)) {
      lockedPrintln("CR:OK");
    } else {
      lockedPrintln("CR:NAK");
    }
  } else if (cmd.startsWith("AP:")) {
    appendData(hextobin(cmd.substring(3)));
  } else if (cmd.startsWith("IN:")) {
    size_t len = appendInputs(hextobin(cmd.substring(3)));
    lockedPrintln("IN:", len);
  } else if (cmd.startsWith("HL:")) {
    hold = cmd[3] == '1';
  } else if (cmd.startsWith("CL:")) {
    writeFile.close();
    lockedPrintln("CL:OK");
  } else if (cmd.startsWith("PM:")) {
    setPinMode(cmd.substring(3));
  } else if (cmd.startsWith("DW:")) {
    writePin(cmd.substring(3));
  } else {
    lockedPrintln("E:Unknown CMD:", cmd.c_str());
  }
}

#define MAX_CMD_LEN 4096
#define MAX_LOOP_LEN 10240

static void inputLoop()
{
  int newChar;
  int charsRead = 0;
  while ((newChar = Serial.read()) != -1 && (charsRead++ <= MAX_LOOP_LEN)) {
    if (newChar == '\n') {
      if (skippingInput)
        Serial.println("E:Skipped too-long line");
      else
        handleCommand(inputString);
      inputString = "";
      skippingInput = false;
    } else if (inputString.length() > MAX_CMD_LEN) {
      skippingInput = true;
    } else {
      inputString += (char)newChar;
    }
  }
}

static void waitForIdle(int us)
{
  LED_HIGH;

    tasFile.close();
  }
  dir.close();
}

void logFrame(const unsigned char *dat, size_t count, size_t num)
