Eric Stahl / Mbed 2 deprecated 541-pacemaker

Dependencies:   TextLCD mbed-rtos mbed

Fork of 541-pacemaker by Terry Fang

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }