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
Fork of 541-pacemaker by
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 00024 TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD16x2); 00025 RawSerial pc(USBTX, USBRX); 00026 00027 Timer vClock; 00028 Timer aClock; //PaceSignal model 00029 Timer arpClock; 00030 00031 //RtosTimer *apace_timer; 00032 //RtosTimer *vpace_timer; 00033 //RtosTimer *vpace_timer2; 00034 00035 double LRI = 1000; 00036 double URI = 700; 00037 double VRP = 200; // V noise interval 00038 double ARP = 50; // A noise interval 00039 double AVI = 150; // A-V max interval 00040 double PVARP = 300; // V-A max interval 00041 double ratio; 00042 int wait_period = 10; // 3a requirement 00043 00044 int observation_interval = 10000; // In miliseconds 00045 int upperBound; //for mode changes 00046 int lowerBound; //for mode changes 00047 int heart_beats = 0; // Heart-Beats (sensed or paced) since the last observation interval 00048 char mode = 'n'; 00049 char key = 'n'; 00050 char newObsInt[8]; 00051 int manual_mode = 0; 00052 Mutex hr_mutex; //hr_mutex.lock()/unlock() 00053 00054 Queue<char,256> mode_q; 00055 Queue<char,256> signal_q; 00056 Queue<char,256> obsint_q; 00057 00058 volatile char c; 00059 volatile int mm = 0; 00060 volatile int om = 0; 00061 int mm_flag = 0; 00062 00063 void initialize_intervals() 00064 { 00065 LRI = 1000; 00066 URI = 700; 00067 // VRP = 200; 00068 // ARP = 50; 00069 // AVI = 150; 00070 // PVARP = 300; 00071 } 00072 00073 void Rx_interrupt() 00074 { 00075 while(pc.readable()) { 00076 c = pc.getc(); 00077 if(c == 'm' && om != 1) { 00078 mode_q.put((char*)c); 00079 mm = 1; 00080 } else if(c == 'n' || c == 'e' || c == 's' && om != 1) { 00081 mode_q.put((char*)c); 00082 mm = 0; 00083 } else if((c == 'a' || c == 'v') && mm) { 00084 signal_q.put((char*)c); 00085 } else if(c == 'o' && om != 1) { 00086 mode_q.put((char*)c); 00087 om = 1; 00088 } else if (c == '\r' && om) { 00089 obsint_q.put((char*)c); 00090 om = 0; 00091 } else if ((int)c > 47 && (int)c < 58 && om) { 00092 obsint_q.put((char*)c); 00093 } 00094 } 00095 } 00096 00097 // Function to toggle the LEDs 1,2,3,4 00098 void toggleLed(int led) 00099 { 00100 switch (led) { 00101 case (1): 00102 asense_led = 1; 00103 Thread::wait(wait_period); 00104 asense_led = 0; 00105 break; 00106 case (2): 00107 vsense_led = 1; 00108 Thread::wait(wait_period); 00109 vsense_led = 0; 00110 break; 00111 case (3): 00112 apace_led = 1; 00113 Thread::wait(wait_period); 00114 apace_led = 0; 00115 break; 00116 case (4): 00117 vpace_led = 1; 00118 Thread::wait(wait_period); 00119 vpace_led = 0; 00120 break; 00121 } 00122 } 00123 00124 void alarmThread(void const *args) 00125 { 00126 while (1) { 00127 osEvent ext_signal = osSignalWait(0, osWaitForever); 00128 int evt = ext_signal.value.signals; 00129 00130 if (evt == 0xb) { 00131 lcd.printf("%s", "\nALARM HIGH"); 00132 } else if (evt == 0xc) { 00133 lcd.printf("%s", "\nALARM LOW"); 00134 } 00135 } 00136 } 00137 00138 void displayThread(void const *args) 00139 { 00140 while (1) { 00141 Thread::wait(observation_interval); 00142 lcd.cls(); 00143 00144 hr_mutex.lock(); 00145 int hr = (heart_beats*60) / (observation_interval / 1000); 00146 heart_beats = 0; 00147 hr_mutex.unlock(); 00148 00149 lcd.printf("%s%d%s","HR: ", hr, " bpm"); 00150 00151 if (hr > upperBound) { 00152 osSignalSet(alarmTid, 0xb); 00153 } else if (hr < lowerBound) { 00154 osSignalSet(alarmTid, 0xc); 00155 } 00156 } 00157 } 00158 00159 00160 00161 // Incoming signal from the heart 00162 void asignal_irq() 00163 { 00164 osSignalSet(signalTid, 0x1); 00165 } 00166 00167 // Incoming signal from the heart 00168 void vsignal_irq() 00169 { 00170 osSignalSet(signalTid, 0x2); 00171 } 00172 00173 00174 // Timer-driven function to pace the Atrial 00175 void a_pace(void const*) 00176 { 00177 Apace = 1; 00178 Thread::wait(1); 00179 aClock.reset(); 00180 arpClock.reset(); 00181 Apace = 0; 00182 osSignalSet(signalTid, 0x3); 00183 toggleLed(3); 00184 } 00185 00186 // Timer-driven function to pace the ventrical 00187 void v_pace(void const*) 00188 { 00189 hr_mutex.lock(); 00190 osSignalSet(signalTid, 0x4); 00191 heart_beats++; 00192 vClock.reset(); 00193 aClock.reset(); 00194 arpClock.reset(); 00195 hr_mutex.unlock(); 00196 00197 toggleLed(4); 00198 } 00199 00200 00201 00202 void PaceSignal(void const *args) 00203 { 00204 int pFlag1 = 0; 00205 int pFlag2 = 0; 00206 vClock.start(); 00207 aClock.start(); 00208 arpClock.start(); 00209 00210 while(1) { 00211 while (!pFlag1) { 00212 osEvent ext_signal = osSignalWait(0, osWaitForever); 00213 int evt = ext_signal.value.signals; 00214 00215 if (evt == 0x1 && vClock.read_ms() >= PVARP) { //aSense 00216 osSignalSet(senseTid, 0x1); 00217 aClock.reset(); 00218 arpClock.reset(); 00219 pFlag1 = 1; 00220 } else if(evt == 0x2 && vClock.read_ms() >= VRP) { //vSense 00221 pc.printf("%d VSense\n", vClock.read_ms()); 00222 hr_mutex.lock(); 00223 osSignalSet(senseTid, 0x2); 00224 heart_beats++; 00225 vClock.reset(); 00226 aClock.reset(); 00227 arpClock.reset(); 00228 hr_mutex.unlock(); 00229 pFlag1 = 1; 00230 00231 } else if (evt == 0x3) { //aPace 00232 pFlag1 = 1; 00233 } 00234 } 00235 pFlag1 = 0; 00236 while(!pFlag2) { 00237 00238 osEvent ext_signal = osSignalWait(0, osWaitForever); 00239 int evt = ext_signal.value.signals; 00240 00241 if (evt == 0x1 && arpClock.read_ms() >= ARP) { //aSense 00242 osSignalSet(senseTid, 0x1); 00243 arpClock.reset(); 00244 00245 } else if(evt == 0x2) { //vSense 00246 hr_mutex.lock(); 00247 osSignalSet(senseTid, 0x2); 00248 heart_beats++; 00249 vClock.reset(); 00250 aClock.reset(); 00251 arpClock.reset(); 00252 hr_mutex.unlock(); 00253 pFlag2 = 1; 00254 } else if (evt == 0x4) { //vPace 00255 pc.printf("%d VPace\n", vClock.read_ms()); 00256 pFlag2 = 1; 00257 } 00258 } 00259 pFlag2 = 0; 00260 } 00261 } 00262 00263 00264 void PaceSense(void const *args) 00265 { 00266 int interval; 00267 int pFlag1 = 0; 00268 int pFlag2 = 0; 00269 int time_sub = 0; 00270 int evt = 0; 00271 while(1) { 00272 while (!pFlag1) { 00273 00274 time_sub = LRI-AVI - vClock.read_ms(); 00275 00276 if (time_sub > 0 && !mm_flag) { 00277 osEvent ext_signal = osSignalWait(0, time_sub); 00278 evt = ext_signal.value.signals; 00279 } else if(mm_flag) { 00280 osEvent ext_signal = osSignalWait(0, osWaitForever); 00281 evt = ext_signal.value.signals; 00282 } else { 00283 evt = 0x0; 00284 } 00285 00286 if (evt == 0x0) { //aPace 0x0 00287 aClock.reset(); 00288 arpClock.reset(); 00289 Apace = 1; 00290 Thread::wait(1); 00291 Apace = 0; 00292 osSignalSet(signalTid, 0x3); 00293 00294 toggleLed(3); 00295 interval = AVI; 00296 pFlag1 = 1; 00297 } else if (evt == 0x1) { //aSense 00298 if(!mm_flag) { 00299 interval = (vClock.read_ms() + AVI >= URI) ? AVI : URI; 00300 time_sub = interval; 00301 } 00302 toggleLed(1); 00303 pFlag1 = 1; 00304 } else if(evt == 0x2) { //vSense 00305 toggleLed(2); 00306 } else if(evt == 0x3) { //apace 00307 pFlag1 = 1; 00308 } 00309 } 00310 pFlag1 = 0; 00311 00312 while(!pFlag2) { 00313 time_sub = (interval == AVI) ? AVI - aClock.read_ms() : URI - vClock.read_ms(); 00314 00315 if (time_sub > 0 && !mm_flag) { 00316 osEvent ext_signal = osSignalWait(0, time_sub); 00317 evt = ext_signal.value.signals; 00318 } else if(mm_flag) { 00319 osEvent ext_signal = osSignalWait(0, osWaitForever); 00320 evt = ext_signal.value.signals; 00321 } else { 00322 evt = 0x0; 00323 } 00324 00325 if (evt == 0x0) { //vPace 0x0 00326 00327 hr_mutex.lock(); 00328 heart_beats++; 00329 vClock.reset(); 00330 aClock.reset(); 00331 arpClock.reset(); 00332 Vpace = 1; 00333 Thread::wait(1); 00334 Vpace = 0; 00335 osSignalSet(signalTid, 0x4); 00336 hr_mutex.unlock(); 00337 00338 toggleLed(4); 00339 pFlag2 = 1; 00340 00341 } else if (evt == 0x1) { //aSense 00342 toggleLed(1); 00343 } else if(evt == 0x2) { //vSense 00344 toggleLed(2); 00345 pFlag2 = 1; 00346 } else if (evt == 0x4) { //vpace 00347 pFlag2 = 1; 00348 } 00349 } 00350 pFlag2 = 0; 00351 } 00352 } 00353 00354 void normalmode(void const *args) 00355 { 00356 initialize_intervals(); 00357 mode = 'n'; 00358 lcd.printf("N"); 00359 upperBound = 100; //beats per msecond 00360 lowerBound = 40; //beats per msecond 00361 //reset obs interval 00362 hr_mutex.lock(); 00363 heart_beats = 0; 00364 hr_mutex.unlock(); 00365 00366 vClock.reset(); 00367 aClock.reset(); 00368 // vpace_timer->start(LRI); 00369 // apace_timer->start(LRI-AVI); 00370 } 00371 00372 void exercisemode(void const *args) 00373 { 00374 initialize_intervals(); 00375 mode = 'e'; 00376 lcd.printf("E"); 00377 upperBound = 175; //beats per msecond 00378 lowerBound = 100; //beats per msecond 00379 ratio = (175.00/100.00 + 100.00/40.00) / 2.00; 00380 LRI /= ratio; 00381 URI /= ratio; 00382 //reset obs interval 00383 hr_mutex.lock(); 00384 heart_beats = 0; 00385 hr_mutex.unlock(); 00386 00387 vClock.reset(); 00388 aClock.reset(); 00389 // vpace_timer->start(LRI); 00390 // apace_timer->start(LRI-AVI); 00391 } 00392 00393 void sleepmode(void const *args) 00394 { 00395 initialize_intervals(); 00396 mode = 's'; 00397 lcd.printf("S"); 00398 upperBound = 60; //beats per msecond 00399 lowerBound = 30; //beats per msecond v-v 0.5s 00400 ratio = (60.00/100.00 + 30.00/40.00) / 2.00; 00401 LRI /= ratio; 00402 URI /= ratio; 00403 //reset obs interval 00404 hr_mutex.lock(); 00405 heart_beats = 0; 00406 hr_mutex.unlock(); 00407 00408 vClock.reset(); 00409 aClock.reset(); 00410 // vpace_timer->start(LRI); 00411 // apace_timer->start(LRI-AVI); 00412 } 00413 00414 void m_vpace() 00415 { 00416 vClock.reset(); 00417 aClock.reset(); 00418 arpClock.reset(); 00419 Vpace = 1; 00420 Thread::wait(1); 00421 Vpace = 0; 00422 osSignalSet(signalTid, 0x4); 00423 osSignalSet(senseTid, 0x4); 00424 hr_mutex.lock(); 00425 heart_beats++; 00426 hr_mutex.unlock(); 00427 00428 toggleLed(4); 00429 } 00430 00431 void m_apace() 00432 { 00433 aClock.reset(); 00434 arpClock.reset(); 00435 Apace = 1; 00436 Thread::wait(1); 00437 Apace = 0; 00438 osSignalSet(senseTid, 0x3); 00439 osSignalSet(signalTid, 0x3); 00440 toggleLed(3); 00441 } 00442 00443 void manualmode(void const *args) 00444 { 00445 upperBound = 175; //beats per msecond 00446 lowerBound = 30; //beats per msecond 00447 lcd.printf("M"); 00448 mode = 'm'; 00449 LRI = 2125; // max V-V (LRI) based on exercise mode 00450 URI = 675; // min V-V (URI) based on sleep mode 00451 00452 while(1) { 00453 osEvent evt = signal_q.get(); 00454 if(evt.status == osEventMessage) { 00455 if((char)evt.value.p == 'v') { 00456 m_vpace(); 00457 } else if((char)evt.value.p == 'a') { 00458 m_apace(); 00459 } 00460 } 00461 } 00462 } 00463 00464 void obsinterval() 00465 { 00466 char newObsInt[8]; 00467 int isChangingObsInt = 1; 00468 int i = 0; 00469 while(isChangingObsInt) { 00470 osEvent evt = obsint_q.get(); 00471 if(evt.status == osEventMessage) { 00472 key = (char)evt.value.p; 00473 if(key != '\r' && i < 7 ) { 00474 newObsInt[i] = key; 00475 i++; 00476 } else if((key == '\r') && (i > 0)) { 00477 heart_beats = 0; 00478 int obsint; 00479 newObsInt[i] = '\0'; 00480 sscanf(newObsInt, "%d", &obsint); 00481 observation_interval = (obsint > 0 ) ? obsint: 1; 00482 isChangingObsInt = 0; 00483 lcd.printf("%d", observation_interval); 00484 } 00485 } 00486 } 00487 } 00488 00489 osThreadDef(PaceSignal, osPriorityNormal, DEFAULT_STACK_SIZE); 00490 osThreadDef(PaceSense, osPriorityNormal, DEFAULT_STACK_SIZE); 00491 osThreadDef(alarmThread, osPriorityBelowNormal, DEFAULT_STACK_SIZE); //priority BelowNormal 00492 00493 osThreadDef(displayThread, osPriorityLow, DEFAULT_STACK_SIZE); //priority Low 00494 osThreadDef(manualmode, osPriorityNormal, DEFAULT_STACK_SIZE); 00495 //osThreadDef(normalmode, osPriorityNormal, DEFAULT_STACK_SIZE); 00496 //osThreadDef(exercisemode, osPriorityNormal, DEFAULT_STACK_SIZE); 00497 //osThreadDef(sleepmode, osPriorityNormal, DEFAULT_STACK_SIZE); 00498 00499 00500 //////////////////////////////////////////// 00501 //////////////////////////////////////////// 00502 //////////////////////////////////////////// 00503 00504 int main() 00505 { 00506 alarmTid = osThreadCreate(osThread(alarmThread), NULL); 00507 senseTid = osThreadCreate(osThread(PaceSense), NULL); 00508 signalTid = osThreadCreate(osThread(PaceSignal), NULL); 00509 displayTid = osThreadCreate(osThread(displayThread), NULL); 00510 // pacemodeTid = osThreadCreate(osThread(normalmode), NULL); 00511 normalmode(NULL); 00512 00513 vsignal.rise(&vsignal_irq); //rising edge of timer 00514 asignal.rise(&asignal_irq); 00515 00516 // Callback<void()> apaceTimerTask((void*)NULL, (void (*)(void*))&a_pace); 00517 // Callback<void()> vpaceTimerTask((void*)NULL, (void (*)(void*))&v_pace); 00518 // apace_timer = new RtosTimer(apaceTimerTask); 00519 // vpace_timer = new RtosTimer(vpaceTimerTask); 00520 00521 lcd.cls(); 00522 00523 pc.attach(&Rx_interrupt, RawSerial::RxIrq); 00524 while(true) { 00525 // lcd.printf("test1"); 00526 osEvent evt = mode_q.get(); 00527 if(evt.status == osEventMessage) { 00528 switch((char)evt.value.p) { 00529 case('n'): 00530 mm_flag = 0; 00531 osSignalSet(senseTid, 0x5); 00532 lcd.printf("paceN"); 00533 osThreadTerminate (pacemodeTid); 00534 osThreadTerminate (displayTid); 00535 // pacemodeTid = osThreadCreate(osThread(normalmode), NULL); 00536 normalmode(NULL); 00537 displayTid = osThreadCreate(osThread(displayThread), NULL); 00538 lcd.printf("%d", observation_interval); 00539 break; 00540 case('s'): 00541 mm_flag = 0; 00542 osSignalSet(senseTid, 0x5); 00543 lcd.printf("paceS"); 00544 osThreadTerminate (pacemodeTid); 00545 osThreadTerminate (displayTid); 00546 // pacemodeTid = osThreadCreate(osThread(sleepmode), NULL); 00547 sleepmode(NULL); 00548 displayTid = osThreadCreate(osThread(displayThread), NULL); 00549 break; 00550 case('e'): 00551 mm_flag = 0; 00552 osSignalSet(senseTid, 0x5); 00553 lcd.printf("paceE"); 00554 osThreadTerminate (pacemodeTid); 00555 osThreadTerminate (displayTid); 00556 // pacemodeTid = osThreadCreate(osThread(exercisemode), NULL); 00557 exercisemode(NULL); 00558 displayTid = osThreadCreate(osThread(displayThread), NULL); 00559 lcd.printf("%d", observation_interval); 00560 break; 00561 case('m'): 00562 mm_flag = 1; 00563 osThreadTerminate (pacemodeTid); 00564 //osThreadTerminate (displayTid); 00565 // apace_timer->stop(); 00566 // vpace_timer->stop(); 00567 pacemodeTid = osThreadCreate(osThread(manualmode), NULL); 00568 // displayTid = osThreadCreate(osThread(displayThread), NULL); 00569 manual_mode = 1; 00570 break; 00571 case('o'): 00572 lcd.printf("modeO"); 00573 hr_mutex.lock(); 00574 obsinterval(); 00575 hr_mutex.unlock(); 00576 osThreadTerminate (displayTid); 00577 displayTid = osThreadCreate(osThread(displayThread), NULL); 00578 break; 00579 } 00580 } 00581 } 00582 }
Generated on Fri Oct 28 2022 19:38:50 by
1.7.2
