#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDR 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void setup() {
Wire.begin();
if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
for (;;);
}
scanBootAnimation();
}
void loop() {
// Nothing yet
}
void whiteBG() {
display.clearDisplay();
display.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, SSD1306_WHITE);
}
void drawScanLine(int y) {
// A thin black line + a tiny "shadow" above it for depth
display.drawFastHLine(0, y, SCREEN_WIDTH, SSD1306_BLACK);
if (y > 0) display.drawFastHLine(0, y - 2, SCREEN_WIDTH, SSD1306_BLACK);
}
void typeText(int x, int y, uint8_t size, const char* text, int perCharDelayMs) {
display.setTextSize(size);
display.setTextColor(SSD1306_BLACK);
display.setCursor(x, y);
for (int i = 0; text[i] != '\0'; i++) {
display.print(text[i]);
display.display();
delay(perCharDelayMs);
}
}
void scanBootAnimation() {
// 1) White background
whiteBG();
display.display();
delay(200);
// 2) Scan line sweep
for (int y = 0; y < SCREEN_HEIGHT; y += 2) {
whiteBG();
// Keep a tiny header marker for "device-ness"
display.drawRect(2, 2, 20, 8, SSD1306_BLACK);
display.fillRect(4, 4, 6, 4, SSD1306_BLACK); // little "status block"
drawScanLine(y);
display.display();
delay(20);
}
// 3) Type in "NFC"
whiteBG();
display.drawRect(2, 2, 20, 8, SSD1306_BLACK);
display.fillRect(4, 4, 6, 4, SSD1306_BLACK);
display.display();
typeText(18, 20, 3, "N", 0);
delay(120);
typeText(18 + 18, 20, 3, "F", 0);
delay(120);
typeText(18 + 36, 20, 3, "C", 0);
delay(250);
// 4) "Play" appears, then collapses to "P"
display.setTextSize(2);
display.setTextColor(SSD1306_BLACK);
display.setCursor(78, 34);
display.print("Play");
display.display();
delay(450);
// Collapse effect: erase letters from right to left in chunky steps
// Area covering "Play" at size 2 is roughly 4 chars * 12px wide = ~48px; height ~16px
int x = 78, y = 34;
int w = 52, h = 16;
// Erase right side in chunks to feel "mechanical"
for (int i = 0; i < 5; i++) {
display.fillRect(x + (w - (i + 1) * 10), y, 10, h, SSD1306_WHITE);
display.display();
delay(70);
}
// Final: clear and draw a bold P
display.fillRect(x, y, w, h, SSD1306_WHITE);
display.setTextSize(3);
display.setTextColor(SSD1306_BLACK);
display.setCursor(78, 20);
display.println("P");
display.setTextSize(0.5);
display.println(" ^INSERT MEDIA^");
display.display();
// "Lock" flash: invert quickly twice
delay(120);
display.invertDisplay(true);
delay(60);
display.invertDisplay(false);
delay(80);
display.invertDisplay(true);
delay(40);
display.invertDisplay(false);
}