latest pacemaker

Dependencies:   TextLCD mbed-rtos mbed

main.cpp

Committer:
terryfan
Date:
2016-12-11
Revision:
4:a9c37c60425c
Parent:
3:77efff091ef1

File content as of revision 4:a9c37c60425c:

#include "mbed.h"
#include "rtos.h"
#include "TextLCD.h"
#include <stdio.h>

InterruptIn vsignal(p7);
InterruptIn asignal(p8);
DigitalOut Vpace(p5);
DigitalOut Apace(p6);

DigitalOut asense_led(LED1);
DigitalOut vsense_led(LED2);
DigitalOut apace_led(LED3);
DigitalOut vpace_led(LED4);

Thread *pacemodeThread;

osThreadId signalTid;
osThreadId senseTid;
osThreadId displayTid;
osThreadId pacemodeTid;
osThreadId alarmTid;
osThreadId ledTid;

TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD16x2);
RawSerial pc(USBTX, USBRX);

Timer vClock;
Timer aClock;               //PaceSignal model
Timer arpClock;

double LRI = 1000;
double URI = 700;
double VRP = 200;                // V noise interval
double ARP = 50;                // A noise interval
double AVI = 150;          // A-V max interval
double PVARP = 300;      // V-A max interval
double ratio;
int wait_period = 10;       // 3a requirement

double observation_interval = 10000; // In miliseconds
int upperBound; //for mode changes
int lowerBound; //for mode changes
double heart_beats = 0; // Heart-Beats (sensed or paced) since the last observation interval
char mode = 'n';
char key = 'n';
char newObsInt[8];
int manual_mode = 0;
Mutex hr_mutex; //hr_mutex.lock()/unlock()

Queue<char,256> mode_q;
Queue<char,256> signal_q;
Queue<char,256> obsint_q;

volatile char c;
volatile int mm = 0;
volatile int om = 0;
int mm_flag = 0;

void initialize_intervals()
{
    LRI = 1000;
    URI = 700;
}

void Rx_interrupt()
{
    while(pc.readable()) {
        c = pc.getc();
        if(c == 'm' && om != 1) {
            mode_q.put((char*)c);
            mm = 1;
        } else if(c == 'n' || c == 'e' || c == 's' && om != 1) {
            mode_q.put((char*)c);
            mm = 0;
        } else if((c == 'a' || c == 'v') && mm) {
            signal_q.put((char*)c);
        } else if(c == 'o' && om != 1) {
            mode_q.put((char*)c);
            om = 1;
        } else if (c == '\r' && om) {
            obsint_q.put((char*)c);
            om = 0;
        } else if ((int)c > 47 && (int)c < 58 && om) {
            obsint_q.put((char*)c);
        }
    }
}

// Function to toggle the LEDs 1,2,3,4
void ledThread(void const *args)

{
    while (1) {
        osEvent ext_signal = osSignalWait(0, osWaitForever);
        int evt = ext_signal.value.signals;

        if (evt == 0xA) {
            asense_led = 1;
            Thread::wait(wait_period);
            asense_led = 0;
        } else if (evt == 0xB) {
            vsense_led = 1;
            Thread::wait(wait_period);
            vsense_led = 0;
        } else if (evt == 0xC) {
            apace_led = 1;
            Thread::wait(wait_period);
            apace_led = 0;
        } else if (evt == 0xD) {
            vpace_led = 1;
            Thread::wait(wait_period);
            vpace_led = 0;
        }
    }
}

void alarmThread(void const *args)
{
    while (1) {
        osEvent ext_signal = osSignalWait(0, osWaitForever);
        int evt = ext_signal.value.signals;

        if (evt == 0xb) {
            lcd.printf("%s", "\nALARM HIGH");
        } else if (evt == 0xc) {
            lcd.printf("%s", "\nALARM LOW");
        }
    }
}

void displayThread(void const *args)
{
    while (1) {
        Thread::wait(observation_interval);
        lcd.cls();

        hr_mutex.lock();
        double hr = (heart_beats*60) / (observation_interval / 1000);
        heart_beats = 0;
        hr_mutex.unlock();

        lcd.printf("%s%d%s","HR: ", (int)hr, " bpm");

        if (hr > upperBound) {
            osSignalSet(alarmTid, 0xb);
        } else if (hr < lowerBound) {
            osSignalSet(alarmTid, 0xc);
        }
    }
}



// Incoming signal from the heart
void asignal_irq()
{
    osSignalSet(signalTid, 0x1);
}

// Incoming signal from the heart
void vsignal_irq()
{
    osSignalSet(signalTid, 0x2);
}


