#include <SPI.h>
// --- Konfigurasi Pin ---
const int latchPin = 8; // Pin STCP pada 74HC595 (SS)
// Pin 11 (MOSI) dan 13 (SCK) otomatis dikendalikan oleh library SPI
// --- Variabel Global ---
unsigned long previousMillis = 0;
unsigned long interval = 100; // Kecepatan awal (ms)
byte ledData = 0b00000001; // Pola awal (1 LED nyala di ujung)
bool arahKanan = true; // Penanda arah gerak lampu
// Variabel Serial
String inputString = "";
bool stringComplete = false;
void setup() {
Serial.begin(9600);
// Setup SPI
SPI.begin();
pinMode(latchPin, OUTPUT);
Serial.println("System Ready!");
Serial.println("Ketik: SET FREQ 2 / 5 / 10 (Untuk ubah kecepatan)");
}
void loop() {
// 1. TANGANI KOMUNIKASI SERIAL (UART - Channel B)
checkSerial();
// 2. TANGANI SPI DISPLAY (Channel A)
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
updateShiftRegister(); // Kirim data via SPI
geserBit(); // Hitung pola bit berikutnya
// Debugging (Opsional, matikan jika ingin serial bersih)
// Serial.print("Interval: "); Serial.println(interval);
}
}
// --- Fungsi Logika Pengiriman SPI ---
void updateShiftRegister() {
digitalWrite(latchPin, LOW); // [Latch Turun] Buka gerbang penyimpanan
SPI.transfer(ledData); // [SPI Kirim] Kirim 8 bit data (sangat cepat!)
digitalWrite(latchPin, HIGH); // [Latch Naik] Tampilkan data ke output
}
// --- Fungsi Matematika Geser Bit (Bitwise) ---
void geserBit() {
if (arahKanan) {
ledData = ledData << 1; // Geser bit ke kiri (001 -> 010)
if (ledData == 0b10000000) arahKanan = false; // Jika mentok kiri, balik arah
} else {
ledData = ledData >> 1; // Geser bit ke kanan
if (ledData == 0b00000001) arahKanan = true; // Jika mentok kanan, balik arah
}
}
// --- Fungsi Serial Parser ---
void checkSerial() {
while (Serial.available()) {
char inChar = (char)Serial.read();
inputString += inChar;
if (inChar == '\n') {
parseCommand();
inputString = "";
}
}
}
void parseCommand() {
inputString.trim();
if (inputString.startsWith("SET FREQ")) {
String valStr = inputString.substring(9);
int val = valStr.toInt();
// Mapping nilai soal ke visual mata manusia
// Soal minta 2ms/5ms/10ms.
// Tapi 2ms terlalu cepat untuk mata (LED terlihat nyala semua).
// Kita kalikan 10 atau 20 agar terlihat gerakannya di simulasi.
if (val > 0) {
interval = val * 20;
Serial.print("Speed Updated. Interval Variable: ");
Serial.println(interval);
}
}
}