#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_FT6206.h>
// Pin definitions for the TFT display
#define TFT_CS 10
#define TFT_RST 8
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);
// Touch screen pins
Adafruit_FT6206 ts = Adafruit_FT6206();
// Buttons
Adafruit_GFX_Button autoModeBtn, manualModeBtn;
Adafruit_GFX_Button prevBtn, nextBtn;
Adafruit_GFX_Button startBtn, mainMenuBtn;
Adafruit_GFX_Button EnBtn, FrBtn;
Adafruit_GFX_Button MTBtn, STBtn;
// Frequencies and timer values
int freq1 = 10;
int freq2 = 10;
int freq3 = 10;
int timerDuration = 30; // in seconds
// Positions for slider labels
const int labelX = 250;
const int labelY1 = 50;
const int labelY2 = 90;
const int labelY3 = 130;
const int labelY4 = 170;
int minF = 1; // Minimum frequency
int maxF = 100; // Maximum frequency
const int minT = 1; // Minimum time
const int maxT = 60; // Maximum time
int tonePin = 6;
bool startFlag = false;
String screen = "select_lang";
String mode = "select_lang";
String lang = "";
String mt_st = "";
const char* diseasesEN[] = { "Wrist", "Elbout", "Shoulder", "Cervical Vertebra", "Lumbar Vertebra", "Groin", "Hip", "Thigh", "Knee", "Foot/Ankle" };
const char* diseasesFR[] = { "Poignet", "Coude", "Épaule", "Vertèbre cervicale", "Vertèbre lombaire", "Aine", "Hanche", "Cuisse", "Genou", "Pied/Cheville" };
const int frequenciesMT[][3] = {
{ 7, 25, 10 }, // Frequencies for Wrist
{ 7, 25, 10 }, // Frequencies for Elbout
{ 7, 25, 10 }, // Frequencies for Shoulder
{ 7, 25, 10 }, // Frequencies for Cervical Vertebra
{ 7, 25, 10 }, // Frequencies for Lumbar Vertebra
{ 7, 25, 10 }, // Frequencies for Groin
{ 25, 45, 15 }, // Frequencies for Hip
{ 7, 25, 10 }, // Frequencies for Thigh
{ 7, 25, 10 }, // Frequencies for Knee
{ 7, 25, 10 } // Frequencies for Foot/Ankle
};
const int frequenciesST[][3] = {
{ 1000, 3000, 2000 }, // Frequencies for Wrist
{ 1000, 3000, 2000 }, // Frequencies for Elbout
{ 1000, 3000, 2000 }, // Frequencies for Shoulder
{ 1000, 3000, 2000 }, // Frequencies for Cervical Vertebra
{ 1000, 3000, 2000 }, // Frequencies for Lumbar Vertebra
{ 1000, 3000, 2000 }, // Frequencies for Groin
{ 1000, 3000, 2000 }, // Frequencies for Hip
{ 1000, 3000, 2000 }, // Frequencies for Thigh
{ 1000, 3000, 2000 }, // Frequencies for Knee
{ 1000, 3000, 2000 } // Frequencies for Foot/Ankle
};
const int timers[] = { 15, 15, 20 , 20, 20, 15, 20, 20, 20, 15}; // Timers in minutes for auto mode
int NumDiseases = 10;
int currentDiseaseIndex = 0;
unsigned long lastDebounceTime = 0;
const unsigned long debounceDelay = 50; // milliseconds
void setup() {
Serial.begin(9600);
tft.begin();
tft.setRotation(3);
tft.fillScreen(ILI9341_WHITE); // Set background to white
ts.begin();
displaySelectLang();
}
void loop() {
if (ts.touched()) {
TS_Point p = ts.getPoint();
handleTouch(320 - p.y, p.x);
}
}
bool debounce() {
if ((millis() - lastDebounceTime) > debounceDelay) {
lastDebounceTime = millis();
return true;
}
return false;
}
void displaySelectLang() {
tft.fillScreen(ILI9341_WHITE);
tft.setTextColor(ILI9341_BLACK);
tft.setTextSize(2);
tft.setCursor(20, 20);
tft.print("Select Language:");
tft.setCursor(20, 50);
tft.print("Choisir la langue:");
EnBtn.initButton(&tft, 160, 140, 150, 40, ILI9341_BLACK, ILI9341_BLUE, ILI9341_WHITE, "English", 2);
FrBtn.initButton(&tft, 160, 200, 150, 40, ILI9341_BLACK, ILI9341_BLUE, ILI9341_WHITE, "French", 2);
EnBtn.drawButton(false);
FrBtn.drawButton(false);
Serial.println("Language Selection Displayed");
}
void displaySelectMT_ST() {
tft.fillScreen(ILI9341_WHITE);
MTBtn.initButton(&tft, 160, 140, 150, 40, ILI9341_BLACK, ILI9341_BLUE, ILI9341_WHITE, "MT Mode", 2);
STBtn.initButton(&tft, 160, 200, 150, 40, ILI9341_BLACK, ILI9341_BLUE, ILI9341_WHITE, "ST Mode", 2);
MTBtn.drawButton(false);
STBtn.drawButton(false);
Serial.println("MT_ST Selection Displayed");
}
void displayMainMenu() {
tft.fillScreen(ILI9341_WHITE);
tft.setTextColor(ILI9341_BLACK);
tft.setTextSize(2);
tft.setCursor(60, 60);
tft.print(getStr(lang, "Sélectionnez le Mode", "Select Mode"));
autoModeBtn.initButton(&tft, 160, 140, 150, 40, ILI9341_BLACK, ILI9341_BLUE, ILI9341_WHITE, getStr(lang, "Automatique", "Auto"), 2);
manualModeBtn.initButton(&tft, 160, 200, 150, 40, ILI9341_BLACK, ILI9341_BLUE, ILI9341_WHITE, getStr(lang, "Manuel", "Manual"), 2);
autoModeBtn.drawButton(false);
manualModeBtn.drawButton(false);
Serial.println("Main Menu Displayed");
}
void displayAutoMode() {
tft.fillScreen(ILI9341_WHITE);
tft.setTextColor(ILI9341_BLACK);
tft.setTextSize(2);
tft.setCursor(10, 10);
tft.print(getStr(lang, "Mode Automatique:", "Auto Mode:"));
prevBtn.initButton(&tft, 37, 223, 70, 30, ILI9341_BLACK, ILI9341_BLUE, ILI9341_WHITE, "<<", 2);
nextBtn.initButton(&tft, 283, 223, 70, 30, ILI9341_BLACK, ILI9341_BLUE, ILI9341_WHITE, ">>", 2);
mainMenuBtn.initButton(&tft, 303, 15, 30, 30, ILI9341_BLACK, ILI9341_RED, ILI9341_WHITE, "X", 3);
startBtn.initButton(&tft, 160, 218, 120, 40, ILI9341_BLACK, ILI9341_GREEN, ILI9341_WHITE, getStr(lang, "Commencer:", "Start"), 2);
prevBtn.drawButton(false);
nextBtn.drawButton(false);
mainMenuBtn.drawButton(false);
startBtn.drawButton(false);
SetConfig();
Serial.println("Auto Mode Displayed");
}
void displayManualMode() {
tft.fillScreen(ILI9341_WHITE);
tft.setTextColor(ILI9341_BLACK);
tft.setTextSize(2);
tft.setCursor(10, 10);
tft.print(getStr(lang, "Mode Manuel:", "Manual Mode:"));
// Draw sliders
drawSlider(20, 40, 220, 30, freq1, minF, maxF);
drawSlider(20, 80, 220, 30, freq2, minF, maxF);
drawSlider(20, 120, 220, 30, freq3, minF, maxF);
drawSlider(20, 160, 220, 30, timerDuration, minT, maxT);
mainMenuBtn.initButton(&tft, 303, 15, 30, 30, ILI9341_BLACK, ILI9341_RED, ILI9341_WHITE, "X", 3);
startBtn.initButton(&tft, 160, 218, 120, 40, ILI9341_BLACK, ILI9341_GREEN, ILI9341_WHITE, getStr(lang, "Commencer:", "Start"), 2);
mainMenuBtn.drawButton(false);
startBtn.drawButton(false);
Serial.println("Manual Mode Displayed");
}
void displayGenerate() {
tft.fillScreen(ILI9341_WHITE);
tft.setTextColor(ILI9341_BLACK);
tft.setTextSize(3);
tft.setCursor(10, 10);
tft.print(getStr(lang, "Fonctionnement...", "Working..."));
mainMenuBtn.initButton(&tft, 303, 15, 30, 30, ILI9341_BLACK, ILI9341_RED, ILI9341_WHITE, "X", 3);
mainMenuBtn.drawButton(false);
Serial.println("Generating Displayed");
}
void handleTouch(int x, int y) {
if (!debounce()) return;
if (screen == "select_lang") {
if (FrBtn.contains(x, y)) {
FrBtn.press(true);
} else if (EnBtn.contains(x, y)) {
EnBtn.press(true);
} else {
FrBtn.press(false);
EnBtn.press(false);
}
if (FrBtn.justPressed()) {
lang = "fr";
Serial.println("French Selected");
screen = "select_mt_st";
displaySelectMT_ST();
x = 0; y = 0;
} else if (EnBtn.justPressed()) {
lang = "en";
Serial.println("English Selected");
screen = "select_mt_st";
displaySelectMT_ST();
x = 0; y = 0;
}
}
if (screen == "select_mt_st") {
if (MTBtn.contains(x, y)) {
MTBtn.press(true);
} else if (STBtn.contains(x, y)) {
STBtn.press(true);
} else {
MTBtn.press(false);
STBtn.press(false);
}
if (MTBtn.justPressed()) {
mt_st = "MT";
minF = 1; // Minimum frequency
maxF = 100; // Maximum frequency
freq1 = 10;
freq2 = 10;
freq3 = 10;
Serial.println("MT Selected");
screen = "mode_select";
displayMainMenu();
x = 0; y = 0;
} else if (STBtn.justPressed()) {
mt_st = "ST";
minF = 1000; // Minimum frequency
maxF = 3000; // Maximum frequency
freq1 = 1000;
freq2 = 1000;
freq3 = 1000;
Serial.println("ST Selected");
screen = "mode_select";
displayMainMenu();
x = 0; y = 0;
}
}
if (screen == "mode_select") {
if (autoModeBtn.contains(x, y)) {
autoModeBtn.press(true);
} else if (manualModeBtn.contains(x, y)) {
manualModeBtn.press(true);
} else {
autoModeBtn.press(false);
manualModeBtn.press(false);
}
if (autoModeBtn.justPressed()) {
mode = "auto";
screen = "auto_mode";
Serial.println("Auto Mode Selected");
displayAutoMode();
x = 0; y = 0;
} else if (manualModeBtn.justPressed()) {
mode = "manual";
screen = "manual_mode";
Serial.println("Manual Mode Selected");
displayManualMode();
x = 0; y = 0;
}
}
if (screen == "auto_mode") {
BackToMainMenu(x, y);
if (prevBtn.contains(x, y)) {
prevBtn.press(true);
} else if (nextBtn.contains(x, y)) {
nextBtn.press(true);
} else if (startBtn.contains(x, y)) {
startBtn.press(true);
} else {
prevBtn.press(false);
nextBtn.press(false);
startBtn.press(false);
}
if (prevBtn.justPressed()) {
prevBtn.press(false);
Serial.println("<<");
if (currentDiseaseIndex > 0){
currentDiseaseIndex--;
SetConfig();
}
Serial.println(currentDiseaseIndex);
x = 0; y = 0;
} else if (nextBtn.justPressed()) {
nextBtn.press(false);
Serial.println(">>");
if (currentDiseaseIndex < NumDiseases - 1){
currentDiseaseIndex++;
SetConfig();
}
Serial.println(currentDiseaseIndex);
x = 0; y = 0;
} else if (startBtn.justPressed()) {
startBtn.press(false);
Serial.println("Start Generating...");
screen = "generating";
displayGenerate();
x = 0; y = 0;
}
}
if (screen == "manual_mode") {
BackToMainMenu(x, y);
if (startBtn.contains(x, y)) {
startBtn.press(true);
} else {
startBtn.press(false);
}
if (startBtn.justPressed()) {
startBtn.press(false);
Serial.println("Start Generating...");
screen = "generating";
displayGenerate();
x = 0; y = 0;
}
// Handle slider movement
handleSliderTouch(x, y);
}
if (screen == "generating") {
generateFrequencies();
}
}
void drawSlider(int x, int y, int w, int h, int value, int minValue, int maxValue) {
int knobX = map(value, minValue, maxValue, x, x + w);
tft.fillRect(x, y, w, h, ILI9341_LIGHTGREY);
drawSliderKnob(knobX, y + h / 2, ILI9341_BLUE);
updateSliderLabels(freq1, freq2, freq3, timerDuration);
}
void clearSlider(int x, int y, int w, int h) {
tft.fillRect(x, y, w, h, ILI9341_WHITE);
}
void drawSliderKnob(int x, int y, uint16_t color) {
tft.fillRect(x - 5, y - 10, 10, 20, color);
}
void handleSliderTouch(int x, int y) {
// Define the positions and dimensions of the sliders
const int sliderX = 20;
const int sliderWidth = 220;
// Only process if x is within the slider range
if (x >= sliderX && x <= sliderX + sliderWidth) {
if (y > 40 && y < 70) { // First slider (freq1)
freq1 = map(x, sliderX, sliderX + sliderWidth, minF, maxF);
clearSlider(sliderX, 40, sliderWidth, 30);
drawSlider(sliderX, 40, sliderWidth, 30, freq1, minF, maxF);
Serial.print("Frequency 1: ");
Serial.println(freq1);
} else if (y > 80 && y < 110) { // Second slider (freq2)
freq2 = map(x, sliderX, sliderX + sliderWidth, minF, maxF);
clearSlider(sliderX, 80, sliderWidth, 30);
drawSlider(sliderX, 80, sliderWidth, 30, freq2, minF, maxF);
Serial.print("Frequency 2: ");
Serial.println(freq2);
} else if (y > 120 && y < 150) { // Third slider (freq3)
freq3 = map(x, sliderX, sliderX + sliderWidth, minF, maxF);
clearSlider(sliderX, 120, sliderWidth, 30);
drawSlider(sliderX, 120, sliderWidth, 30, freq3, minF, maxF);
Serial.print("Frequency 3: ");
Serial.println(freq3);
} else if (y > 160 && y < 190) { // Fourth slider (timerDuration)
timerDuration = map(x, sliderX, sliderX + sliderWidth, minT, maxT);
clearSlider(sliderX, 160, sliderWidth, 30);
drawSlider(sliderX, 160, sliderWidth, 30, timerDuration, minT, maxT);
Serial.print("Timer Duration: ");
Serial.println(timerDuration);
}
}
}
// Function to update slider labels with units (Hz for frequencies, min for timer)
void updateSliderLabels(int freq1, int freq2, int freq3, int timerDuration) {
tft.setTextColor(ILI9341_BLACK);
tft.setTextSize(1);
// Clear previous labels
tft.fillRect(labelX, labelY1 - 10, 90, 20, ILI9341_WHITE);
tft.fillRect(labelX, labelY2 - 10, 90, 20, ILI9341_WHITE);
tft.fillRect(labelX, labelY3 - 10, 90, 20, ILI9341_WHITE);
tft.fillRect(labelX, labelY4 - 10, 90, 20, ILI9341_WHITE);
// Draw updated labels with units
tft.setCursor(labelX, labelY1);
tft.print("F1:");
tft.print(freq1);
tft.print(" Hz");
tft.setCursor(labelX, labelY2);
tft.print("F2:");
tft.print(freq2);
tft.print(" Hz");
tft.setCursor(labelX, labelY3);
tft.print("F3:");
tft.print(freq3);
tft.print(" Hz");
tft.setCursor(labelX, labelY4);
tft.print("T:");
tft.print(timerDuration);
tft.print(" min");
}
char* getStr(String language, char* FR, char* EN) {
if (language == "en") {
return EN;
} else if (language == "fr") {
return FR;
}
}
void(* resetFunc) (void) = 0; // Declare reset function at address 0
void BackToMainMenu(int x, int y) {
if (mainMenuBtn.contains(x, y)) {
mainMenuBtn.press(true);
} else {
mainMenuBtn.press(false);
}
if (mainMenuBtn.justPressed()) {
resetFunc();
}
}
void DiseaseLabel(char* ch){
tft.fillRect(0, 100, 320, 50, ILI9341_WHITE);
tft.setTextColor(ILI9341_BLACK);
tft.setTextSize(2);
tft.setCursor(10, 100);
tft.print(ch);
}
void SetConfig(){
DiseaseLabel(getStr(lang,diseasesFR[currentDiseaseIndex],diseasesEN[currentDiseaseIndex]));
timerDuration = timers[currentDiseaseIndex];
if(mt_st == "MT"){
freq1 = frequenciesMT[currentDiseaseIndex][0];
freq2 = frequenciesMT[currentDiseaseIndex][1];
freq3 = frequenciesMT[currentDiseaseIndex][2];
} else if(mt_st == "ST"){
freq1 = frequenciesST[currentDiseaseIndex][0];
freq2 = frequenciesST[currentDiseaseIndex][1];
freq3 = frequenciesST[currentDiseaseIndex][2];
}
}
void generateFrequencies() {
unsigned long startTime = millis();
unsigned long endTime = startTime + timerDuration * 60000;
unsigned long interval = 12000; // 12 seconds
unsigned long lastChange = startTime;
int currentFreq = freq1;
while (millis() < endTime) {
if (ts.touched()) {
TS_Point p = ts.getPoint();
BackToMainMenu(320 - p.y, p.x);
}
updateTimeDisplay(endTime - millis());
if (millis() - lastChange >= interval) {
if (currentFreq == freq1) {
currentFreq = freq2;
} else if (currentFreq == freq2) {
currentFreq = freq3;
} else {
currentFreq = freq1;
}
lastChange = millis();
}
tone(tonePin, currentFreq);
delay(100); // Keep the loop responsive
}
noTone(tonePin);
resetFunc();
}
void updateTimeDisplay(unsigned long timeRemaining) {
int minutes = timeRemaining / 60000;
int seconds = (timeRemaining % 60000) / 1000;
tft.fillRect(20, 140, 300, 20, ILI9341_WHITE); // Clear previous text
tft.setCursor(20, 140);
tft.setTextColor(ILI9341_BLACK); // Set text color
tft.setTextSize(2); // Set text size
tft.print(getStr(lang, "Temps restant: ", "Remaining time: "));
tft.print(minutes);
tft.print(":");
if (seconds < 10) tft.print("0");
tft.print(seconds);
}