Terry Fang / Mbed 2 deprecated 541-pacemaker

Dependencies:   TextLCD mbed-rtos mbed

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 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 }