Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: TextLCD mbed-rtos mbed
main.cpp
00001 #include "mbed.h" 00002 #include "rtos.h" 00003 #include "TextLCD.h" 00004 #include <stdio.h> 00005 00006 InterruptIn vsignal(p7); 00007 InterruptIn asignal(p8); 00008 DigitalOut Vpace(p5); 00009 DigitalOut Apace(p6); 00010 00011 DigitalOut asense_led(LED1); 00012 DigitalOut vsense_led(LED2); 00013 DigitalOut apace_led(LED3); 00014 DigitalOut vpace_led(LED4); 00015 00016 Thread *pacemodeThread; 00017 00018 osThreadId signalTid; 00019 osThreadId senseTid; 00020 osThreadId displayTid; 00021 osThreadId pacemodeTid; 00022 osThreadId alarmTid; 00023 osThreadId ledTid; 00024 00025 TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD16x2); 00026 RawSerial pc(USBTX, USBRX); 00027 00028 Timer vClock; 00029 Timer aClock; //PaceSignal model 00030 Timer arpClock; 00031 00032 double LRI = 1000; 00033 double URI = 700; 00034 double VRP = 200; // V noise interval 00035 double ARP = 50; // A noise interval 00036 double AVI = 150; // A-V max interval 00037 double PVARP = 300; // V-A max interval 00038 double ratio; 00039 int wait_period = 10; // 3a requirement 00040 00041 double observation_interval = 10000; // In miliseconds 00042 int upperBound; //for mode changes 00043 int lowerBound; //for mode changes 00044 double heart_beats = 0; // Heart-Beats (sensed or paced) since the last observation interval 00045 char mode = 'n'; 00046 char key = 'n'; 00047 char newObsInt[8]; 00048 int manual_mode = 0; 00049 Mutex hr_mutex; //hr_mutex.lock()/unlock() 00050 00051 Queue<char,256> mode_q; 00052 Queue<char,256> signal_q; 00053 Queue<char,256> obsint_q; 00054 00055 volatile char c; 00056 volatile int mm = 0; 00057 volatile int om = 0; 00058 int mm_flag = 0; 00059 00060 void initialize_intervals() 00061 { 00062 LRI = 1000; 00063 URI = 700; 00064 } 00065 00066 void Rx_interrupt() 00067 { 00068 while(pc.readable()) { 00069 c = pc.getc(); 00070 if(c == 'm' && om != 1) { 00071 mode_q.put((char*)c); 00072 mm = 1; 00073 } else if(c == 'n' || c == 'e' || c == 's' && om != 1) { 00074 mode_q.put((char*)c); 00075 mm = 0; 00076 } else if((c == 'a' || c == 'v') && mm) { 00077 signal_q.put((char*)c); 00078 } else if(c == 'o' && om != 1) { 00079 mode_q.put((char*)c); 00080 om = 1; 00081 } else if (c == '\r' && om) { 00082 obsint_q.put((char*)c); 00083 om = 0; 00084 } else if ((int)c > 47 && (int)c < 58 && om) { 00085 obsint_q.put((char*)c); 00086 } 00087 } 00088 } 00089 00090 // Function to toggle the LEDs 1,2,3,4 00091 void ledThread(void const *args) 00092 00093 { 00094 while (1) { 00095 osEvent ext_signal = osSignalWait(0, osWaitForever); 00096 int evt = ext_signal.value.signals; 00097 00098 if (evt == 0xA) { 00099 asense_led = 1; 00100 Thread::wait(wait_period); 00101 asense_led = 0; 00102 } else if (evt == 0xB) { 00103 vsense_led = 1; 00104 Thread::wait(wait_period); 00105 vsense_led = 0; 00106 } else if (evt == 0xC) { 00107 apace_led = 1; 00108 Thread::wait(wait_period); 00109 apace_led = 0; 00110 } else if (evt == 0xD) { 00111 vpace_led = 1; 00112 Thread::wait(wait_period); 00113 vpace_led = 0; 00114 } 00115 } 00116 } 00117 00118 void alarmThread(void const *args) 00119 { 00120 while (1) { 00121 osEvent ext_signal = osSignalWait(0, osWaitForever); 00122 int evt = ext_signal.value.signals; 00123 00124 if (evt == 0xb) { 00125 lcd.printf("%s", "\nALARM HIGH"); 00126 } else if (evt == 0xc) { 00127 lcd.printf("%s", "\nALARM LOW"); 00128 } 00129 } 00130 } 00131 00132 void displayThread(void const *args) 00133 { 00134 while (1) { 00135 Thread::wait(observation_interval); 00136 lcd.cls(); 00137 00138 hr_mutex.lock(); 00139 double hr = (heart_beats*60) / (observation_interval / 1000); 00140 heart_beats = 0; 00141 hr_mutex.unlock(); 00142 00143 lcd.printf("%s%d%s","HR: ", (int)hr, " bpm"); 00144 00145 if (hr > upperBound) { 00146 osSignalSet(alarmTid, 0xb); 00147 } else if (hr < lowerBound) { 00148 osSignalSet(alarmTid, 0xc); 00149 } 00150 } 00151 } 00152 00153 00154 00155 // Incoming signal from the heart 00156 void asignal_irq() 00157 { 00158 osSignalSet(signalTid, 0x1); 00159 } 00160 00161 // Incoming signal from the heart 00162 void vsignal_irq() 00163 { 00164 osSignalSet(signalTid, 0x2); 00165 } 00166 00167 00168 void PaceSignal(void const *args) 00169 { 00170 int pFlag1 = 0; 00171 int pFlag2 = 0; 00172 vClock.start(); 00173 aClock.start(); 00174 arpClock.start(); 00175 00176 while(1) { 00177 while (!pFlag1) { 00178 osEvent ext_signal = osSignalWait(0, osWaitForever); 00179 int evt = ext_signal.value.signals; 00180 00181 if (evt == 0x1 && vClock.read_ms() >= PVARP) { //aSense 00182 osSignalSet(senseTid, 0x1); 00183 aClock.reset(); 00184 arpClock.reset(); 00185 pFlag1 = 1; 00186 } else if(evt == 0x2 && vClock.read_ms() >= VRP) { //vSense 00187 hr_mutex.lock(); 00188 osSignalSet(senseTid, 0x2); 00189 heart_beats++; 00190 vClock.reset(); 00191 aClock.reset(); 00192 arpClock.reset(); 00193 hr_mutex.unlock(); 00194 pFlag1 = 1; 00195 00196 } else if (evt == 0x3) { //aPace 00197 pFlag1 = 1; 00198 } 00199 } 00200 pFlag1 = 0; 00201 while(!pFlag2) { 00202 00203 osEvent ext_signal = osSignalWait(0, osWaitForever); 00204 int evt = ext_signal.value.signals; 00205 00206 if (evt == 0x1 && arpClock.read_ms() >= ARP) { //aSense 00207 osSignalSet(senseTid, 0x1); 00208 arpClock.reset(); 00209 00210 } else if(evt == 0x2) { //vSense 00211 hr_mutex.lock(); 00212 osSignalSet(senseTid, 0x2); 00213 heart_beats++; 00214 vClock.reset(); 00215 aClock.reset(); 00216 arpClock.reset(); 00217 hr_mutex.unlock(); 00218 pFlag2 = 1; 00219 } else if (evt == 0x4) { //vPace 00220 pFlag2 = 1; 00221 } 00222 } 00223 pFlag2 = 0; 00224 } 00225 } 00226 00227 void PaceSense(void const *args) 00228 { 00229 int interval; 00230 int pFlag1 = 0; 00231 int pFlag2 = 0; 00232 int time_sub = 0; 00233 int evt = 0; 00234 while(1) { 00235 while (!pFlag1) { 00236 00237 time_sub = LRI-AVI - vClock.read_ms(); 00238 00239 if (time_sub > 0 && !mm_flag) { 00240 osEvent ext_signal = osSignalWait(0, time_sub); 00241 evt = ext_signal.value.signals; 00242 } else if(mm_flag) { 00243 osEvent ext_signal = osSignalWait(0, osWaitForever); 00244 evt = ext_signal.value.signals; 00245 } else { 00246 evt = 0x0; 00247 } 00248 00249 if (evt == 0x0) { //aPace 0x0 00250 aClock.reset(); 00251 arpClock.reset(); 00252 Apace = 1; 00253 Thread::wait(1); 00254 Apace = 0; 00255 osSignalSet(signalTid, 0x3); 00256 osSignalSet(ledTid, 0xC); 00257 00258 interval = AVI; 00259 pFlag1 = 1; 00260 } else if (evt == 0x1) { //aSense 00261 if(!mm_flag) { 00262 interval = (vClock.read_ms() + AVI >= URI) ? AVI : URI; 00263 time_sub = interval; 00264 } 00265 osSignalSet(ledTid, 0xA); 00266 pFlag1 = 1; 00267 } else if(evt == 0x2) { //vSense 00268 osSignalSet(ledTid, 0xB); 00269 } else if(evt == 0x3) { //apace 00270 pFlag1 = 1; 00271 } 00272 } 00273 pFlag1 = 0; 00274 00275 while(!pFlag2) { 00276 time_sub = (interval == AVI) ? AVI - aClock.read_ms() : URI - vClock.read_ms(); 00277 00278 if (time_sub > 0 && !mm_flag) { 00279 osEvent ext_signal = osSignalWait(0, time_sub); 00280 evt = ext_signal.value.signals; 00281 } else if(mm_flag) { 00282 osEvent ext_signal = osSignalWait(0, osWaitForever); 00283 evt = ext_signal.value.signals; 00284 } else { 00285 evt = 0x0; 00286 } 00287 00288 if (evt == 0x0) { //vPace 0x0 00289 00290 hr_mutex.lock(); 00291 heart_beats++; 00292 vClock.reset(); 00293 aClock.reset(); 00294 arpClock.reset(); 00295 Vpace = 1; 00296 Thread::wait(1); 00297 Vpace = 0; 00298 osSignalSet(signalTid, 0x4); 00299 hr_mutex.unlock(); 00300 00301 osSignalSet(ledTid, 0xD); 00302 pFlag2 = 1; 00303 00304 } else if (evt == 0x1) { //aSense 00305 osSignalSet(ledTid, 0xA); 00306 } else if(evt == 0x2) { //vSense 00307 osSignalSet(ledTid, 0xB); 00308 pFlag2 = 1; 00309 } else if (evt == 0x4) { //vpace 00310 pFlag2 = 1; 00311 } 00312 } 00313 pFlag2 = 0; 00314 } 00315 } 00316 00317 void normalmode(void const *args) 00318 { 00319 initialize_intervals(); 00320 mode = 'n'; 00321 upperBound = 100; //beats per msecond 00322 lowerBound = 40; //beats per msecond 00323 hr_mutex.lock(); 00324 heart_beats = 0; 00325 hr_mutex.unlock(); 00326 00327 vClock.reset(); 00328 aClock.reset(); 00329 } 00330 00331 void exercisemode(void const *args) 00332 { 00333 initialize_intervals(); 00334 mode = 'e'; 00335 upperBound = 175; //beats per msecond 00336 lowerBound = 100; //beats per msecond 00337 ratio = (175.00/100.00 + 100.00/40.00) / 2.00; 00338 LRI /= ratio; 00339 URI /= ratio; 00340 //reset obs interval 00341 hr_mutex.lock(); 00342 heart_beats = 0; 00343 hr_mutex.unlock(); 00344 00345 vClock.reset(); 00346 aClock.reset(); 00347 } 00348 00349 void sleepmode(void const *args) 00350 { 00351 initialize_intervals(); 00352 mode = 's'; 00353 upperBound = 60; //beats per msecond 00354 lowerBound = 30; //beats per msecond v-v 0.5s 00355 ratio = (60.00/100.00 + 30.00/40.00) / 2.00; 00356 LRI /= ratio; 00357 URI /= ratio; 00358 hr_mutex.lock(); 00359 heart_beats = 0; 00360 hr_mutex.unlock(); 00361 00362 vClock.reset(); 00363 aClock.reset(); 00364 } 00365 00366 void m_vpace() 00367 { 00368 vClock.reset(); 00369 aClock.reset(); 00370 arpClock.reset(); 00371 Vpace = 1; 00372 Thread::wait(1); 00373 Vpace = 0; 00374 osSignalSet(signalTid, 0x4); 00375 osSignalSet(senseTid, 0x4); 00376 hr_mutex.lock(); 00377 heart_beats++; 00378 hr_mutex.unlock(); 00379 00380 osSignalSet(ledTid, 0xD); 00381 } 00382 00383 void m_apace() 00384 { 00385 aClock.reset(); 00386 arpClock.reset(); 00387 Apace = 1; 00388 Thread::wait(1); 00389 Apace = 0; 00390 osSignalSet(senseTid, 0x3); 00391 osSignalSet(signalTid, 0x3); 00392 osSignalSet(ledTid, 0xC); 00393 } 00394 00395 void manualmode(void const *args) 00396 { 00397 upperBound = 175; //beats per msecond 00398 lowerBound = 30; //beats per msecond 00399 mode = 'm'; 00400 LRI = 2125; // max V-V (LRI) based on exercise mode 00401 URI = 675; // min V-V (URI) based on sleep mode 00402 00403 while(1) { 00404 osEvent evt = signal_q.get(); 00405 if(evt.status == osEventMessage) { 00406 if((char)evt.value.p == 'v') { 00407 m_vpace(); 00408 } else if((char)evt.value.p == 'a') { 00409 m_apace(); 00410 } 00411 } 00412 } 00413 } 00414 00415 void obsinterval() 00416 { 00417 char newObsInt[8]; 00418 int isChangingObsInt = 1; 00419 int i = 0; 00420 while(isChangingObsInt) { 00421 osEvent evt = obsint_q.get(); 00422 if(evt.status == osEventMessage) { 00423 key = (char)evt.value.p; 00424 if(key != '\r' && i < 7 ) { 00425 newObsInt[i] = key; 00426 i++; 00427 } else if((key == '\r') && (i > 0)) { 00428 heart_beats = 0; 00429 int obsint; 00430 newObsInt[i] = '\0'; 00431 sscanf(newObsInt, "%d", &obsint); 00432 00433 if(obsint < 300) { 00434 observation_interval = 300.0; 00435 } else if (obsint > 10000) { 00436 observation_interval = 10000.0; 00437 } else { 00438 observation_interval = (double)obsint; 00439 } 00440 isChangingObsInt = 0; 00441 00442 } 00443 } 00444 } 00445 } 00446 00447 osThreadDef(PaceSignal, osPriorityNormal, DEFAULT_STACK_SIZE); 00448 osThreadDef(PaceSense, osPriorityNormal, DEFAULT_STACK_SIZE); 00449 osThreadDef(alarmThread, osPriorityBelowNormal, DEFAULT_STACK_SIZE); //priority BelowNormal 00450 osThreadDef(ledThread, osPriorityBelowNormal, DEFAULT_STACK_SIZE); 00451 00452 osThreadDef(displayThread, osPriorityLow, DEFAULT_STACK_SIZE); //priority Low 00453 osThreadDef(manualmode, osPriorityNormal, DEFAULT_STACK_SIZE); 00454 00455 int main() 00456 { 00457 alarmTid = osThreadCreate(osThread(alarmThread), NULL); 00458 senseTid = osThreadCreate(osThread(PaceSense), NULL); 00459 signalTid = osThreadCreate(osThread(PaceSignal), NULL); 00460 displayTid = osThreadCreate(osThread(displayThread), NULL); 00461 ledTid = osThreadCreate(osThread(ledThread), NULL); 00462 00463 normalmode(NULL); 00464 00465 vsignal.rise(&vsignal_irq); //rising edge of timer 00466 asignal.rise(&asignal_irq); 00467 00468 lcd.cls(); 00469 00470 pc.attach(&Rx_interrupt, RawSerial::RxIrq); 00471 while(true) { 00472 osEvent evt = mode_q.get(); 00473 if(evt.status == osEventMessage) { 00474 switch((char)evt.value.p) { 00475 case('n'): 00476 mm_flag = 0; 00477 osSignalSet(senseTid, 0x5); 00478 osThreadTerminate (pacemodeTid); 00479 osThreadTerminate (displayTid); 00480 normalmode(NULL); 00481 displayTid = osThreadCreate(osThread(displayThread), NULL); 00482 break; 00483 case('s'): 00484 mm_flag = 0; 00485 osSignalSet(senseTid, 0x5); 00486 osThreadTerminate (pacemodeTid); 00487 osThreadTerminate (displayTid); 00488 sleepmode(NULL); 00489 displayTid = osThreadCreate(osThread(displayThread), NULL); 00490 break; 00491 case('e'): 00492 mm_flag = 0; 00493 osSignalSet(senseTid, 0x5); 00494 osThreadTerminate (pacemodeTid); 00495 osThreadTerminate (displayTid); 00496 exercisemode(NULL); 00497 displayTid = osThreadCreate(osThread(displayThread), NULL); 00498 break; 00499 case('m'): 00500 mm_flag = 1; 00501 osThreadTerminate (pacemodeTid); 00502 pacemodeTid = osThreadCreate(osThread(manualmode), NULL); 00503 manual_mode = 1; 00504 break; 00505 case('o'): 00506 obsinterval(); 00507 osThreadTerminate (displayTid); 00508 displayTid = osThreadCreate(osThread(displayThread), NULL); 00509 break; 00510 } 00511 } 00512 } 00513 }
Generated on Fri Dec 2 2022 10:41:01 by
1.7.2