void PaceSignal(void const *args)
{
    int pFlag1 = 0;
    int pFlag2 = 0;
    vClock.start();
    aClock.start();
    arpClock.start();

    while(1) {
        while (!pFlag1) {
            osEvent ext_signal = osSignalWait(0, osWaitForever);
            int evt = ext_signal.value.signals;

            if (evt == 0x1 && vClock.read_ms() >= PVARP) { //aSense
                osSignalSet(senseTid, 0x1);
                aClock.reset();
                arpClock.reset();
                pFlag1 = 1;
            } else if(evt == 0x2 && vClock.read_ms() >= VRP) { //vSense
                hr_mutex.lock();
                osSignalSet(senseTid, 0x2);
                heart_beats++;
                vClock.reset();
                aClock.reset();
                arpClock.reset();
                hr_mutex.unlock();
                pFlag1 = 1;

            } else if (evt == 0x3) { //aPace
                pFlag1 = 1;
            }
        }
        pFlag1 = 0;
        while(!pFlag2) {

            osEvent ext_signal = osSignalWait(0, osWaitForever);
            int evt = ext_signal.value.signals;

            if (evt == 0x1 && arpClock.read_ms() >= ARP) { //aSense
                osSignalSet(senseTid, 0x1);
                arpClock.reset();

            } else if(evt == 0x2) { //vSense
                hr_mutex.lock();
                osSignalSet(senseTid, 0x2);
                heart_beats++;
                vClock.reset();
                aClock.reset();
                arpClock.reset();
                hr_mutex.unlock();
                pFlag2 = 1;
            } else if (evt == 0x4) { //vPace
                pFlag2 = 1;
            }
        }
        pFlag2 = 0;
    }
}

void PaceSense(void const *args)
{
    int interval;
    int pFlag1 = 0;
    int pFlag2 = 0;
    int time_sub = 0;
    int evt = 0;
    while(1) {
        while (!pFlag1) {

            time_sub = LRI-AVI - vClock.read_ms();

            if (time_sub > 0  && !mm_flag) {
                osEvent ext_signal = osSignalWait(0, time_sub);
                evt = ext_signal.value.signals;
            } else if(mm_flag) {
                osEvent ext_signal = osSignalWait(0, osWaitForever);
                evt = ext_signal.value.signals;
            } else {
                evt = 0x0;
            }

            if (evt == 0x0) { //aPace 0x0
                aClock.reset();
                arpClock.reset();
                Apace = 1;
                Thread::wait(1);
                Apace = 0;
                osSignalSet(signalTid, 0x3);
                osSignalSet(ledTid, 0xC);

                interval = AVI;
                pFlag1 = 1;
            } else if (evt == 0x1) { //aSense
                if(!mm_flag) {
                    interval = (vClock.read_ms() + AVI >= URI) ? AVI : URI;
                    time_sub = interval;
                }
                osSignalSet(ledTid, 0xA);
                pFlag1 = 1;
            } else if(evt == 0x2) { //vSense
                osSignalSet(ledTid, 0xB);
            } else if(evt == 0x3) { //apace
                pFlag1 = 1;
            }
        }
        pFlag1 = 0;

        while(!pFlag2) {
            time_sub = (interval == AVI) ? AVI - aClock.read_ms() : URI - vClock.read_ms();

            if (time_sub > 0 && !mm_flag) {
                osEvent ext_signal = osSignalWait(0, time_sub);
                evt = ext_signal.value.signals;
            } else if(mm_flag) {
                osEvent ext_signal = osSignalWait(0, osWaitForever);
                evt = ext_signal.value.signals;
            } else {
                evt = 0x0;
            }

            if (evt == 0x0) { //vPace 0x0

                hr_mutex.lock();
                heart_beats++;
                vClock.reset();
                aClock.reset();
                arpClock.reset();
                Vpace = 1;
                Thread::wait(1);
                Vpace = 0;
                osSignalSet(signalTid, 0x4);
                hr_mutex.unlock();

                osSignalSet(ledTid, 0xD);
                pFlag2 = 1;

            } else if (evt == 0x1) { //aSense
                osSignalSet(ledTid, 0xA);
            } else if(evt == 0x2) { //vSense
                osSignalSet(ledTid, 0xB);
                pFlag2 = 1;
            } else if (evt == 0x4) { //vpace
                pFlag2 = 1;
            }
        }
        pFlag2 = 0;
    }
}

void normalmode(void const *args)
{
    initialize_intervals();
    mode = 'n';
    upperBound = 100; //beats per msecond
    lowerBound = 40; //beats per msecond
    hr_mutex.lock();
    heart_beats = 0;
    hr_mutex.unlock();

    vClock.reset();
    aClock.reset();
}

void exercisemode(void const *args)
{
    initialize_intervals();
    mode = 'e';
    upperBound = 175; //beats per msecond
    lowerBound = 100; //beats per msecond
    ratio = (175.00/100.00 + 100.00/40.00) / 2.00;
    LRI /= ratio;
    URI /= ratio;
    //reset obs interval
    hr_mutex.lock();
    heart_beats = 0;
    hr_mutex.unlock();

    vClock.reset();
    aClock.reset();
}

void sleepmode(void const *args)
{
    initialize_intervals();
    mode = 's';
    upperBound = 60; //beats per msecond
    lowerBound = 30; //beats per msecond v-v 0.5s
    ratio = (60.00/100.00 + 30.00/40.00) / 2.00;
    LRI /= ratio;
    URI /= ratio;
    hr_mutex.lock();
    heart_beats = 0;
    hr_mutex.unlock();

    vClock.reset();
    aClock.reset();
}

