// --- Indonesia Raya: Buzzer + OLED Lyrics (delay based) + Red/White LED ---
// Board: Arduino UNO
// Buzzer pasif di D8
// LED Merah di D9, LED Putih di D10
// OLED SSD1306 I2C (128x64): SDA=A4, SCL=A5
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define BUZZER_PIN 23
#define LED_RED 9
#define LED_WHITE 10
float tempoScale = 1.0;
// ================== MELODY (singkatkan di sini, isi lengkap sama seperti sebelumnya) ==================
// 0 = rest. Durasi ms. Elemen terakhir durasi = 0 (sentinel).
int melody[] = {
262,277,311,523,0,523,466,466,415,311,0,311,311,349,311,277,262,233,0,
233,262,277,466,0,466,415,415,392,349,0,311,311,392,349,311,277,262,0,
262,277,311,523,0,523,466,466,415,311,0,311,311,349,311,415,466,392,349,
349,349,554,554,523,466,622,415,392,349,311,554,523,466,415,0,311,311,349,
554,554,554,554,554,523,415,415,415,392,415,466,622,622,622,554,554,523,
415,311,311,349,554,554,554,554,554,523,415,415,415,392,415,466,622,622,
523,466,415,0,415,415,554,698,698,698,698,698,622,523,523,523,622,622,
554,466,466,466,622,554,523,415,415,415,554,698,698,698,698,698,622,523,
523,523,622,622,622,554,523,466,523,466,415,0,415,415,622,554,523,466,
523,466,415,0,0
};
int noteDurations[] = {
468,156,624,624,468,156,468,156,624,624,624,468,156,624,624,624,624,1248,624,
468,156,624,624,468,156,468,156,624,624,624,468,156,624,624,624,624,1248,624,
468,156,624,624,468,156,468,156,624,624,624,468,156,624,624,624,624,1248,624,
468,156,624,624,624,624,1248,624,468,156,624,624,624,624,1248,624,468,156,624,
468,156,624,468,156,624,468,156,624,468,156,624,468,156,624,468,156,1248,624,
468,156,624,468,156,624,468,156,624,468,156,624,468,156,624,624,624,468,156,
1248,624,468,156,624,468,156,624,468,156,624,468,156,624,468,156,624,468,156,
624,468,156,1248,624,468,156,624,468,156,624,468,156,624,468,156,624,468,156,
624,468,156,624,468,156,1248,624,468,156,624,468,156,624,468,156,1248,1248,0
};
// ================== LIRIK BERDASAR DELAY ==================
struct LyricTime {
unsigned long ms; // waktu sejak awal lagu
const char* text;
};
LyricTime lyricTimes[] = {
{0, "Indonesia tanah airku" },
{3750, "Tanah tumpah darahku" },
{9000, "Disanalah aku berdiri" },
{13750, "Jadi pandu ibuku" },
{18500, "Indonesia kebangsaanku" },
{24000, "Bangsa dan tanah airku" },
{29500, "Marilah kita berseru" },
{34500, "Indonesia bersatu" },
{39000, "Hiduplah tanahku" },
{42000, "Hiduplah negeriku" },
{44500, "Bangsaku rakyatku semuanya" },
{49300, "Bangunlah jiwanya" },
{52000, "Bangunlah badannya" },
{54500, "Untuk Indonesia Raya" },
{59000, "Indonesia Raya, merdeka!" },
{64500, "Tanahku negeriku yang kucinta" },
{69500, "Indonesia Raya, merdeka!" },
{74500, "Hiduplah Indonesia Raya" }
};
int lyricCount = sizeof(lyricTimes)/sizeof(lyricTimes[0]);
// ================== OLED ==================
void oledShowLine(const char* line) {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
display.setCursor(0, 28);
display.println(line);
display.display();
}
// ================== SETUP ==================
void setup() {
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LED_RED, OUTPUT);
pinMode(LED_WHITE, OUTPUT);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
// OLED gagal, lanjut tanpa tampilan
} else {
oledShowLine("INDONESIA RAYA");
delay(1000);
}
playIndonesiaRaya();
}
void loop() {}
// ================== PEMUTARAN ==================
void playIndonesiaRaya() {
unsigned long elapsed = 0;
int nextLyric = 0;
int N = sizeof(melody)/sizeof(melody[0]);
for (int i = 0; i < N; i++) {
int dur = noteDurations[i];
if (dur <= 0) break;
dur = (int)(dur * tempoScale);
// cek apakah waktunya ganti lirik
if (nextLyric < lyricCount && elapsed >= lyricTimes[nextLyric].ms) {
oledShowLine(lyricTimes[nextLyric].text);
nextLyric++;
}
// LED bergantian
int ledOn = (i % 2 == 0) ? LED_RED : LED_WHITE;
int ledOff = (i % 2 == 0) ? LED_WHITE : LED_RED;
digitalWrite(ledOff, LOW);
digitalWrite(ledOn, HIGH);
// mainkan nada
if (melody[i] > 0) tone(BUZZER_PIN, melody[i], dur*0.9);
else noTone(BUZZER_PIN);
delay(dur);
elapsed += dur;
noTone(BUZZER_PIN);
digitalWrite(ledOn, LOW);
}
// akhir lagu
noTone(BUZZER_PIN);
digitalWrite(LED_RED, LOW);
digitalWrite(LED_WHITE, LOW);
}