Part of the Pacemaker Project; this models the Pacemaker.

Dependencies:   mbed TextLCD mbed-rtos

PacemakerController.cpp

Committer:
chadnach1
Date:
2015-12-02
Revision:
27:2c5aefcf3000
Parent:
24:81cd9ef5c4f6
Child:
29:5cec671cb80d

File content as of revision 27:2c5aefcf3000:

#include "mbed.h"
#include "LPC17xx.h"
#include "TextLCD.h"
#include "rtos.h"
#include "Thread.h"
using namespace rtos;


// This is for the pacemaker
volatile unsigned short timer_count;
Serial pc(USBTX, USBRX);
TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD20x4); // rs, e, d4-d7

int keyboard_needs_numeric = 0; // boolean - is in middle of interval input?

int h_clock;
int pm_clock;
Timer avi_clk;

int LRI = 1000;
int AVI = 150;
int PVARP = 300;
int VRP = 200;

// constants
int MAX_PM_RT = 180;
int MIN_PM_RT = 40;
enum mode {NORMAL, SLEEP, EXERCISE, MANUAL};

// counters
int beats = 0;

// state variables
int upper_bound = 100;
int lower_bound = 40;
int obs_int = 10;
mode curr_mode = NORMAL;

// alarms
DigitalOut led_apace(LED1);
DigitalOut led_vpace(LED2);
DigitalOut Asense(LED3);
DigitalOut Vsense(LED4);

DigitalIn  agetSignal(p24);
DigitalIn  vgetSignal(p23);
DigitalOut apaceSignal(p22);
DigitalOut vpaceSignal(p21);

bool v_sense;
bool a_sense;

void asense()
{
    a_sense = 1;
    Thread::wait(10);
    a_sense = 0;
}

void vsense()
{
    v_sense = 1;
    Thread::wait(10);
    v_sense = 0;
}

void apace()
{

    apaceSignal = 1;
    led_apace = 1;
    Thread::wait(10);
    apaceSignal = 0;

}

void vpace()
{

    vpaceSignal = 1;
    led_vpace = 1;
    Thread::wait(10);
    vpaceSignal = 0;

}

// hardware interrupt handler, adapted from code in piazza post by Dagaen
extern "C" void TIMER0_IRQHandler (void)
{
    if((LPC_TIM0->IR & 0x01) == 0x01) { // if MR0 interrupt, proceed
        LPC_TIM0->IR |= 1 << 0;         // Clear MR0 interrupt flag
        timer_count++;                  //increment timer_count
    }
}

// init the hardware interrupt (timer0), adapted same as above
void timer0_init(void)
{
    LPC_SC->PCONP |=1<1;            //timer0 power on
    LPC_SC-> PCLKSEL0 |= 1 << 2;    // set timer clock to CCLCK nondivided (1 clock cycle = 1 increment)
    LPC_TIM0->MR0 = 1000000;          //100mhz clock cycle, 1 cycle = 10ns, 10ms = 10 000 000 ns = 1M cycles
    LPC_TIM0->MCR = 3;              //interrupt and reset control
    //3 = Interrupt & reset timer0 on match (111) sets all three bits
    NVIC_EnableIRQ(TIMER0_IRQn);    //enable timer0 interrupt
}


void PM_ALARM(void const *args)
{

    // min hr alarm
    if( beats < MIN_PM_RT) {
        lcd.locate(0,1);
        lcd.printf("!<");
    }

    // max hr alarm
    if(beats > MAX_PM_RT) {
        lcd.locate(0,1);
        lcd.printf("!>");
    }

}

// hw interrupt callback, deal with the keyboard input from PC
void keyboard_handler()
{

    // get the char, put it on the PC command line
    char a = pc.getc();

    if (keyboard_needs_numeric) {
        if (a >= '0' && a <= '9') {
            // update observation interval
            obs_int = (a - '0' + 1) * 5;
        } else {
            pc.printf("Expected numeric key\n");
        }
    } else if(a == 'N') {
        // if the char is N, update bounds to normal mode
        curr_mode = NORMAL;
        upper_bound = 100;
        lower_bound = 40;
        pc.printf("MODE IS N\n");
        // if the char is S, set bounds to sleep
    } else if (a == 'S') {
        curr_mode = SLEEP;
        upper_bound = 60;
        lower_bound = 30;
        pc.printf("MODE IS S\n");
        // if the char is E, set bounds to exercise
    } else if (a == 'E') {
        curr_mode = EXERCISE;
        upper_bound = 175;
        lower_bound = 100;
        pc.printf("MODE IS E\n");
        beats = 2;
        // if the char is M, set to manual
    } else if (a == 'M') {
        curr_mode = MANUAL;
        upper_bound = 175;
        lower_bound = 30;
        beats = 300;
        pc.printf("MODE IS MANUAL\n");
        // check for A if mode is manual
    } else if (a == 'A') {
        if(curr_mode == MANUAL) {
            pc.printf("MODE IS MANUAL GOT APACE\n");
        }
        // check for V is mode is manual
    } else if (a == 'V') {
        if(curr_mode == MANUAL) {
            pc.printf("MODE IS MANUAL GOT VPACE\n");
        }
    } else if (a == 'O') {
        keyboard_needs_numeric = 1;
    } else {
        // do nothing for invalid char
    }

}

void pm_sense(void const *args)
{

    while(1) {

        if (timer_count >= VRP && vgetSignal == 1) {
            // Valid_V state

            timer_count = 0;
            vsense();
            // do something with Vsense!

        } else if (timer_count < VRP  && vgetSignal == 1) {
            // Invalid_V state
        }

        if (timer_count < PVARP && agetSignal == 1) {
            // Invalid_A state
        } else if (timer_count >= PVARP && agetSignal == 1) {
            // Valid_A state
            asense();
            // do something with Asense!
        }

    }
}

void pm_response(void const *args)
{
    while(1) {
        bool goInitalState = 1;
        if (timer_count >= LRI-AVI) {
            goInitalState = 0;
            // PM_A! sets the LED high
            led_apace = 1;

            // avi_clk = 0
            avi_clk.reset();

            apace();
            // At Atrial Event State
            while (avi_clk.read() < AVI) {
                if (v_sense == 1) {
                    goInitalState = 1;
                    break;
                }
            }
            if (!goInitalState) {
                // Ventricular Event
                timer_count = 0;

                // PM_V! sets the LED high
                led_vpace = 1;

                timer_count = 0;
                vpace();
            }
        } else if (timer_count < LRI - AVI) {
            // if Asense, move on to atrial event
            if (a_sense == 1) {
                goInitalState = 0;
                
                // avi_clk = 0
                avi_clk.reset();

                // At Atrial Event State
                while (avi_clk.read() < AVI) {
                    if (v_sense == 1) {
                        goInitalState = 1;
                        break;
                    }
                }

                // Ventricular Event
                timer_count = 0;

                // PM_V! sets the LED high
                led_vpace = 1;

                timer_count = 0;
                vpace();
            }
        }
    }
}

int main()
{
    // https://developer.mbed.org/users/chadnach1/code/PacemakerController/
    // connect the serial device (PC keybd) to the interrupt
    pc.attach(&keyboard_handler);

    // Start LED's Off
    led_apace = 0;
    led_vpace = 0;

    // Start the avi_clock
    avi_clk.start();

    Thread t2(PM_ALARM);
    Thread t3(pm_sense);
    Thread t4(pm_response);
}