Newer
Older
SerialTrigger / Trigger_arduino / Trigger_arduino.ino
#include <Arduino.h>
#include <string.h>

constexpr uint8_t TRIGGER_PIN = 9;
constexpr uint32_t TRIGGER_WIDTH_US = 100000UL;

constexpr size_t RX_BUFFER_SIZE = 32;
char rxBuffer[RX_BUFFER_SIZE];
size_t rxLength = 0;
bool rxOverflow = false;

bool triggerActive = false;
uint32_t triggerStartUs = 0;

/*
 * 使用中のPro Micro互換基板では、
 * LED0 = 点灯、LED1 = 消灯として動作する。
 */
void triggerLedOn()
{
  TXLED0;
}

void triggerLedOff()
{
  TXLED1;
}

void allCommunicationLedsOff()
{
  RXLED1;
  TXLED1;
}

void startTrigger()
{
  if (triggerActive)
  {
    Serial.println(F("BUSY"));
    return;
  }

  // TTL信号と赤色LEDを同時にON
  digitalWrite(TRIGGER_PIN, HIGH);
  triggerLedOn();

  triggerStartUs = micros();
  triggerActive = true;

  Serial.println(F("ACK"));
}

void updateTrigger()
{
  if (!triggerActive)
  {
    return;
  }

  const uint32_t elapsedUs = micros() - triggerStartUs;

  if (elapsedUs >= TRIGGER_WIDTH_US)
  {
    // TTL信号と赤色LEDを同時にOFF
    digitalWrite(TRIGGER_PIN, LOW);
    triggerLedOff();

    triggerActive = false;

    Serial.println(F("DONE"));
  }
}

void processCommand(const char* command)
{
  if (strcmp(command, "TRIG") == 0)
  {
    startTrigger();
  }
  else if (strcmp(command, "PING") == 0)
  {
    Serial.println(F("PONG"));
  }
  else
  {
    Serial.print(F("ERR UNKNOWN_COMMAND: "));
    Serial.println(command);
  }
}

void receiveCommands()
{
  while (Serial.available() > 0)
  {
    const char received = static_cast<char>(Serial.read());

    if (received == '\n' || received == '\r')
    {
      if (rxOverflow)
      {
        Serial.println(F("ERR LINE_TOO_LONG"));
        rxLength = 0;
        rxOverflow = false;
        continue;
      }

      if (rxLength == 0)
      {
        continue;
      }

      rxBuffer[rxLength] = '\0';
      processCommand(rxBuffer);
      rxLength = 0;
      continue;
    }

    if (rxOverflow)
    {
      continue;
    }

    if (rxLength < RX_BUFFER_SIZE - 1)
    {
      rxBuffer[rxLength++] = received;
    }
    else
    {
      rxOverflow = true;
    }
  }
}

void setup()
{
  // TTL出力を初期状態LOWにする
  digitalWrite(TRIGGER_PIN, LOW);
  pinMode(TRIGGER_PIN, OUTPUT);

  // RX/TX LEDを出力として初期化
  TX_RX_LED_INIT;

  // 待機中は赤色LEDを両方消灯
  allCommunicationLedsOff();

  Serial.begin(115200);
}

void loop()
{
  updateTrigger();
  receiveCommands();
  updateTrigger();
}