Part of the Pacemaker Project; this models the Pacemaker.

Dependencies:   mbed TextLCD mbed-rtos

PacemakerController.cpp

Committer:
chadnach1
Date:
2015-12-02
Revision:
39:51c4ec84f6fd
Parent:
35:b5e8650a7669
Child:
40:e401b1cb71c0

File content as of revision 39:51c4ec84f6fd:

#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;
Timer t_count;

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 led_asense(LED3);
DigitalOut led_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;
    led_asense = 1;
    Thread::wait(10);
    led_asense = 0;
    a_sense = 0;
}

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

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

}

void vpace()
{
    vpaceSignal = 1;
    led_vpace = 1;
    Thread::wait(10);
    led_vpace = 0;
    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)
{
    while (1) {
        // min hr alarm
        if( beats < MIN_PM_RT) {
            lcd.cls();
            lcd.locate(0,1);
            lcd.printf("!<\n");
        }

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

}

// hw interrupt callback, deal with the keyboard input from PC

void pm_sense(void const *args)
{

    while(1) {
        /*if (agetSignal == 0) {
            pc.printf("Aget:LO\n"); 
        }
        
        if (vgetSignal == 0) {
            pc.printf("Vget:LO\n"); 
        }
        if (agetSignal == 1) {
            pc.printf("Aget:HI\n"); 
        }
        
        if (vgetSignal == 1) {
            pc.printf("Vget:HI\n"); 
        }*/
        

        if (t_count.read_ms() >= VRP && vgetSignal == 1) {
            
            // Valid_V state
            t_count.reset();
            vsense();

        } else if (t_count.read_ms() < VRP  && vgetSignal == 1) {
            //pc.printf("invalid v state\n");

            // Invalid_V state
        }

        if (t_count.read_ms() < PVARP && agetSignal == 1) {
            // Invalid_A state
            
            //pc.printf("invalid a state\n");
        } else if (t_count.read_ms() >= PVARP && agetSignal == 1) {
            // Valid_A state
            asense();
        }
    }
}

void pm_response(void const *args)
{
    while(1) {

        bool goInitalState = 1;
        if (t_count.read_ms() >= LRI - AVI) {
            
            goInitalState = 0;
            
            // PM_A! sets the LED high
            led_apace = 1;

            avi_clk.reset();

            apace();
            
            // At Atrial Event State
            while (avi_clk.read_ms() < AVI) {

                if (v_sense == 1) {
                    goInitalState = 1;
                    break;
                }
            }
            if (!goInitalState) {
                // Ventricular Event
                t_count.reset();

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

                t_count.reset();
                vpace();
            }
        } else if (t_count.read_ms() < LRI - AVI) {

            // if Asense, move on to atrial event
            if (a_sense == 1) {
                goInitalState = 0;
                
                avi_clk.reset();

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

                // Ventricular Event
                t_count.reset();

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

                t_count.reset();
                vpace();
            }
        }
    }
}

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

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

    // Start the avi_clock
    avi_clk.start();
    avi_clk.reset();

    Thread t1(pm_sense, (void *)"");
    Thread t2(pm_response, (void *)"");
    Thread t3(PM_ALARM, (void *)"");
    t_count.start();
    t_count.reset();

    while(1) {
        if (pc.readable()) {
    
            char a = pc.getc();
    
            // Handle different keyboard inputs
            if (keyboard_needs_numeric) {
                if (a >= '0' && a <= '9') {
                    // update observation interval
                    obs_int = (a - '0' + 1) * 5;
                    keyboard_needs_numeric = 0;
                } 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");
                // if the char is M, set to manual
            } else if (a == 'M') {
                curr_mode = MANUAL;
                upper_bound = 175;
                lower_bound = 30;
                pc.printf("MODE IS MANUAL\n");
                // check for A if mode is manual
            } else if (a == 'A') {
                if(curr_mode == MANUAL) {
                    apace();
                    pc.printf("MODE IS MANUAL SENT APACE\n");
                }
                // check for V is mode is manual
            } else if (a == 'V') {
                if(curr_mode == MANUAL) {
                    vpace();
                    pc.printf("MODE IS MANUAL SENT VPACE\n");
                }
            } else if (a == 'O') {
                keyboard_needs_numeric = 1;
            } else {
                // do nothing for invalid char
            }
        }
    }
}