#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();
}