yay!

Dependencies:   TextLCD mbed-rtos mbed

Fork of 541_Pacermaker by CIS541

main.cpp

Committer:
adamvan101
Date:
2015-12-02
Revision:
4:8e3dc7e73627
Parent:
3:2ed03f9e0042
Child:
6:a1a3e73d90f3

File content as of revision 4:8e3dc7e73627:

#include "PacemakerLibrary.h"
#include "TextLCD.h"

TextLCD lcd(p15,p16,p17,p18,p19,p20);

void incrementHeartRate() {
    heartRateMutex.lock();
    heartRate++;
    heartRateMutex.unlock();
}

void setVSignal(bool state) {
    VMutex.lock();        
    waitVSignal = state;
    VMutex.unlock();
}

void setASignal(bool state) {
    AMutex.lock();        
    waitASignal = state;
    AMutex.unlock();   
}

void setTimeConstraint(int i) {
    timeConstraintMutex.lock();
    timeConstraint = i;
    timeConstraintMutex.unlock();    
}

void printToLCD() {
    displayMutex.lock();
//    pc.printf("%04d\r\n", avgHeartRate);
//    pc.printf("%02d\r\n", pacemakerIntervalInMs/1000);
//    pc.printf("%04d\r\n", (heartRateHeart*(60/sec)));
    lcd.cls(); 
    lcd.locate(0,0);
    lcd.printf("Rate: %.2f BPM", avgHeartRate);
    lcd.locate(0,1);
    switch(pacemakerMode)
    {
        default:
        case NORMAL:
        {
            lcd.printf("NORMAL");
            break;
        }
        case EXERCISE:
        {
            lcd.printf("EXERCISE");
            break;
        }
        case SLEEP:
        {
            lcd.printf("SLEEP (ZZZ)");
            break;
        }
        case MANUAL:
        {
            lcd.printf("MANUAL");
            break;
        }
    }    
    displayMutex.unlock();
}

void println(const char *c) {
    pc.printf(c);
    pc.printf("\r\n");
}

void switchToNormal() {
    LRI = normalModeLRI;
    AVI = normalModeAVI;
    PVARP = normalModePVARP;
    URI = normalModeURI;
    VRP = normalModeVRP;
    PVAB = normalModePVAB;
}

void switchToExercise() {
    LRI = exerciseModeLRI;
    AVI = exerciseModeAVI;
    PVARP = exerciseModePVARP;
    URI = exerciseModeURI;
    VRP = exerciseModeVRP;
    PVAB = exerciseModePVAB;
}

void switchToSleep() {
    LRI = sleepModeLRI;
    AVI = sleepModeAVI;
    PVARP = sleepModePVARP;
    URI = sleepModeURI;
    VRP = sleepModeVRP;
    PVAB = sleepModePVAB;
}

void changeMode()
{
    switch(pacemakerMode)
    {
        default:
        case NORMAL:
        {
            switchToNormal();
            break;
        }
        case EXERCISE:
        {
            switchToExercise();
            break;
        }
        case SLEEP:
        {
            switchToSleep();
            break;
        }
        case MANUAL:
        {
            break;
        }
    }    
    changePacemakerMode=false;
}

void pacemakerModeSwitch(const void *args)
{
    while(1)
    {
        Thread::signal_wait(signal3);
        if(changePacemakerMode)
        {
            changeMode();
        }
    }
}
            
void aSense()
{
    if(waitASignal)
    {
        asenseLED=1;
        wait(0.001);
//        pc.printf("ASense Received at %d ms\r\n", globalTimer.read_ms());
        asenseLED=0; 
        if(changePacemakerMode)
        {
            (*P_PacemakerModeSwitch).signal_set(signal3);
        }
        ASenseReceived=true;
        (*P_PacemakerReceive).signal_set(signal4);
    }    
}

void vSense()
{
    if(waitVSignal)
    {
        vsenseLED=1;
//        pc.printf("VSense Received at %d ms\r\n", globalTimer.read_ms());
        wait(0.001);
        vsenseLED=0;
        if(changePacemakerMode)
        {
            (*P_PacemakerModeSwitch).signal_set(signal3);
        }
        waitVPace=false;
        ASenseReceived=false;
        (*P_PacemakerReceive).signal_set(signal4);
    }
}

