From 2f471aeae61da6e67da4e86ed9aa13891b48a005 Mon Sep 17 00:00:00 2001
From: Caril <caril.martinez@cti.espol.edu.ec>
Date: Mon, 28 Oct 2024 16:21:05 -0500
Subject: [PATCH] Updates

---
 firmware/nest_main.ino           | 347 -------------------------------
 firmware/nest_main/nest_main.ino | 233 +++++++++++++++++++++
 2 files changed, 233 insertions(+), 347 deletions(-)
 delete mode 100644 firmware/nest_main.ino
 create mode 100644 firmware/nest_main/nest_main.ino

diff --git a/firmware/nest_main.ino b/firmware/nest_main.ino
deleted file mode 100644
index c1d00a0..0000000
--- a/firmware/nest_main.ino
+++ /dev/null
@@ -1,347 +0,0 @@
-#include <Adafruit_TinyUSB.h>
-#include <SPI.h>
-#include "Ucglib.h"
-#include <TouchScreen.h>
-#include <bluefruit.h>
-#include "algorithm_by_RF.h"
-#include "max30102.h"
-
-#define TFT_CS     33
-#define TFT_RST    2
-#define TFT_DC     25
-#define TFT_MOSI   24
-#define TFT_SCLK   26
-#define LIGHT_PIN  10
-#define OXI_INT    18
-
-Ucglib_ST7735_18x128x160_HWSPI ucg(TFT_DC, TFT_CS, TFT_RST);
-
-// Touchscreen pins
-#define YP A6
-#define XM A2
-#define YM A0
-#define XP A7
-#define TS_MINX 150
-#define TS_MINY 120
-#define TS_MAXX 920
-#define TS_MAXY 940
-TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
-
-// Global variables for the screen state
-enum Screen { MAIN_MENU, RESCUE_CONFIRM, SENDING_DATA, SURVEY_SENT, HEART_RATE };
-Screen currentScreen = MAIN_MENU;
-
-int currentBpm = -1;  // Initialized to -1 to indicate no valid value yet
-uint32_t elapsedTime, timeStart;
-
-uint32_t aun_ir_buffer[BUFFER_SIZE]; // Infrared LED sensor data
-uint32_t aun_red_buffer[BUFFER_SIZE];  // Red LED sensor data
-float old_n_spo2;  // Previous SPO2 value
-uint8_t uch_dummy, k;
-
-// Define UUIDs for the service and characteristic
-#define SERVICE_UUID   "12345678-1234-5678-1234-56789abcdef0"
-#define CHARACTERISTIC_UUID "abcdef12-3456-7890-1234-56789abcdef1"
-BLEService customService(SERVICE_UUID);
-BLECharacteristic alertCharacteristic(CHARACTERISTIC_UUID);
-
-void setup(void) {
-
-  pinMode(OXI_INT, INPUT);  // pin 18 connects to the interrupt output pin of the MAX30102
-
-  Serial.begin(115200);
-  while (!Serial); // Wait for the serial port to be ready for debugging
-
-  maxim_max30102_init();  // Initialize the MAX30102
-  old_n_spo2 = 0.0;
-
-  pinMode(LIGHT_PIN, OUTPUT);
-  analogWrite(LIGHT_PIN, 255);
-  ucg.begin(UCG_FONT_MODE_TRANSPARENT);
-  ucg.clearScreen();
-  setupBLE();  // Initialize BLE configuration
-  drawInterface(); // Initially draw the main screen
-}
-
-void loop(void) {
-  bool isTouched = checkTouch();  // This returns true if the screen was touched
-
-  if (currentScreen == HEART_RATE && !isTouched) {
-    updateHeartRate();  // Only update if we are on the heart rate screen and no touch was detected
-  }
-
-  delay(100);  // Small delay to avoid too fast refreshing
-}
-
-void setupBLE() {
-  Bluefruit.begin();
-  Bluefruit.Periph.setConnectCallback(connect_callback);
-  Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
-  Bluefruit.setName("NEST Device");
-
-  // Initialize the service
-  customService.begin();
-
-  // Initialize the characteristic
-  alertCharacteristic.setProperties(CHR_PROPS_NOTIFY);
-  alertCharacteristic.setPermission(SECMODE_OPEN, SECMODE_NO_ACCESS);
-  alertCharacteristic.setFixedLen(20);
-  alertCharacteristic.begin();
-
-  startAdvertising();
-}
-
-void startAdvertising() {
-  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
-  Bluefruit.Advertising.addTxPower();
-  Bluefruit.Advertising.addService(customService);
-  Bluefruit.Advertising.addName();
-  Bluefruit.Advertising.start(0); // 0 for continuous advertising
-}
-
-void connect_callback(uint16_t conn_handle) {
-  Serial.println("Device Connected!");
-}
-
-void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
-  Serial.println("Device Disconnected!");
-}
-
-void drawInterface() {
-  currentScreen = MAIN_MENU;
-  ucg.clearScreen();
-  ucg.setColor(255, 255, 255); // White
-  ucg.setFont(ucg_font_ncenR12_tr);
-  ucg.setPrintPos(10, 15);
-  ucg.print("NEST - OS");
-
-  drawButton(5, 30, 118, 36, "Pain Diary", 0x2104);
-  drawButton(5, 75, 118, 36, "Rescue", 0x2104);
-  drawButton(5, 120, 118, 36, "Monitoring", 0x2104);
-}
-
-void drawRescueConfirmationScreen() {
-  currentScreen = RESCUE_CONFIRM;
-  ucg.clearScreen();
-
-  ucg.setColor(255, 255, 255);
-  ucg.setFont(ucg_font_ncenR12_tr);
-  ucg.setPrintPos(10, 20); ucg.print("Are you sure");
-  ucg.setPrintPos(10, 40); ucg.print("you want to");
-  ucg.setPrintPos(10, 60); ucg.print("send data");
-
-  ucg.setColor(255, 0, 0);  // Red for the NO button
-  ucg.drawDisc(40, 100, 20, UCG_DRAW_ALL);
-  ucg.setColor(255, 255, 255); ucg.setPrintPos(34, 107); ucg.print("X");
-
-  // Smaller YES button with a check mark
-  ucg.setColor(0, 0, 255); // Blue
-  ucg.drawDisc(90, 100, 20, UCG_DRAW_ALL); // Reduced diameter
-  ucg.setColor(255, 255, 255); // White
-  
-  // Draw a thicker check mark
-  int baseX = 85, baseY = 98; // Base point for the check
-  // Lines for the lower part of the check
-  ucg.drawLine(baseX, baseY, baseX + 4, baseY + 4);
-  ucg.drawLine(baseX, baseY - 1, baseX + 4, baseY + 3);
-  ucg.drawLine(baseX, baseY + 1, baseX + 4, baseY + 5);
-  // Lines for the upper part of the check
-  ucg.drawLine(baseX + 3, baseY + 3, baseX + 12, baseY - 6);
-  ucg.drawLine(baseX + 3, baseY + 4, baseX + 12, baseY - 5);
-  ucg.drawLine(baseX + 3, baseY + 5, baseX + 12, baseY - 4);
-
-}
-
-void drawSendingDataScreen() {
-  currentScreen = SENDING_DATA;
-  ucg.clearScreen();
-  ucg.setColor(255, 255, 255);
-  ucg.setFont(ucg_font_ncenR14_hr);
-  ucg.setPrintPos(10, 60); ucg.print("Sending");
-  ucg.setPrintPos(10, 80); ucg.print("data...");
-
-  const char* alertMsg = "Data Sent";
-  if (Bluefruit.connected()) {
-    if (alertCharacteristic.notify(alertMsg, strlen(alertMsg))) {
-      Serial.println("Alert sent via BLE");
-    } else {
-      Serial.println("Failed to send notification");
-    }
-  } else {
-    Serial.println("No devices connected.");
-  }
-
-  delay(3000); // Simulate some processing
-  drawSurveySentScreen(); // Call the screen for survey sent
-}
-
-void drawSurveySentScreen() {
-  currentScreen = SURVEY_SENT;  // Set the correct state
-  ucg.clearScreen();
-  ucg.setColor(255, 255, 255);
-  ucg.setFont(ucg_font_ncenR14_hr);
-  ucg.setPrintPos(10, 60);
-  ucg.print("Survey");
-  ucg.setPrintPos(10, 80);
-  ucg.print("Sent");
-}
-
-void drawHeartRateScreen() {
-  currentScreen = HEART_RATE;  // Make sure to add this to the screen enum
-  ucg.clearScreen();  // Clear the screen before drawing the new view
-
-  ucg.setColor(255, 255, 255); // White for the text
-  ucg.setFont(ucg_font_ncenR14_hr); // Large font for the title
-  ucg.setPrintPos(10, 20); // Adjust position as needed
-  ucg.print("Heart");
-  ucg.setPrintPos(10, 35); // Adjust position as needed
-  ucg.print("Rate");
-
-  // Draw a button to go back
-  ucg.setColor(128, 0, 128); // Purple color for the button
-  ucg.drawDisc(20, 80, 15, UCG_DRAW_ALL);
-  ucg.setColor(255, 255, 255); // White for the button icon
-  ucg.setFont(ucg_font_ncenR12_tr); // Change to a smaller font for the icon
-  ucg.setPrintPos(15, 85); // Adjust to center the text in the circle
-  ucg.print("<");
-
-  // Draw the heart rate value
-  ucg.setFont(ucg_font_ncenR24_tr); // Large font for the numbers
-  ucg.setColor(255, 255, 255); // White
-  ucg.setPrintPos(60, 80);  // Adjust as needed
-
-  if (currentBpm >= 0) {
-    ucg.print(currentBpm);  // Show the current BPM value
-  } else {
-    ucg.print("  -");  // Show a dash if BPM is invalid
-  }
-  
-  ucg.setFont(ucg_font_ncenR14_hr); // Smaller font for "BPM"
-  ucg.setPrintPos(60, 100);  // Adjust as needed
-  ucg.print("BPM");
-
-  // Draw a small heart below "BPM"
-  drawHeart(80, 110);  // Adjust coordinates as needed
-}
-
-void drawHeart(int x, int y) {
-  ucg.setColor(255, 0, 0); // Red color for the heart
-  
-  // Draw the top of the heart as two red circles
-  // Make sure the circles slightly overlap the triangle
-  ucg.drawDisc(x - 2, y - 2, 4, UCG_DRAW_UPPER_LEFT); // Adjust position for better blending
-  ucg.drawDisc(x - 2, y - 2, 4, UCG_DRAW_UPPER_RIGHT); // Adjust position for better blending
-  ucg.drawDisc(x + 9, y - 2, 4, UCG_DRAW_UPPER_RIGHT); // Adjust position for better blending
-  ucg.drawDisc(x + 9, y - 2, 4, UCG_DRAW_UPPER_LEFT); // Adjust position for better blending
-
-  // Draw the bottom part of the heart as a triangle
-  ucg.drawTriangle(x - 6, y - 2, x + 14, y - 2, x + 4, y + 8);
-}
-
-bool checkTouch() {
-  TSPoint p = ts.getPoint();
-  pinMode(XM, OUTPUT);
-  pinMode(YP, OUTPUT);
-  bool screenTouched = false;
-
-  if (p.z > ts.pressureThreshhold) {
-    int x = map(p.x, TS_MINX, TS_MAXX, 0, 128);
-    int y = map(p.y, TS_MINY, TS_MAXY, 0, 160);
-    screenTouched = true;  // The screen was touched
-
-    switch(currentScreen) {
-      case MAIN_MENU:
-        if (y > 30 && y < 66) {  // "Pain Diary" button
-          // Implement what should happen if "Pain Diary" is selected
-        } else if (y > 75 && y < 111) {  // "Rescue" button
-          drawRescueConfirmationScreen();
-        } else if (y > 120 && y < 156) {  // "Monitoring" button
-          drawHeartRateScreen();
-        }
-        break;
-
-      case RESCUE_CONFIRM:
-        if (x > 20 && x < 60 && y > 80 && y < 120) { // NO button
-          drawInterface();  // Go back to the main menu
-        } else if (x > 70 && x < 110 && y > 80 && y < 120) { // YES button
-          drawSendingDataScreen();  // Go to "Sending data..."
-        }
-        break;
-
-      case SENDING_DATA:
-        // Hold the screen until any part is touched, then go back to the menu
-        drawInterface();
-        break;
-
-      case SURVEY_SENT:
-        // Return to the main menu with any screen touch
-        drawInterface();
-        break;
-
-      case HEART_RATE:
-        if (x > 20 && x < 60 && y > 80 && y < 120) {  // Back button area on the "Heart Rate" screen
-          drawInterface();  // Go back to the main menu
-        }
-        break;
-
-      default:
-        // You can add more cases if there are more screens
-        break;
-    }
-  }
-  return screenTouched;
-}
-
-void drawButton(int x, int y, int w, int h, const char* text, uint16_t color) {
-  ucg.setColor(255, 255, 255);
-  ucg.drawRBox(x, y, w, h, 5);
-  ucg.setColor(color >> 8, color & 0xFF, color & 0xFF);
-  ucg.drawRBox(x + 2, y + 2, w - 4, h - 4, 5);
-  ucg.setColor(255, 255, 255);
-  ucg.setFont(ucg_font_6x10_tr);
-  int textX = x + (w - ucg.getStrWidth(text)) / 2;
-  int textY = y + h / 2 + 3;
-  ucg.setPrintPos(textX, textY);
-  ucg.print(text);
-}
-
-void updateHeartRate() {
-  static unsigned long lastUpdateTime = 0;  // Save the last time the reading was updated
-  int32_t n_heart_rate; // Variable to store heart rate value
-  int8_t ch_hr_valid;   // Indicator if heart rate reading is valid
-  float n_spo2, ratio, correl;  // Additional variables used in calculation
-  int8_t ch_spo2_valid;  // Validity indicator for oxygen saturation
-  int32_t i;
-
-  for(i = 0; i < BUFFER_SIZE; i++) {
-    while (digitalRead(OXI_INT) == 1);  // Wait until the interrupt pin asserts
-    maxim_max30102_read_fifo((aun_red_buffer + i), (aun_ir_buffer + i));  // Read from MAX30102 FIFO
-  }
-
-  // Calculate heart rate and oxygen saturation
-  rf_heart_rate_and_oxygen_saturation(aun_ir_buffer, BUFFER_SIZE, aun_red_buffer, &n_spo2, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid, &ratio, &correl);
-
-  if (ch_hr_valid) {
-    currentBpm = n_heart_rate;
-  } else {
-    currentBpm = -1;  // If reading is invalid, set to -1
-  }
-
-  if (currentScreen == HEART_RATE) {
-    ucg.setColor(0, 0, 0);  // Assuming the background is black
-    ucg.drawBox(40, 50, 80, 35);  // Adjust dimensions to fully cover the number and text
-
-    ucg.setColor(255, 255, 255);  // White
-    ucg.setFont(ucg_font_ncenR24_tr);
-    ucg.setPrintPos(60, 80);  // Adjust as needed
-
-    if (currentBpm >= 0) {
-      ucg.print(currentBpm);
-    } else {
-      ucg.print("  -");
-    }
-  }
-}
-
-
-
diff --git a/firmware/nest_main/nest_main.ino b/firmware/nest_main/nest_main.ino
new file mode 100644
index 0000000..1fd83ec
--- /dev/null
+++ b/firmware/nest_main/nest_main.ino
@@ -0,0 +1,233 @@
+bool checkTouch() {
+  TSPoint p = ts.getPoint();
+  pinMode(XM, OUTPUT);
+  pinMode(YP, OUTPUT);
+  bool screenTouched = false;
+
+  // Check if screen was touched by pressure threshold
+  if (p.z > ts.pressureThreshhold) {
+    int x = map(p.x, TS_MINX, TS_MAXX, 0, 128);
+    int y = map(p.y, TS_MINY, TS_MAXY, 0, 160);
+    screenTouched = true;
+
+    // Switch case for handling different screens based on the current screen state
+    switch (currentScreen) {
+      case MAIN_MENU:
+        if (y > 30 && y < 66) {  
+          drawPainDiaryScreen();  // Open Pain Diary screen
+        } else if (y > 75 && y < 111) {  
+          drawRescueConfirmationScreen();
+        } else if (y > 120 && y < 156) {  
+          drawHeartRateScreen();
+        }
+        break;
+
+      case PAIN_DIARY:
+        // Select pain intensity level and proceed accordingly
+        if (y > 40 && y < 70) { 
+          Serial.println("Ausencia de dolor seleccionada");
+          selectedPainLevel = 0;  // No pain
+          drawInterface();
+        } else if (y > 80 && y < 110) { 
+          Serial.println("Dolor leve seleccionado");
+          selectedPainLevel = 1;  // Mild pain
+          drawPainDescriptionScreen();  // Proceed to pain description screen
+        } else if (y > 120 && y < 150) {  
+          Serial.println("Dolor moderado seleccionado");
+          selectedPainLevel = 2;  // Moderate pain
+          drawPainDescriptionScreen();
+        } else if (y > 160 && y < 190) {  
+          Serial.println("Dolor severo seleccionado");
+          selectedPainLevel = 3;  // Severe pain
+          drawPainDescriptionScreen();
+        }
+        break;
+
+      case PAIN_DESCRIPTION:
+        // Select type of pain description and proceed to daily limitation screen
+        if (y > 40 && y < 70) { 
+          painDescription = 0;  // Changing intensity
+          drawDailyLimitationScreen();
+        } else if (y > 80 && y < 110) { 
+          painDescription = 1;  // Constant intensity
+          drawDailyLimitationScreen();
+        } else if (y > 120 && y < 150) {  
+          painDescription = 2;  // Stabbing pain
+          drawDailyLimitationScreen();
+        } else if (y > 160 && y < 190) {  
+          painDescription = 3;  // Pain when standing
+          drawDailyLimitationScreen();
+        }
+        break;
+
+      case RESCUE_CONFIRM:
+        // Confirm or cancel rescue operation
+        if (x > 20 && x < 60 && y > 80 && y < 120) { 
+          drawInterface();  
+        } else if (x > 70 && x < 110 && y > 80 && y < 120) {  
+          drawSendingDataScreen();  
+        }
+        break;
+
+      case SENDING_DATA:
+        drawInterface();  // Return to main interface after sending data
+        break;
+
+      case SURVEY_SENT:
+        if (x > 80 && x < 120 && y > 80 && y < 100)
+          drawInterface();
+        break;
+
+      case HEART_RATE:
+        if (x > 20 && x < 60 && y > 80 && y < 120) {  
+          drawInterface();
+        }
+        break;
+
+      case DAILY_LIMITATION:
+        // Select daily limitation level and start HR measurement screen
+        if (y > 40 && y < 70) { 
+          dailyLimitation = 0;  // No limitation
+        } else if (y > 80 && y < 110) { 
+          dailyLimitation = 1;  // Slightly limiting
+        } else if (y > 120 && y < 150) {  
+          dailyLimitation = 2;  // Moderate limitation
+        } else if (y > 160 && y < 190) {  
+          dailyLimitation = 3;  // Total limitation
+        }
+        drawHRMeasurementScreen();  // Proceed to "Measuring HR" screen
+        break;
+
+      case HR_MEASUREMENT:
+        if (x > 20 && x < 60 && y > 80 && y < 120)  {  // Coordinates for purple button
+          goToPreviousScreen();  // Go back to the previous screen
+        }
+        break;
+
+      case HR_ERROR:
+        if (x > 20 && x < 60 && y > 80 && y < 120) {  // Coordinates for purple button in error screen
+          drawHRMeasurementScreen();  // Retry HR measurement screen
+        }
+        break;
+
+      case HR_RESULT:
+        if (x > 20 && x < 60 && y > 80 && y < 120) {  // Left button
+          drawHRMeasurementScreen();  // Return to HR measurement screen
+        } else if (x > 80 && x < 120 && y > 80 && y < 120) {  // Right button
+          drawDataConfirmationScreen();  // Proceed to data confirmation screen
+        }
+        break;
+
+      case DATA_CONFIRMATION:
+        // Confirm or cancel data sending
+        if (x > 20 && x < 60 && y > 80 && y < 120) { 
+          drawInterface();  
+        } else if (x > 70 && x < 110 && y > 80 && y < 120) {  
+          drawDataSendingScreen();  
+        }
+        break;
+
+      default:
+        break;
+    }
+  }
+  return screenTouched;
+}
+
+
+void sendSurveyDataViaBLE() {
+  // Compile survey data and BPM for BLE transmission
+  String dataToSend = "BPM: " + String(currentBpm) + 
+                      ", Intensidad: " + String(selectedPainLevel) + 
+                      ", Descripción: " + String(painDescription) + 
+                      ", Limitación: " + String(dailyLimitation);
+
+  const char* alertMsg = dataToSend.c_str();  // Convert data to BLE-compatible format
+
+  if (Bluefruit.connected()) {
+    // Attempt to send BLE notification with data
+    if (alertCharacteristic.notify(alertMsg, strlen(alertMsg))) {
+      Serial.println("Datos de encuesta enviados vía BLE");
+      drawSurveySentScreen();  // Show "Survey Sent" screen after sending
+    } else {
+      Serial.println("Error al enviar los datos de la encuesta");
+      drawSurveySentScreen();  // Show "Survey Sent" screen after sending
+    }
+  } else {
+    Serial.println("No hay dispositivos conectados.");
+    drawSurveySentScreen();  // Show "Survey Sent" screen after sending
+  }
+}
+
+
+void drawButton(int x, int y, int w, int h, const char* text, uint16_t color) {
+  ucg.setColor(255, 255, 255);  // Draw white border for button
+  ucg.drawRBox(x, y, w, h, 5);
+
+  // Convert RGB565 color to RGB888
+  uint8_t r = (color >> 11) & 0x1F;
+  uint8_t g = (color >> 5) & 0x3F;
+  uint8_t b = color & 0x1F;
+
+  // Scale color values to 0-255
+  r = (r * 255) / 31;
+  g = (g * 255) / 63;
+  b = (b * 255) / 31;
+
+  // Set and draw button color with rounded corners
+  ucg.setColor(r, g, b);
+  ucg.drawRBox(x + 2, y + 2, w - 4, h - 4, 5);
+
+  // Draw button text in white
+  ucg.setColor(255, 255, 255);
+  ucg.setFont(ucg_font_6x10_tr);
+  int textX = x + (w - ucg.getStrWidth(text)) / 2;
+  int textY = y + h / 2 + 3;
+  ucg.setPrintPos(textX, textY);
+  ucg.print(text);
+}
+
+
+void updateHeartRate() {
+  static unsigned long lastUpdateTime = 0;  
+  int32_t n_heart_rate; 
+  int8_t ch_hr_valid;   
+  float n_spo2, ratio, correl;  
+  int8_t ch_spo2_valid;  
+  int32_t i;
+
+  // Read data from MAX30102 sensor
+  for (i = 0; i < BUFFER_SIZE; i++) {
+    while (digitalRead(OXI_INT) == 1);  
+    maxim_max30102_read_fifo((aun_red_buffer + i), (aun_ir_buffer + i));  
+  }
+
+  // Process heart rate and oxygen saturation data
+  rf_heart_rate_and_oxygen_saturation(aun_ir_buffer, BUFFER_SIZE, aun_red_buffer, &n_spo2, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid, &ratio, &correl);
+
+  if (ch_hr_valid) {
+    currentBpm = n_heart_rate;
+  } else {
+    currentBpm = -1;  
+  }
+
+  // Update display if on the HEART_RATE screen
+  if (currentScreen == HEART_RATE) {
+    ucg.setColor(0, 0, 0);  // Black to clear previous reading
+    ucg.drawBox(40, 50, 80, 35);  
+
+    ucg.setColor(255, 255, 255);  // White for new BPM reading
+    ucg.setFont(ucg_font_ncenR24_tr);
+    ucg.setPrintPos(60, 80);  
+
+    if (currentBpm >= 0) {
+      ucg.print(currentBpm);  // Display current BPM
+    } else {
+      ucg.print("  -");  // Display dash if BPM is invalid
+    }
+  }
+}
+
+
+
+
-- 
GitLab