void m_vpace()
{
    vClock.reset();
    aClock.reset();
    arpClock.reset();
    Vpace = 1;
    Thread::wait(1);
    Vpace = 0;
    osSignalSet(signalTid, 0x4);
    osSignalSet(senseTid, 0x4);
    hr_mutex.lock();
    heart_beats++;
    hr_mutex.unlock();

    osSignalSet(ledTid, 0xD);
}

void m_apace()
{
    aClock.reset();
    arpClock.reset();
    Apace = 1;
    Thread::wait(1);
    Apace = 0;
    osSignalSet(senseTid, 0x3);
    osSignalSet(signalTid, 0x3);
    osSignalSet(ledTid, 0xC);
}

void manualmode(void const *args)
{
    upperBound = 175; //beats per msecond
    lowerBound = 30; //beats per msecond
    mode = 'm';
    LRI = 2125; // max V-V (LRI) based on exercise mode
    URI = 675; // min V-V (URI) based on sleep mode

    while(1) {
        osEvent evt = signal_q.get();
        if(evt.status == osEventMessage) {
            if((char)evt.value.p == 'v') {
                m_vpace();
            } else if((char)evt.value.p == 'a') {
                m_apace();
            }
        }
    }
}

void obsinterval()
{
    char newObsInt[8];
    int isChangingObsInt = 1;
    int i = 0;
    while(isChangingObsInt) {
        osEvent evt = obsint_q.get();
        if(evt.status == osEventMessage) {
            key = (char)evt.value.p;
            if(key != '\r' && i < 7 ) {
                newObsInt[i] = key;
                i++;
            } else if((key == '\r') && (i > 0)) {
                heart_beats = 0;
                int obsint;
                newObsInt[i] = '\0';
                sscanf(newObsInt, "%d", &obsint);

                if(obsint < 300) {
                    observation_interval = 300.0;
                } else if (obsint > 10000) {
                    observation_interval = 10000.0;
                } else {
                    observation_interval = (double)obsint;
                }
                isChangingObsInt = 0;

            }
        }
    }
}

osThreadDef(PaceSignal, osPriorityNormal, DEFAULT_STACK_SIZE);
osThreadDef(PaceSense, osPriorityNormal, DEFAULT_STACK_SIZE);
osThreadDef(alarmThread, osPriorityBelowNormal, DEFAULT_STACK_SIZE); //priority BelowNormal
osThreadDef(ledThread, osPriorityBelowNormal, DEFAULT_STACK_SIZE);

osThreadDef(displayThread, osPriorityLow, DEFAULT_STACK_SIZE); //priority Low
osThreadDef(manualmode, osPriorityNormal, DEFAULT_STACK_SIZE);

int main()
{
    alarmTid = osThreadCreate(osThread(alarmThread), NULL);
    senseTid = osThreadCreate(osThread(PaceSense), NULL);
    signalTid = osThreadCreate(osThread(PaceSignal), NULL);
    displayTid = osThreadCreate(osThread(displayThread), NULL);
    ledTid = osThreadCreate(osThread(ledThread), NULL);

    normalmode(NULL);

    vsignal.rise(&vsignal_irq); //rising edge of timer
    asignal.rise(&asignal_irq);

    lcd.cls();

    pc.attach(&Rx_interrupt, RawSerial::RxIrq);
    while(true) {
        osEvent evt = mode_q.get();
        if(evt.status == osEventMessage) {
            switch((char)evt.value.p) {
                case('n'):
                    mm_flag = 0;
                    osSignalSet(senseTid, 0x5);
                    osThreadTerminate (pacemodeTid);
                    osThreadTerminate (displayTid);
                    normalmode(NULL);
                    displayTid = osThreadCreate(osThread(displayThread), NULL);
                    break;
                case('s'):
                    mm_flag = 0;
                    osSignalSet(senseTid, 0x5);
                    osThreadTerminate (pacemodeTid);
                    osThreadTerminate (displayTid);
                    sleepmode(NULL);
                    displayTid = osThreadCreate(osThread(displayThread), NULL);
                    break;
                case('e'):
                    mm_flag = 0;
                    osSignalSet(senseTid, 0x5);
                    osThreadTerminate (pacemodeTid);
                    osThreadTerminate (displayTid);
                    exercisemode(NULL);
                    displayTid = osThreadCreate(osThread(displayThread), NULL);
                    break;
                case('m'):
                    mm_flag = 1;
                    osThreadTerminate (pacemodeTid);
                    pacemodeTid = osThreadCreate(osThread(manualmode), NULL);
                    manual_mode = 1;
                    break;
                case('o'):
                    obsinterval();
                    osThreadTerminate (displayTid);
                    displayTid = osThreadCreate(osThread(displayThread), NULL);
                    break;
            }
        }
    }
}