#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <esp_wifi.h>
#include <EEPROM.h>
#include <SPI.h>
// OLED display settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// VS1053 MP3 decoder pins
#define VS1053_CS 32
#define VS1053_DCS 33
#define VS1053_DREQ 35
// Potentiometer and Buzzer pins
#define POT_PIN 34
#define BUZZER_PIN 5
uint8_t volume = 50;
#define VOLUME 100 // volume level 0-100
#define EEPROM_SIZE 2
// Time interval for autosave
long interval = 1000;
int SECONDS_TO_AUTOSAVE = 30;
long seconds = 0;
long previousMillis = 0;
// Radio station configuration
int radioStation = 0;
int previousRadioStation = -1;
// Buttons for changing stations
const int previousButton = 12;
const int nextButton = 13;
// WiFi credentials
char ssid[] = "Wokwi-GUEST";
char pass[] = "v";
// Radio station URLs and settings
char *host[5] = {"media-ice.musicradio.com", "radionorthsea.zapto.org", "peridot.streamguys.com", "192.99.41.102", "ice1.streeemer.com"};
char *path[5] = {"/ClassicFM-M-Movies", "/stream", "/Mirchi", "/;", "/radio.aac"};
int port[5] = {80, 8008, 7150, 5429, 8020};
int status = WL_IDLE_STATUS;
WiFiClient client;
uint8_t mp3buff[32];
// Initialize VS1053 object
//VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);
// Function to update volume value
void updateValue(int delta) {
volume = constrain(volume + delta, 0, 100);
}
// Function to update OLED display
void updateDisplay() {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
// Display RADIONET title
display.setCursor(0, 0);
display.println("DIGITAL RADIO");
// Display station name
display.setCursor(0, 10);
switch (radioStation) {
case 0:
display.println("Classic Hits");
break;
case 1:
display.println("Private Radio");
break;
case 2:
display.println("Mirchi FM");
break;
case 3:
display.println("Suryan FM");
break;
case 4:
display.println("RadiCity");
break;
}
// Draw volume bar
display.setCursor(0, 45);
display.println("Volume");
display.drawRoundRect(10, 54, 108, 7, 2, WHITE);
display.fillRect(11, 55, volume * 106 / 100, 5, WHITE);
display.display();
}
// Interrupt service routine for previous button
void IRAM_ATTR previousButtonInterrupt() {
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
if (interrupt_time - last_interrupt_time > 200) {
if (radioStation > 0)
radioStation--;
else
radioStation = 4;
}
last_interrupt_time = interrupt_time;
}
// Interrupt service routine for next button
void IRAM_ATTR nextButtonInterrupt() {
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
if (interrupt_time - last_interrupt_time > 200) {
if (radioStation < 4)
radioStation++;
else
radioStation = 0;
}
last_interrupt_time = interrupt_time;
}
// Interrupt service routine for volume potentiometer
void IRAM_ATTR volumePotInterrupt() {
static unsigned long last_interrupt_time = 0;
unsigned long interrupt_time = millis();
if (interrupt_time - last_interrupt_time > 200) {
int sensorValue = analogRead(POT_PIN);
volume = map(sensorValue, 0, 4095, 0, 100);
last_interrupt_time = interrupt_time;
}
}
void setup() {
Serial.begin(9600);
delay(500);
SPI.begin();
// Initialize OLED display
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;)
;
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 10);
display.println("Connecting");
display.display();
// Initialize EEPROM
EEPROM.begin(EEPROM_SIZE);
// Set up button and potentiometer pins
pinMode(previousButton, INPUT_PULLUP);
pinMode(nextButton, INPUT_PULLUP);
pinMode(POT_PIN, INPUT);
pinMode(BUZZER_PIN, OUTPUT);
analogWrite(BUZZER_PIN, 0); // Initialize the buzzer with 0 volume
// Attach interrupt routines to buttons and potentiometer
attachInterrupt(digitalPinToInterrupt(previousButton), previousButtonInterrupt, FALLING);
attachInterrupt(digitalPinToInterrupt(nextButton), nextButtonInterrupt, FALLING);
attachInterrupt(digitalPinToInterrupt(POT_PIN), volumePotInterrupt, FALLING);
// Connect to WiFi
Serial.print("Connecting to WiFi");
WiFi.begin("Wokwi-GUEST", "", 6);
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println(" Connected!");
// Read station from EEPROM and set it
int throwaway = readStationFromEEPROM();
Serial.println("ReadFromEEPROM(): " + String(throwaway));
throwaway = readStationFromEEPROM();
Serial.println("ReadFromEEPROM(): " + String(throwaway));
radioStation = throwaway;
// Update display with initial values
display.clearDisplay();
updateDisplay();
display.display();
}
void loop() {
// Check if it's time to connect to the radio station
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > interval) {
if (radioStation != previousRadioStation) {
station_connect(radioStation);
previousRadioStation = radioStation;
seconds = 0;
} else {
seconds++;
if (seconds == SECONDS_TO_AUTOSAVE) {
int readStation = readStationFromEEPROM();
if (readStation != radioStation) {
Serial.println("loop(): Saving new station to EEPROM");
writeStationToEEPROM(&radioStation);
}
}
}
previousMillis = currentMillis;
Serial.println("loop(): " + String(seconds) + " " + String(radioStation));
}
// Read volume from potentiometer and update display
int sensorValue = analogRead(POT_PIN);
int mappedVolume = map(sensorValue, 0, 4095, 0, 100);
if (volume != mappedVolume) {
volume = mappedVolume;
analogWrite(BUZZER_PIN, map(volume, 0, 100, 0, 255));
updateDisplay();
}
// If data available from the radio station, send it to VS1053
//if (client.available() > 0) {
// uint8_t bytesread = client.read(mp3buff, 32);
// player.playChunk(mp3buff, bytesread);
//}
}
// Connect to the specified radio station
void station_connect(int station_no) {
//if (client.connect(host[station_no], port[station_no])) {
Serial.println("Connected to radio station");
//client.print(String("GET ") + path[station_no] + " HTTP/1.1\r\n" +
// "Host: " + host[station_no] + "\r\n" +
// "Connection: close\r\n\r\n");
drawRadioStationName(station_no);
//}
}
// Read radio station from EEPROM
int readStationFromEEPROM() {
int station;
byte ByteArray[2];
for (int x = 0; x < 2; x++) {
ByteArray[x] = EEPROM.read(x);
}
memcpy(&station, ByteArray, 2);
Serial.println("readFrequencyFromEEPROM(): " + String(station));
return station;
}
// Write radio station to EEPROM
void writeStationToEEPROM(int *freq) {
byte ByteArray[2];
memcpy(ByteArray, freq, 2);
for (int x = 0; x < 2; x++) {
EEPROM.write(x, ByteArray[x]);
}
EEPROM.commit();
Serial.println("writeFrequencyFromEEPROM(): " + String(radioStation));
}
// Initialize the MP3 decoder
//void initMP3Decoder() {
//player.begin();
//player.switchToMp3Mode(); // optional, some boards require this
//player.setVolume(VOLUME);
//}
// Draw radio station name on OLED display
void drawRadioStationName(int id) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0, 0);
switch (id) {
case 0:
display.println("Classic Hits");
break;
case 1:
display.println("Private Radio");
break;
case 2:
display.println("Mirchi FM");
break;
case 3:
display.println("suryan FM");
break;
case 4:
display.println("Radio City");
break;
}
display.display();
delay(2000);
}