#include <Arduino.h>
#include <SPI.h>
#define DATA_LEN 16
#define DEFAULT_FREQ_MS 2UL
volatile uint8_t spiData[DATA_LEN]; volatile uint8_t spiIndex = 0;
volatile uint32_t spiIntervalMs = DEFAULT_FREQ_MS; volatile unsigned long spiCount = 0;
volatile unsigned long lastSpiMicros = 0;
const uint8_t CMD_BUF_SIZE = 32; char cmdBuf[CMD_BUF_SIZE];
uint8_t cmdPos = 0; const int ledPin = 13;
unsigned long lastBlink = 0; bool ledState = LOW;
uint16_t msToOCR1A(uint32_t ms) {
uint32_t ticks = (ms * 1000UL) / 4UL;
if (ticks < 1) ticks = 1;
if (ticks > 65535UL) ticks = 65535UL;
return (uint16_t)(ticks - 1);
}
void setSpiIntervalMs(uint32_t ms) {
if (ms < 1) ms = 1; cli();
spiIntervalMs = ms;
OCR1A = msToOCR1A(ms); sei();
}
void setupTimer1ForSpi(uint32_t ms) {
noInterrupts();
TCCR1A = 0; TCCR1B = 0;
TCNT1 = 0; OCR1A = msToOCR1A(ms);
TCCR1B |= (1 << WGM12); TCCR1B |= (1 << CS11) | (1 << CS10);
TIMSK1 |= (1 << OCIE1A); interrupts();
}
ISR(TIMER1_COMPA_vect) {
uint8_t b = spiData[spiIndex]; SPDR = b; spiIndex++;
if (spiIndex >= DATA_LEN) spiIndex = 0; spiCount++;
lastSpiMicros = micros();
}
void parseCommand(const char *cmd) {
while (*cmd == ' ' || *cmd == '\t') cmd++;
if (strncmp(cmd, "SET FREQ", 8) == 0) {
cmd += 8;
while (*cmd == ' ' || *cmd == '\t') cmd++;
int val = atoi(cmd);
if (val == 2 || val == 5 || val == 10) {
spiCount = 0; setSpiIntervalMs(val);
Serial.print(F("OK: FREQ SET TO ")); Serial.print(val);
Serial.println(F(" ms"));
return;
}
}
Serial.println(F("ERR: UNKNOWN CMD"));
}
void setup() {
Serial.begin(115200);
for (uint8_t i = 0; i < DATA_LEN; i++) spiData[i] = i; SPI.begin();
pinMode(SS, OUTPUT); digitalWrite(SS, HIGH);
setupTimer1ForSpi(spiIntervalMs); pinMode(ledPin, OUTPUT);
Serial.println(F("READY. Commands: SET FREQ 2 / 5 / 10"));
}
void loop() {
unsigned long m = millis();
if (m - lastBlink >= 250) {
lastBlink = m; ledState = !ledState;
digitalWrite(ledPin, ledState);
}
while (Serial.available()) {
char c = Serial.read();
if (c == '\r') continue;
if (c == '\n' || cmdPos >= CMD_BUF_SIZE - 1) {
cmdBuf[cmdPos] = '\0';
if (cmdPos > 0) parseCommand(cmdBuf);
cmdPos = 0;
} else {
cmdBuf[cmdPos++] = c;
}
}
static unsigned long lastStatus = 0;
if (m - lastStatus >= 1000) {
lastStatus = m; noInterrupts();
uint32_t curInterval = spiIntervalMs; unsigned long count = spiCount;
unsigned long lastMic = lastSpiMicros; interrupts();
Serial.print(F("STATUS: interval="));
Serial.print(curInterval);
Serial.print(F(" ms, Count="));
Serial.print(count);
Serial.print(F(", lastSpiMicros="));
Serial.println(lastMic);
}
}