#include <Adafruit_NeoPixel.h>
#include <LiquidCrystal.h>
#define LED_PIN 6
#define NUM_LEDS 16
Adafruit_NeoPixel ring(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
String bookName = "";
String genre = "DEFAULT";
int modeID = 0;
unsigned long lastAnimTime = 0;
int stepIndex = 0;
void setAll(int r, int g, int b, int brightness) {
ring.setBrightness(brightness);
for (int i = 0; i < NUM_LEDS; i++) {
ring.setPixelColor(i, ring.Color(r, g, b));
}
ring.show();
}
void updateLCD(String line1, String line2) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(line1);
lcd.setCursor(0, 1);
lcd.print(line2);
}
String toLowerCase(String s) {
for (int i = 0; i < s.length(); i++) {
s[i] = tolower(s[i]);
}
return s;
}
String detectGenre(String name) {
name = toLowerCase(name);
if (name.indexOf("ghost") >= 0 || name.indexOf("haunted") >= 0 ||
name.indexOf("horror") >= 0 || name.indexOf("dracula") >= 0 ||
name.indexOf("it") >= 0) {
return "HORROR";
}
if (name.indexOf("love") >= 0 || name.indexOf("romance") >= 0 ||
name.indexOf("heart") >= 0 || name.indexOf("kiss") >= 0) {
return "ROMANCE";
}
if (name.indexOf("murder") >= 0 || name.indexOf("crime") >= 0 ||
name.indexOf("killer") >= 0 || name.indexOf("thriller") >= 0 ||
name.indexOf("escape") >= 0) {
return "THRILLER";
}
if (name.indexOf("mystery") >= 0 || name.indexOf("detective") >= 0 ||
name.indexOf("secret") >= 0 || name.indexOf("case") >= 0 ||
name.indexOf("clue") >= 0) {
return "MYSTERY";
}
if (name.indexOf("magic") >= 0 || name.indexOf("dragon") >= 0 ||
name.indexOf("wizard") >= 0 || name.indexOf("kingdom") >= 0 ||
name.indexOf("harry potter") >= 0) {
return "FANTASY";
}
return "DEFAULT";
}
void horrorAnimation() {
int brightness = 30 + abs(70 - (stepIndex % 140)); // pulse
setAll(255, 0, 0, brightness);
stepIndex++;
}
void romanceAnimation() {
int brightness = 60 + (stepIndex % 90);
setAll(255, 20, 147, brightness);
stepIndex++;
}
void thrillerAnimation() {
if (stepIndex % 2 == 0) setAll(255, 255, 0, 150);
else setAll(0, 0, 0, 0);
stepIndex++;
}
void mysteryAnimation() {
ring.clear();
ring.setBrightness(150);
ring.setPixelColor(stepIndex % NUM_LEDS, ring.Color(128, 0, 128));
ring.show();
stepIndex++;
}
void fantasyAnimation() {
int brightness = 60 + (stepIndex % 100);
setAll(0, 255, 255, brightness); // Cyan magical glow
stepIndex++;
}
void defaultAnimation() {
setAll(255, 180, 120, 120); // Warm reading light
}
void setMode(String g) {
genre = g;
stepIndex = 0;
if (genre == "HORROR") {
modeID = 1;
updateLCD("Genre: HORROR", "Cinematic ON");
}
else if (genre == "ROMANCE") {
modeID = 2;
updateLCD("Genre: ROMANCE", "Cinematic ON");
}
else if (genre == "THRILLER") {
modeID = 3;
updateLCD("Genre: THRILLER", "Cinematic ON");
}
else if (genre == "MYSTERY") {
modeID = 4;
updateLCD("Genre: MYSTERY", "Cinematic ON");
}
else if (genre == "FANTASY") {
modeID = 5;
updateLCD("Genre: FANTASY", "Cinematic ON");
}
else {
modeID = 0;
updateLCD("Genre: DEFAULT", "Normal Reading");
}
}
void setup() {
Serial.begin(9600);
ring.begin();
ring.show();
lcd.begin(16, 2);
updateLCD("Enter Book Name", "in Serial Monitor");
Serial.println("Immersive Reading Environment");
Serial.println("Type ONLY book name and press Enter");
Serial.println("Example: Harry Potter / ghost story / love in life");
}
void loop() {
if (Serial.available()) {
bookName = Serial.readStringUntil('\n');
bookName.trim();
if (bookName.length() > 0) {
Serial.print("📚 Book Name: ");
Serial.println(bookName);
String detected = detectGenre(bookName);
Serial.print("🎭 Detected Genre: ");
Serial.println(detected);
setMode(detected);
}
}
if (millis() - lastAnimTime > 100) {
lastAnimTime = millis();
if (modeID == 1) horrorAnimation();
else if (modeID == 2) romanceAnimation();
else if (modeID == 3) thrillerAnimation();
else if (modeID == 4) mysteryAnimation();
else if (modeID == 5) fantasyAnimation();
else defaultAnimation();
}
}