#include <Arduino.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
// Bluetooth initialization task (with higher priority)
TaskHandle_t bluetoothInitTaskHandle = NULL;
// Timer handle declaration
TaskHandle_t timerTaskHandle = NULL;
// Task handle for controlMusic
TaskHandle_t controlMusicTaskHandle = NULL;
// Mutex to protect shared resources
SemaphoreHandle_t resourceMutex;
// Semaphore to signal that Bluetooth initialization is complete
SemaphoreHandle_t bluetoothInitCompleteSemaphore;
// Mutex for priority inheritance
SemaphoreHandle_t bluetoothInitMutex;
// LED Pin Setup
const int LED_PIN = 2;
// Display Format
const char* TIME_DISPLAY_FORMAT = "%02d:%02d";
// Scheduling Interval
const int SCHEDULING_INTERVAL = 1000;
// Software time interval and maximum song duration (5 minutes)
const unsigned long SOFTWARE_TIMER_INTERVAL = 1000; // 1 second
const unsigned long MAX_TIMER_DURATION = 300000;
// Enum containing program states
enum PlayerState {
Playing,
Paused,
Stopped
};
// Global variables
PlayerState playerState = Stopped;
unsigned long timerStartTime = MAX_TIMER_DURATION;
unsigned long timerElapsedTime = 0;
// Control variables to manage printing
bool printCS6IoT = true;
bool printBuffering = false;
bool printTimer = false;
bool printBufferingOnce = true; // Flag to print "Buffering internet, sabar yah" only once
bool printTimerOnce = false; // Flag to print "timertask" only once
void timerTask(void* pvParameters) {
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = pdMS_TO_TICKS(SCHEDULING_INTERVAL);
while (true) {
vTaskDelayUntil(&xLastWakeTime, xFrequency);
if (playerState == Playing) {
timerElapsedTime = millis() - timerStartTime;
if (timerElapsedTime >= MAX_TIMER_DURATION) {
digitalWrite(LED_PIN, LOW);
timerStartTime = millis();
Serial.println("Lagunya sudah selesai.");
} else {
printBuffering = true;
printTimer = true;
Serial.print("Time: ");
char timeBuffer[10];
sprintf(timeBuffer, TIME_DISPLAY_FORMAT, timerElapsedTime / 60000, (timerElapsedTime % 60000) / 1000);
Serial.print(timeBuffer);
Serial.println("/5:00");
}
}
}
}
void controlMusicTask(void* pvParameters) {
if (xSemaphoreTake(bluetoothInitCompleteSemaphore, portMAX_DELAY) == pdPASS) {
// Take the resourceMutex to protect shared resources
if (xSemaphoreTake(bluetoothInitMutex, portMAX_DELAY) == pdPASS) {
while (Serial.available()) {
String command = Serial.readStringUntil('\n');
char state_selector = command.charAt(1);
switch (state_selector) {
case 'l':
// Play
if (playerState == Stopped) {
if (printCS6IoT) {
Serial.println("CS 6 IoT - Risa Culametan - Culametan Met Met (Official Music Video)");
printCS6IoT = false;
printBuffering = true;
printTimer = true;
}
playerState = Playing;
digitalWrite(LED_PIN, HIGH);
timerStartTime = millis();
} else if (playerState == Paused) {
// If it's paused, resume playing
playerState = Playing;
digitalWrite(LED_PIN, HIGH);
timerStartTime = millis() - timerElapsedTime;
Serial.println("Lagu diputar kembali.");
} else {
Serial.println("Lagu sedang diputar atau sudah selesai, tidak dapat memutar kembali.");
}
break;
case 'a':
// Pause
if (playerState == Playing) {
playerState = Paused;
digitalWrite(LED_PIN, LOW);
Serial.println("Lagu di-pause.");
} else {
Serial.println("Tidak bisa melakukan pause, lagu tidak sedang diputar.");
}
break;
case 'e':
// Resume
if (playerState == Paused) {
playerState = Playing;
digitalWrite(LED_PIN, HIGH);
timerStartTime = millis() - timerElapsedTime;
Serial.println("Lagu diputar kembali.");
} else {
Serial.println("Lagu telah dihentikan, silahkan 'play' untuk memutarnya.");
}
break;
case 't':
// Stop
if (playerState != Stopped) {
playerState = Stopped;
Serial.println("Lagu dihentikan.");
digitalWrite(LED_PIN, LOW);
timerStartTime = 0;
timerElapsedTime = 0;
printCS6IoT = true;
} else {
Serial.println("Tidak ada lagu yang sedang diputar, ketika 'play' untuk memutar lagu.");
}
break;
default:
Serial.println("Unknown command");
}
// Consume the newline character ('\n') in the serial buffer
while (Serial.available() && Serial.read() != '\n') {
// Consume characters until newline is removed
}
}
// Release the resourceMutex
xSemaphoreGive(bluetoothInitMutex);
}
xSemaphoreGive(bluetoothInitCompleteSemaphore);
for (;;) {
vTaskDelay(pdMS_TO_TICKS(100)); // Delay to avoid busy-waiting
}
}
}
void bluetoothInitTask(void* pvParameters) {
// Take the Bluetooth initialization mutex
if (xSemaphoreTake(bluetoothInitMutex, portMAX_DELAY) == pdPASS) {
Serial.println("Initializing connection.");
// Simulate work
vTaskDelay(pdMS_TO_TICKS(2000));
Serial.println("Connection successful!");
// Release the Bluetooth initialization mutex
xSemaphoreGive(bluetoothInitMutex);
// Simulate some work related to the Bluetooth connection
vTaskDelay(pdMS_TO_TICKS(1000));
// Reacquire the Bluetooth initialization mutex for the remaining steps
/*if (xSemaphoreTake(bluetoothInitMutex, portMAX_DELAY) == pdPASS) {
Serial.println("Bluetooth initialization: Step 2");
// Simulate more work
vTaskDelay(pdMS_TO_TICKS(1000));
// Release the Bluetooth initialization mutex
xSemaphoreGive(bluetoothInitMutex);
}*/
}
// Signal that Bluetooth initialization is complete
xSemaphoreGive(bluetoothInitCompleteSemaphore);
for (;;) {
// Simulate some work related to the Bluetooth connection
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void setup() {
// Set the serial monitor baud rate
Serial.begin(115200);
// Initialize the player indication LED
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, LOW);
// Create the resourceMutex to protect shared resources
resourceMutex = xSemaphoreCreateMutex();
// Create the Bluetooth initialization complete semaphore
bluetoothInitCompleteSemaphore = xSemaphoreCreateBinary();
// Create the Bluetooth initialization mutex
bluetoothInitMutex = xSemaphoreCreateMutex();
// Create and start the timer task
xTaskCreatePinnedToCore(
timerTask, "Timer Task", 4096, NULL, 1, &timerTaskHandle, 0);
// Create and start the Bluetooth initialization task (higher priority)
xTaskCreatePinnedToCore(
bluetoothInitTask, "Bluetooth Init Task", 4096, NULL, 2, &bluetoothInitTaskHandle, 0); // Higher priority
// Create and start the controlMusicTask
xTaskCreatePinnedToCore(
controlMusicTask, "Control Music Task", 4096, NULL, 3, &controlMusicTaskHandle, 0); // Medium priority
}
void loop() {
// Empty loop; everything is task-based
}