void timeConstraintTimeout(const void *args)
{
    if(timeConstraint==AVI_const)
    {
        //trigger vpace
        if(waitVPace)
        {
            APace=false;
            (*P_PacemakerSend).signal_set(signal1);
        }
        else
        {
            waitVPace=true;
        }
    }
    else if(timeConstraint==PVAB_const)
    {
        setVSignal(true);
        setTimeConstraint(AVI_const);
        TimeConstTimerOn=true;
        TimeConstTimer->start(AVI-PVAB);
    }
    else if(timeConstraint==VRP_const)
    {
        setVSignal(true);
        setTimeConstraint(PVARP_const);;
        TimeConstTimerOn=true;
        TimeConstTimer->start(PVARP-VRP);
    }
    else if(timeConstraint==PVARP_const)
    {
        setASignal(true);
        setTimeConstraint(LRI_const);
        TimeConstTimerOn=true;
        TimeConstTimer->start(LRI-PVARP-AVI);
    }
    else if(timeConstraint==LRI_const)
    {
        //trigger apace
        APace=true;
        (*P_PacemakerSend).signal_set(signal1);
    }
}

void atrialEventTimeout(const void *args)
{
    if(VPaceNotReceived || waitVPace)
    {
        APace=false;
        VPaceNotReceived=false;
        (*P_PacemakerSend).signal_set(signal1);
    }
    else
    {
        waitVPace=true;
    }
}   

void pacemakerReceive(const void *args)
{
    while(1)
    {
        Thread::signal_wait(signal4);
        if(TimeConstTimerOn)
        {
            TimeConstTimer->stop();
            TimeConstTimerOn=false;
        }
        if(ASenseReceived)
        {
            setASignal(false);
            setVSignal(true);
            TimeConstTimerOn=true;
            setTimeConstraint(AVI_const);
            TimeConstTimer->start(AVI);
        }
        else
        {
            incrementHeartRate();
            setVSignal(false);
            setASignal(false);
            waitVPace=false;
            AtrialEventTimer->start(URI);
            TimeConstTimerOn=true;
            setTimeConstraint(VRP_const);
            TimeConstTimer->start(VRP);
        }
    }
}
        
void pacemakerSend(const void *args)
{
    while(1)
    {
        Thread::signal_wait(signal1);
        if(APace)
        {
            pc.printf("APace Sent at %d ms\r\n", globalTimer.read_ms());
            apaceLED=1;
            aPace=1;
            Thread::wait(1);
            aPace=0;
            apaceLED=0;
            if(changePacemakerMode)
            {
                changeMode();
            }

            setASignal(false);
            setVSignal(false);
            setTimeConstraint(PVAB_const);
            if (pacemakerMode != MANUAL) {
                TimeConstTimerOn=true;
                TimeConstTimer->start(PVAB);
            }
        }
        else
        {
            pc.printf("VPace Sent at %d ms\r\n", globalTimer.read_ms());
            vpaceLED=1;
            vPace=1;
            Thread::wait(1);
            vPace=0;
            vpaceLED=0;
            if(changePacemakerMode)
            {
                changeMode();
            }

            setVSignal(false);
            setASignal(false);
            incrementHeartRate();
            waitVPace=false;
            AtrialEventTimer->start(URI);
            setTimeConstraint(VRP_const);
            TimeConstTimerOn=true;
            if (pacemakerMode != MANUAL) {
                TimeConstTimerOn=true;
                TimeConstTimer->start(VRP);
            }
        }
    }
}

void readInt() {
    char c = pc.getc();
    int input = c-48;
    c = pc.getc();
    while (c != '\r') {
        input *= 10;
        input += c-48;
        c = pc.getc();      
    }

    if (input >= 10 && input <= 90) {
        pacemakerInterval=input;
        pacemakerIntervalInMs = pacemakerInterval*1000;
        displayTimer.reset();
        heartRateMutex.lock();
        heartRate=0;
        heartRateMutex.unlock();
        pc.printf("Obs Int Changed: %d\r\n", pacemakerInterval);     
    } else {
        pc.printf("Bad Obs Int: %d\r\n", input);     
    }
}

