CIS441 Controller

Dependencies:   TextLCD mbed-rtos mbed

Fork of PacemakerController by Chad Nachiappan

PacemakerController.cpp

Committer:
chadnach1
Date:
2015-12-02
Revision:
46:2d9cf50b4bc3
Parent:
45:ec9e76ccec6c
Child:
47:bac7fc1a44fe

File content as of revision 46:2d9cf50b4bc3:

#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

Ticker rate_monitor;
// counters
volatile int beats = 0;
volatile double bpm = 0;
int keyboard_needs_numeric = 0; // boolean - is in middle of interval input?

int h_clock;
int pm_clock;
Timer avi_clk;
Timer sense_clk;
Timer pulse_clk;

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

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

// 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.locate(0,1);
            lcd.printf("!<");
        }

        // max hr alarm
        else if(beats > MAX_PM_RT) {
            lcd.locate(0,1);
            lcd.printf("!>");
        } else {
            lcd.locate(0,1);
            lcd.printf("  ");
           
        }
        
        lcd.locate(0,0);
        lcd.printf("BPM: %.1f   ", bpm);
    }
}

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

void pm_sense(void const *args)
{

    while(1) {       

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

        } else if (sense_clk.read_ms() < VRP  && vgetSignal == 1) {
            // Invalid_V state
        }

        if (sense_clk.read_ms() < PVARP && agetSignal == 1) {
            // Invalid_A state
            
        } else if (sense_clk.read_ms() >= PVARP && agetSignal == 1) {
            // Valid_A state
            asense();
        }
    }
}

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

        bool goInitialState = 1;
        if (pulse_clk.read_ms() >= LRI - AVI) {
            
            goInitialState = 0;
            
            avi_clk.reset();

            // PM_A! sets the LED high
            apace();
            
            // At Atrial Event State
            while (avi_clk.read_ms() < AVI) {

                if (v_sense == 1) {
                    beats++;
                    //sensed valid ventricular event
                    goInitialState = 1;
                    pulse_clk.reset();
                    break;
                }
            }
            if (!goInitialState) {
                // Ventricular Event
                pulse_clk.reset();
                sense_clk.reset();
                
                // PM_V! sets the LED high
                beats++;
                vpace();
            }
        } else if (pulse_clk.read_ms() < LRI - AVI) {

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

                // At Atrial Event State
                while (avi_clk.read() < AVI) {
                    if (v_sense == 1) {
                        beats++;
                        pulse_clk.reset();
                        goInitialState = 1;
                        break;
                    }
                }
                if (!goInitialState) {
                    // Ventricular Event
                    beats++;
                    sense_clk.reset();
                    pulse_clk.reset();
    
                    vpace();
                }
            }
        }
    }
}

/* Every observation interval, calculate beats per minute and display
 *
 */
void update_display() {
    bpm = beats / (double) obs_int * 60;
    //reset count
    beats = 0;
}

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 *)"");
    sense_clk.start();
    pulse_clk.start();
    
    //update_display
    rate_monitor.attach(&update_display, obs_int);
    
    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;
                    rate_monitor.attach(&update_display, obs_int);
                    pc.printf("Set observation interval to %d seconds\n", obs_int);
                } 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;
                LRI = 600;
                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;
                LRI = 1000;
                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;
                LRI = 343;
                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;
                LRI = 1750;
                lower_bound = 30;
                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 SENT APACE\n");
                    apace();
                }
                // check for V is mode is manual
            } else if (a == 'V') {
                if(curr_mode == MANUAL) {
                    pc.printf("MODE IS MANUAL SENT VPACE\n");
                    vpace();
                }
            } else if (a == 'O') {
                keyboard_needs_numeric = 1;
            } else {
                // do nothing for invalid char
            }
        }
    }
}