1#include <WiFi.h>
2#include <VS1053.h>
3#include <U8g2lib.h>
4
5
6#define VS1053_CS 32
7#define VS1053_DCS 33
8#define VS1053_DREQ 35
9
10
11#define BUTTON_NEXT 13
12#define BUTTON_PREV 12
13
14
15U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);
16
17
18const char *ssid = "Your SSID";
19const char *password = "Your Wifi Password";
20
21
22const char* stationNames[] = {"ERT Kosmos", "FFH Lounge", "FFH Summer"};
23const char* stationHosts[] = {"radiostreaming.ert.gr", "mp3.ffh.de", "mp3.ffh.de"};
24const char* stationPaths[] = {"/ert-kosmos", "/ffhchannels/hqlounge.mp3", "/ffhchannels/hqsummerfeeling.mp3"};
25int currentStation = 0;
26const int totalStations = sizeof(stationNames) / sizeof(stationNames[0]);
27
28
29VS1053 player(VS1053_CS, VS1053_DCS, VS1053_DREQ);
30WiFiClient client;
31
32
33int textPosition = 128;
34unsigned long previousMillis = 0;
35const long interval = 50;
36
37void setup() {
38 Serial.begin(115200);
39
40
41 delay(3000);
42
43 u8g2.begin();
44 u8g2.setFlipMode(1);
45 u8g2.setFont(u8g2_font_ncenB08_tr);
46
47
48 u8g2.clearBuffer();
49 u8g2.drawStr(0, 16, "Starting Radio...");
50 u8g2.sendBuffer();
51 delay(2000);
52
53 u8g2.clearBuffer();
54 u8g2.drawStr(0, 16, "Starting Engine...");
55 u8g2.sendBuffer();
56 delay(2000);
57
58 u8g2.clearBuffer();
59 u8g2.drawStr(0, 16, "Connecting to WiFi...");
60 u8g2.sendBuffer();
61
62 Serial.println("\n\nSimple Radio Node WiFi Radio");
63
64 SPI.begin();
65
66 player.begin();
67 if (player.getChipVersion() == 4) {
68 player.loadDefaultVs1053Patches();
69 }
70 player.switchToMp3Mode();
71 player.setVolume(100);
72
73 Serial.print("Connecting to SSID ");
74 Serial.println(ssid);
75 WiFi.begin(ssid, password);
76
77
78 WiFi.setSleep(false);
79
80
81 int attempts = 0;
82 while (WiFi.status() != WL_CONNECTED && attempts < 20) {
83 delay(500);
84 Serial.print(".");
85 attempts++;
86 }
87
88
89 if (WiFi.status() == WL_CONNECTED) {
90 Serial.println("WiFi connected");
91 Serial.println("IP address: ");
92 Serial.println(WiFi.localIP());
93
94
95 u8g2.clearBuffer();
96 u8g2.drawStr(0, 16, "Connected Yay!");
97 u8g2.sendBuffer();
98 delay(2000);
99 } else {
100
101 Serial.println("WiFi not connected");
102 u8g2.clearBuffer();
103 u8g2.drawStr(0, 16, "Not Connected");
104 u8g2.sendBuffer();
105 delay(2000);
106 }
107
108
109 pinMode(BUTTON_NEXT, INPUT_PULLUP);
110 pinMode(BUTTON_PREV, INPUT_PULLUP);
111
112
113 u8g2.setFont(u8g2_font_profont17_mr);
114
115 displayStation();
116 connectToHost();
117}
118
119void loop() {
120
121 if (!client.connected()) {
122 Serial.println("Reconnecting...");
123 connectToHost();
124 }
125
126
127 if (client.available() > 0) {
128 uint8_t buffer[32];
129 size_t bytesRead = client.readBytes(buffer, sizeof(buffer));
130 player.playChunk(buffer, bytesRead);
131 }
132
133 handleButtons();
134 scrollText();
135}
136
137void connectToHost() {
138
139 Serial.print("Connecting to ");
140 Serial.println(stationHosts[currentStation]);
141
142 if (!client.connect(stationHosts[currentStation], 80)) {
143 Serial.println("Connection failed");
144 return;
145 }
146
147
148 Serial.print("Requesting stream: ");
149 Serial.println(stationPaths[currentStation]);
150
151 client.print(String("GET ") + stationPaths[currentStation] + " HTTP/1.1\r\n" +
152 "Host: " + stationHosts[currentStation] + "\r\n" +
153 "Connection: close\r\n\r\n");
154
155
156 while (client.connected()) {
157 String line = client.readStringUntil('\n');
158 if (line == "\r") {
159 break;
160 }
161 }
162
163 Serial.println("Headers received");
164}
165
166void handleButtons() {
167 static bool lastButtonNextState = HIGH;
168 static bool lastButtonPrevState = HIGH;
169
170 bool currentButtonNextState = digitalRead(BUTTON_NEXT);
171 bool currentButtonPrevState = digitalRead(BUTTON_PREV);
172
173
174 if (lastButtonNextState == HIGH && currentButtonNextState == LOW) {
175 nextStation();
176 }
177
178 if (lastButtonPrevState == HIGH && currentButtonPrevState == LOW) {
179 previousStation();
180 }
181
182 lastButtonNextState = currentButtonNextState;
183 lastButtonPrevState = currentButtonPrevState;
184}
185
186void nextStation() {
187 currentStation = (currentStation + 1) % totalStations;
188 displayStation();
189 connectToHost();
190}
191
192
193void nextStation() {
194 currentStation = (currentStation + 1) % totalStations;
195 displayStation();
196 connectToHost();
197}
198
199void previousStation() {
200 currentStation = (currentStation - 1 + totalStations) % totalStations;
201 displayStation();
202 connectToHost();
203}
204
205void displayStation() {
206 textPosition = 128;
207 u8g2.clearBuffer();
208 u8g2.drawLine(0, 0, 127, 0);
209 u8g2.drawLine(0, 31, 127, 31);
210 u8g2.setCursor(textPosition, 22);
211 u8g2.print(stationNames[currentStation]);
212 u8g2.sendBuffer();
213}
214
215void scrollText() {
216 unsigned long currentMillis = millis();
217
218 if (currentMillis - previousMillis >= interval) {
219 previousMillis = currentMillis;
220 textPosition--;
221 if (textPosition < -u8g2.getUTF8Width(stationNames[currentStation])) {
222 textPosition = 128;
223 }
224
225 u8g2.clearBuffer();
226 u8g2.drawLine(0, 0, 127, 0);
227 u8g2.drawLine(0, 31, 127, 31);
228 u8g2.setCursor(textPosition, 22);
229 u8g2.print(stationNames[currentStation]);
230 u8g2.sendBuffer();
231 }
232}