void pacemakerKeyboard(const void *args)
{
    while(1)
    {
        Thread::signal_wait(signal2);
        if (char_read == 'a' && pacemakerMode == MANUAL)
        {
            APace=true;
            (*P_PacemakerSend).signal_set(signal1);
        }
        else if (char_read == 'v' && pacemakerMode == MANUAL)
        {
            if(waitVPace)
            {
                APace=false;
                VPaceNotReceived=false;
                (*P_PacemakerSend).signal_set(signal1);
            }
            else
            {
                VPaceNotReceived=true;
            }
        }
        else if (char_read == 'n' && pacemakerMode != NORMAL && !changePacemakerMode)
        {
            if (pacemakerMode == MANUAL) {
                // restart A/V timers
                TimeConstTimerOn=true;
                TimeConstTimer->start(VRP);    
            }
            pacemakerMode=NORMAL;
            changePacemakerMode=true;
        }
        else if (char_read == 'e' && pacemakerMode != EXERCISE && !changePacemakerMode)
        {
            if (pacemakerMode == MANUAL) {
                // restart A/V timers
                TimeConstTimer->start(VRP);    
            }
            pacemakerMode=EXERCISE;
            changePacemakerMode=true;
        }
        else if (char_read == 's' && pacemakerMode != SLEEP && !changePacemakerMode)
        {
            if (pacemakerMode == MANUAL) {
                // restart A/V timers
                TimeConstTimer->start(VRP);    
            }
            pacemakerMode=SLEEP;
            changePacemakerMode=true;
        }
        else if (char_read == 'm' && pacemakerMode != MANUAL && !changePacemakerMode)
        {
            pacemakerMode=MANUAL;
            changePacemakerMode=true;
        }
        else if (char_read == 'o' && !changePacemakerMode)
        {
            // blocks, reading characters, until "return" is pressed
            observationMutex.lock();
            readInt();
            observationMutex.unlock();
        }                
    }
}

void pacemakerAlarm(const void *args)
{
    while(1)
    {
        Thread::signal_wait(signal5);
        while(avgHeartRate > (60000/URI))
        {
            buzzer=1;
            Thread::wait(5);
            buzzer=0;
            Thread::wait(5);
            if(!alarmPrinted)
            {
                displayMutex.lock();
                println("!!!***Alarm High***!!!");
                displayMutex.unlock();
                alarmPrinted=true;
            }
        }
        while(avgHeartRate < (60000/LRI))
        {
            buzzer=1;
            Thread::wait(10);
            buzzer=0;
            Thread::wait(10);
            if(!alarmPrinted)
            {
                displayMutex.lock();
                println("!!!***Alarm Low***!!!");
                displayMutex.unlock();
                alarmPrinted=true;
            }
        }
        if(alarmPrinted)
        {
            alarmPrinted=false;
//            resetDisplay();
        }
    }
}

void display(const void *args)
{
    displayTimer.start();
    
    while(1)
    {
        observationMutex.lock();
        if (displayTimer.read_ms() >= pacemakerIntervalInMs) {
            displayTimer.reset();
            printToLCD();
            avgHeartRate=heartRate*(60.0/pacemakerInterval);
            heartRateMutex.lock();
            heartRate=0;
            heartRateMutex.unlock();
            observationMutex.unlock();
            (*P_PacemakerAlarm).signal_set(signal5);
        } else {
            printToLCD();
            observationMutex.unlock();
            Thread::wait(100);
        }   
    }
}

int main() 
{    
    setVSignal(true);
    setVSignal(true);
    switchToNormal();
    
    ASignal.rise(&aSense);
    VSignal.rise(&vSense);
    
    TimeConstTimer = new RtosTimer(timeConstraintTimeout, osTimerOnce, (void*)0);
    AtrialEventTimer = new RtosTimer(atrialEventTimeout, osTimerOnce, (void *)0);
    
    Thread PacemakerSend(pacemakerSend);
    P_PacemakerSend=&PacemakerSend;
    PacemakerSend.set_priority(osPriorityHigh);
    
    Thread PacemakerReceive(pacemakerReceive);
    P_PacemakerReceive=&PacemakerReceive;
    PacemakerReceive.set_priority(osPriorityAboveNormal);
    
    Thread PacemakerModeSwitch(pacemakerModeSwitch);
    P_PacemakerModeSwitch=&PacemakerModeSwitch;
    PacemakerModeSwitch.set_priority(osPriorityAboveNormal);
    
    Thread PacemakerKeyboard(pacemakerKeyboard);
    P_PacemakerKeyboard=&PacemakerKeyboard;
    PacemakerKeyboard.set_priority(osPriorityRealtime);
    
    Thread Display(display);
    Display.set_priority(osPriorityAboveNormal);
    
    Thread PacemakerAlarm(pacemakerAlarm);
    P_PacemakerAlarm = &PacemakerAlarm;
    PacemakerAlarm.set_priority(osPriorityAboveNormal);
    
    setTimeConstraint(VRP_const);
    TimeConstTimer->start(VRP);
    
    globalTimer.start();
    
    while(1) {
        if(pc.readable())
        {
            char_read = pc.getc();
            (*P_PacemakerKeyboard).signal_set(signal2);
        }
    }
}