From 918843da109814e9fd15c71861b38155e7644905 Mon Sep 17 00:00:00 2001
From: Caril Martinez <caril.martinez@cti.espol.edu.ec>
Date: Mon, 7 Oct 2024 21:17:11 +0000
Subject: [PATCH] Upload New File

---
 firmware/nest_main.ino | 347 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 347 insertions(+)
 create mode 100644 firmware/nest_main.ino

diff --git a/firmware/nest_main.ino b/firmware/nest_main.ino
new file mode 100644
index 0000000..c1d00a0
--- /dev/null
+++ b/firmware/nest_main.ino
@@ -0,0 +1,347 @@
+#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("  -");
+    }
+  }
+}
+
+
+
-- 
GitLab