Part of the Pacemaker Project; this models the Pacemaker.

Dependencies:   mbed TextLCD mbed-rtos

Committer:
chadnach1
Date:
Wed Dec 02 06:41:57 2015 +0000
Revision:
43:f28bc869321e
Parent:
42:2e4ed3a53c64
Child:
44:dfa38e4b3146
Working from here with Michelle's, without Matt's calculations

Who changed what in which revision?

UserRevisionLine numberNew contents of line
chadnach1 0:d92e0b71c6b5 1 #include "mbed.h"
lucastai 2:5e9c4d83d038 2 #include "LPC17xx.h"
lucastai 2:5e9c4d83d038 3 #include "TextLCD.h"
lucastai 2:5e9c4d83d038 4 #include "rtos.h"
lucastai 2:5e9c4d83d038 5 #include "Thread.h"
lucastai 2:5e9c4d83d038 6 using namespace rtos;
chadnach1 0:d92e0b71c6b5 7
chadnach1 0:d92e0b71c6b5 8 // This is for the pacemaker
lucastai 2:5e9c4d83d038 9 volatile unsigned short timer_count;
lucastai 2:5e9c4d83d038 10 Serial pc(USBTX, USBRX);
lucastai 2:5e9c4d83d038 11 TextLCD lcd(p15, p16, p17, p18, p19, p20, TextLCD::LCD20x4); // rs, e, d4-d7
lucastai 2:5e9c4d83d038 12
mhowar 5:9eee15818b0e 13 int keyboard_needs_numeric = 0; // boolean - is in middle of interval input?
chadnach1 0:d92e0b71c6b5 14
chadnach1 0:d92e0b71c6b5 15 int h_clock;
amiche 3:44d132582373 16 int pm_clock;
chadnach1 27:2c5aefcf3000 17 Timer avi_clk;
chadnach1 32:c58b6651336c 18 Timer t_count;
chadnach1 0:d92e0b71c6b5 19
chadnach1 43:f28bc869321e 20 int LRI = 1000;
chadnach1 43:f28bc869321e 21 int AVI = 300;
amiche 38:ceabf8f1dfa0 22 int PVARP = 150;
amiche 38:ceabf8f1dfa0 23 int VRP = 100;
lucastai 2:5e9c4d83d038 24
lucastai 2:5e9c4d83d038 25 // constants
lucastai 2:5e9c4d83d038 26 int MAX_PM_RT = 180;
lucastai 2:5e9c4d83d038 27 int MIN_PM_RT = 40;
lucastai 2:5e9c4d83d038 28 enum mode {NORMAL, SLEEP, EXERCISE, MANUAL};
lucastai 2:5e9c4d83d038 29
lucastai 2:5e9c4d83d038 30 // counters
chadnach1 43:f28bc869321e 31 int beats = 0;
lucastai 2:5e9c4d83d038 32
lucastai 2:5e9c4d83d038 33 // state variables
lucastai 2:5e9c4d83d038 34 int upper_bound = 100;
lucastai 2:5e9c4d83d038 35 int lower_bound = 40;
lucastai 2:5e9c4d83d038 36 int obs_int = 10;
lucastai 2:5e9c4d83d038 37 mode curr_mode = NORMAL;
lucastai 2:5e9c4d83d038 38
amiche 19:f3615321b5c4 39 // alarms
lucastai 14:a16b636c2bbc 40 DigitalOut led_apace(LED1);
lucastai 14:a16b636c2bbc 41 DigitalOut led_vpace(LED2);
chadnach1 33:b68c1648206e 42 DigitalOut led_asense(LED3);
chadnach1 33:b68c1648206e 43 DigitalOut led_vsense(LED4);
lucastai 2:5e9c4d83d038 44
chadnach1 27:2c5aefcf3000 45 DigitalIn agetSignal(p24);
chadnach1 27:2c5aefcf3000 46 DigitalIn vgetSignal(p23);
chadnach1 27:2c5aefcf3000 47 DigitalOut apaceSignal(p22);
chadnach1 27:2c5aefcf3000 48 DigitalOut vpaceSignal(p21);
chadnach1 27:2c5aefcf3000 49
chadnach1 27:2c5aefcf3000 50 bool v_sense;
chadnach1 27:2c5aefcf3000 51 bool a_sense;
chadnach1 27:2c5aefcf3000 52
chadnach1 27:2c5aefcf3000 53 void asense()
chadnach1 27:2c5aefcf3000 54 {
chadnach1 27:2c5aefcf3000 55 a_sense = 1;
chadnach1 33:b68c1648206e 56 led_asense = 1;
chadnach1 27:2c5aefcf3000 57 Thread::wait(10);
chadnach1 33:b68c1648206e 58 led_asense = 0;
chadnach1 27:2c5aefcf3000 59 a_sense = 0;
chadnach1 27:2c5aefcf3000 60 }
lucastai 18:d4cd9d12345e 61
chadnach1 27:2c5aefcf3000 62 void vsense()
chadnach1 27:2c5aefcf3000 63 {
chadnach1 27:2c5aefcf3000 64 v_sense = 1;
chadnach1 33:b68c1648206e 65 led_vsense = 1;
chadnach1 27:2c5aefcf3000 66 Thread::wait(10);
chadnach1 33:b68c1648206e 67 led_vsense = 0;
chadnach1 27:2c5aefcf3000 68 v_sense = 0;
chadnach1 27:2c5aefcf3000 69 }
chadnach1 27:2c5aefcf3000 70
chadnach1 27:2c5aefcf3000 71 void apace()
chadnach1 27:2c5aefcf3000 72 {
chadnach1 27:2c5aefcf3000 73 apaceSignal = 1;
chadnach1 27:2c5aefcf3000 74 led_apace = 1;
chadnach1 27:2c5aefcf3000 75 Thread::wait(10);
chadnach1 33:b68c1648206e 76 led_apace = 0;
chadnach1 27:2c5aefcf3000 77 apaceSignal = 0;
chadnach1 27:2c5aefcf3000 78
chadnach1 27:2c5aefcf3000 79 }
chadnach1 27:2c5aefcf3000 80
chadnach1 27:2c5aefcf3000 81 void vpace()
chadnach1 27:2c5aefcf3000 82 {
chadnach1 27:2c5aefcf3000 83 vpaceSignal = 1;
chadnach1 27:2c5aefcf3000 84 led_vpace = 1;
chadnach1 27:2c5aefcf3000 85 Thread::wait(10);
chadnach1 33:b68c1648206e 86 led_vpace = 0;
chadnach1 27:2c5aefcf3000 87 vpaceSignal = 0;
chadnach1 43:f28bc869321e 88
chadnach1 27:2c5aefcf3000 89 }
amiche 24:81cd9ef5c4f6 90
lucastai 2:5e9c4d83d038 91 // hardware interrupt handler, adapted from code in piazza post by Dagaen
chadnach1 33:b68c1648206e 92 /*extern "C" void TIMER0_IRQHandler (void)
lucastai 2:5e9c4d83d038 93 {
amiche 19:f3615321b5c4 94 if((LPC_TIM0->IR & 0x01) == 0x01) { // if MR0 interrupt, proceed
amiche 19:f3615321b5c4 95 LPC_TIM0->IR |= 1 << 0; // Clear MR0 interrupt flag
amiche 19:f3615321b5c4 96 timer_count++; //increment timer_count
lucastai 2:5e9c4d83d038 97 }
lucastai 2:5e9c4d83d038 98 }
chadnach1 33:b68c1648206e 99 */
chadnach1 33:b68c1648206e 100 /*// init the hardware interrupt (timer0), adapted same as above
lucastai 2:5e9c4d83d038 101 void timer0_init(void)
lucastai 2:5e9c4d83d038 102 {
lucastai 2:5e9c4d83d038 103 LPC_SC->PCONP |=1<1; //timer0 power on
lucastai 2:5e9c4d83d038 104 LPC_SC-> PCLKSEL0 |= 1 << 2; // set timer clock to CCLCK nondivided (1 clock cycle = 1 increment)
lucastai 2:5e9c4d83d038 105 LPC_TIM0->MR0 = 1000000; //100mhz clock cycle, 1 cycle = 10ns, 10ms = 10 000 000 ns = 1M cycles
lucastai 2:5e9c4d83d038 106 LPC_TIM0->MCR = 3; //interrupt and reset control
amiche 19:f3615321b5c4 107 //3 = Interrupt & reset timer0 on match (111) sets all three bits
lucastai 2:5e9c4d83d038 108 NVIC_EnableIRQ(TIMER0_IRQn); //enable timer0 interrupt
chadnach1 33:b68c1648206e 109 }*/
chadnach1 0:d92e0b71c6b5 110
lucastai 2:5e9c4d83d038 111
chadnach1 27:2c5aefcf3000 112 void PM_ALARM(void const *args)
amiche 19:f3615321b5c4 113 {
chadnach1 29:5cec671cb80d 114 while (1) {
chadnach1 29:5cec671cb80d 115 // min hr alarm
chadnach1 29:5cec671cb80d 116 if( beats < MIN_PM_RT) {
chadnach1 30:97db5a684eaa 117 lcd.cls();
chadnach1 29:5cec671cb80d 118 lcd.locate(0,1);
chadnach1 30:97db5a684eaa 119 lcd.printf("!<\n");
chadnach1 29:5cec671cb80d 120 }
chadnach1 31:7f0e865e3d4b 121
chadnach1 29:5cec671cb80d 122 // max hr alarm
chadnach1 29:5cec671cb80d 123 if(beats > MAX_PM_RT) {
chadnach1 30:97db5a684eaa 124 lcd.cls();
chadnach1 29:5cec671cb80d 125 lcd.locate(0,1);
chadnach1 30:97db5a684eaa 126 lcd.printf("!>\n");
chadnach1 29:5cec671cb80d 127 }
amiche 19:f3615321b5c4 128 }
amiche 19:f3615321b5c4 129
chadnach1 0:d92e0b71c6b5 130 }
chadnach1 0:d92e0b71c6b5 131
lucastai 2:5e9c4d83d038 132 // hw interrupt callback, deal with the keyboard input from PC
lucastai 2:5e9c4d83d038 133
chadnach1 27:2c5aefcf3000 134 void pm_sense(void const *args)
amiche 19:f3615321b5c4 135 {
amiche 19:f3615321b5c4 136
chadnach1 4:f04eb7f96f4b 137 while(1) {
chadnach1 33:b68c1648206e 138 /*if (agetSignal == 0) {
chadnach1 33:b68c1648206e 139 pc.printf("Aget:LO\n");
chadnach1 33:b68c1648206e 140 }
chadnach1 33:b68c1648206e 141
chadnach1 33:b68c1648206e 142 if (vgetSignal == 0) {
chadnach1 33:b68c1648206e 143 pc.printf("Vget:LO\n");
chadnach1 33:b68c1648206e 144 }
chadnach1 33:b68c1648206e 145 if (agetSignal == 1) {
chadnach1 33:b68c1648206e 146 pc.printf("Aget:HI\n");
chadnach1 33:b68c1648206e 147 }
chadnach1 33:b68c1648206e 148
chadnach1 33:b68c1648206e 149 if (vgetSignal == 1) {
chadnach1 33:b68c1648206e 150 pc.printf("Vget:HI\n");
chadnach1 33:b68c1648206e 151 }*/
chadnach1 33:b68c1648206e 152
amiche 19:f3615321b5c4 153
chadnach1 33:b68c1648206e 154 if (t_count.read_ms() >= VRP && vgetSignal == 1) {
chadnach1 34:b4b50ca26e8c 155
amiche 24:81cd9ef5c4f6 156 // Valid_V state
chadnach1 32:c58b6651336c 157 t_count.reset();
amiche 24:81cd9ef5c4f6 158 vsense();
amiche 24:81cd9ef5c4f6 159
chadnach1 33:b68c1648206e 160 } else if (t_count.read_ms() < VRP && vgetSignal == 1) {
chadnach1 20:dc272bfaa276 161 // Invalid_V state
chadnach1 4:f04eb7f96f4b 162 }
amiche 19:f3615321b5c4 163
chadnach1 33:b68c1648206e 164 if (t_count.read_ms() < PVARP && agetSignal == 1) {
chadnach1 20:dc272bfaa276 165 // Invalid_A state
chadnach1 34:b4b50ca26e8c 166
chadnach1 33:b68c1648206e 167 } else if (t_count.read_ms() >= PVARP && agetSignal == 1) {
chadnach1 20:dc272bfaa276 168 // Valid_A state
amiche 24:81cd9ef5c4f6 169 asense();
chadnach1 4:f04eb7f96f4b 170 }
chadnach1 4:f04eb7f96f4b 171 }
amiche 3:44d132582373 172 }
amiche 3:44d132582373 173
chadnach1 27:2c5aefcf3000 174 void pm_response(void const *args)
amiche 19:f3615321b5c4 175 {
chadnach1 4:f04eb7f96f4b 176 while(1) {
chadnach1 34:b4b50ca26e8c 177
chadnach1 27:2c5aefcf3000 178 bool goInitalState = 1;
chadnach1 33:b68c1648206e 179 if (t_count.read_ms() >= LRI - AVI) {
chadnach1 33:b68c1648206e 180
chadnach1 27:2c5aefcf3000 181 goInitalState = 0;
chadnach1 34:b4b50ca26e8c 182
amiche 19:f3615321b5c4 183 // PM_A! sets the LED high
amiche 19:f3615321b5c4 184 led_apace = 1;
amiche 19:f3615321b5c4 185
amiche 19:f3615321b5c4 186 avi_clk.reset();
amiche 19:f3615321b5c4 187
amiche 19:f3615321b5c4 188 apace();
chadnach1 34:b4b50ca26e8c 189
amiche 19:f3615321b5c4 190 // At Atrial Event State
chadnach1 33:b68c1648206e 191 while (avi_clk.read_ms() < AVI) {
chadnach1 34:b4b50ca26e8c 192
chadnach1 27:2c5aefcf3000 193 if (v_sense == 1) {
chadnach1 27:2c5aefcf3000 194 goInitalState = 1;
amiche 24:81cd9ef5c4f6 195 break;
amiche 24:81cd9ef5c4f6 196 }
amiche 24:81cd9ef5c4f6 197 }
chadnach1 27:2c5aefcf3000 198 if (!goInitalState) {
amiche 24:81cd9ef5c4f6 199 // Ventricular Event
chadnach1 32:c58b6651336c 200 t_count.reset();
amiche 19:f3615321b5c4 201
amiche 24:81cd9ef5c4f6 202 // PM_V! sets the LED high
amiche 24:81cd9ef5c4f6 203 led_vpace = 1;
amiche 19:f3615321b5c4 204
chadnach1 32:c58b6651336c 205 t_count.reset();
chadnach1 43:f28bc869321e 206 pc.printf("in pmresponse 2");
amiche 24:81cd9ef5c4f6 207 vpace();
amiche 24:81cd9ef5c4f6 208 }
chadnach1 33:b68c1648206e 209 } else if (t_count.read_ms() < LRI - AVI) {
chadnach1 34:b4b50ca26e8c 210
amiche 24:81cd9ef5c4f6 211 // if Asense, move on to atrial event
chadnach1 27:2c5aefcf3000 212 if (a_sense == 1) {
chadnach1 27:2c5aefcf3000 213 goInitalState = 0;
chadnach1 34:b4b50ca26e8c 214
amiche 24:81cd9ef5c4f6 215 avi_clk.reset();
amiche 19:f3615321b5c4 216
amiche 24:81cd9ef5c4f6 217 // At Atrial Event State
amiche 24:81cd9ef5c4f6 218 while (avi_clk.read() < AVI) {
chadnach1 27:2c5aefcf3000 219 if (v_sense == 1) {
chadnach1 27:2c5aefcf3000 220 goInitalState = 1;
amiche 24:81cd9ef5c4f6 221 break;
amiche 24:81cd9ef5c4f6 222 }
amiche 24:81cd9ef5c4f6 223 }
amiche 19:f3615321b5c4 224
amiche 24:81cd9ef5c4f6 225 // Ventricular Event
chadnach1 32:c58b6651336c 226 t_count.reset();
amiche 24:81cd9ef5c4f6 227
amiche 24:81cd9ef5c4f6 228 // PM_V! sets the LED high
amiche 24:81cd9ef5c4f6 229 led_vpace = 1;
amiche 24:81cd9ef5c4f6 230
chadnach1 32:c58b6651336c 231 t_count.reset();
amiche 24:81cd9ef5c4f6 232 vpace();
amiche 24:81cd9ef5c4f6 233 }
amiche 19:f3615321b5c4 234 }
amiche 19:f3615321b5c4 235 }
amiche 3:44d132582373 236 }
lucastai 2:5e9c4d83d038 237
amiche 19:f3615321b5c4 238 int main()
amiche 19:f3615321b5c4 239 {
chadnach1 16:ae9df4194011 240 // https://developer.mbed.org/users/chadnach1/code/PacemakerController/
lucastai 2:5e9c4d83d038 241 // connect the serial device (PC keybd) to the interrupt
amiche 19:f3615321b5c4 242
chadnach1 16:ae9df4194011 243 // Start LED's Off
chadnach1 17:c89cddf30925 244 led_apace = 0;
chadnach1 17:c89cddf30925 245 led_vpace = 0;
amiche 19:f3615321b5c4 246
chadnach1 16:ae9df4194011 247 // Start the avi_clock
chadnach1 16:ae9df4194011 248 avi_clk.start();
chadnach1 33:b68c1648206e 249 avi_clk.reset();
amiche 19:f3615321b5c4 250
chadnach1 30:97db5a684eaa 251 Thread t1(pm_sense, (void *)"");
chadnach1 30:97db5a684eaa 252 Thread t2(pm_response, (void *)"");
chadnach1 31:7f0e865e3d4b 253 Thread t3(PM_ALARM, (void *)"");
chadnach1 33:b68c1648206e 254 t_count.start();
chadnach1 33:b68c1648206e 255 t_count.reset();
chadnach1 31:7f0e865e3d4b 256
chadnach1 31:7f0e865e3d4b 257 while(1) {
mhowar 35:b5e8650a7669 258 if (pc.readable()) {
mhowar 35:b5e8650a7669 259
mhowar 35:b5e8650a7669 260 char a = pc.getc();
mhowar 35:b5e8650a7669 261
mhowar 35:b5e8650a7669 262 // Handle different keyboard inputs
mhowar 35:b5e8650a7669 263 if (keyboard_needs_numeric) {
mhowar 35:b5e8650a7669 264 if (a >= '0' && a <= '9') {
mhowar 35:b5e8650a7669 265 // update observation interval
mhowar 35:b5e8650a7669 266 obs_int = (a - '0' + 1) * 5;
mhowar 35:b5e8650a7669 267 keyboard_needs_numeric = 0;
mhowar 35:b5e8650a7669 268 } else {
mhowar 35:b5e8650a7669 269 pc.printf("Expected numeric key\n");
mhowar 35:b5e8650a7669 270 }
mhowar 35:b5e8650a7669 271 } else if(a == 'N') {
mhowar 35:b5e8650a7669 272 // if the char is N, update bounds to normal mode
mhowar 35:b5e8650a7669 273 curr_mode = NORMAL;
mhowar 35:b5e8650a7669 274 upper_bound = 100;
chadnach1 43:f28bc869321e 275 LRI = 1000;
mhowar 35:b5e8650a7669 276 lower_bound = 40;
mhowar 35:b5e8650a7669 277 pc.printf("MODE IS N\n");
mhowar 35:b5e8650a7669 278 // if the char is S, set bounds to sleep
mhowar 35:b5e8650a7669 279 } else if (a == 'S') {
mhowar 35:b5e8650a7669 280 curr_mode = SLEEP;
mhowar 35:b5e8650a7669 281 upper_bound = 60;
chadnach1 43:f28bc869321e 282 LRI = 600;
mhowar 35:b5e8650a7669 283 lower_bound = 30;
mhowar 35:b5e8650a7669 284 pc.printf("MODE IS S\n");
mhowar 35:b5e8650a7669 285 // if the char is E, set bounds to exercise
mhowar 35:b5e8650a7669 286 } else if (a == 'E') {
mhowar 35:b5e8650a7669 287 curr_mode = EXERCISE;
mhowar 35:b5e8650a7669 288 upper_bound = 175;
chadnach1 43:f28bc869321e 289 LRI = 1750;
mhowar 35:b5e8650a7669 290 lower_bound = 100;
mhowar 35:b5e8650a7669 291 pc.printf("MODE IS E\n");
mhowar 35:b5e8650a7669 292 // if the char is M, set to manual
mhowar 35:b5e8650a7669 293 } else if (a == 'M') {
mhowar 35:b5e8650a7669 294 curr_mode = MANUAL;
mhowar 35:b5e8650a7669 295 upper_bound = 175;
chadnach1 43:f28bc869321e 296 LRI = 1750;
mhowar 35:b5e8650a7669 297 lower_bound = 30;
mhowar 35:b5e8650a7669 298 pc.printf("MODE IS MANUAL\n");
mhowar 35:b5e8650a7669 299 // check for A if mode is manual
mhowar 35:b5e8650a7669 300 } else if (a == 'A') {
mhowar 35:b5e8650a7669 301 if(curr_mode == MANUAL) {
chadnach1 43:f28bc869321e 302 pc.printf("MODE IS MANUAL SENT APACE\n");
chadnach1 39:51c4ec84f6fd 303 apace();
mhowar 35:b5e8650a7669 304 }
mhowar 35:b5e8650a7669 305 // check for V is mode is manual
mhowar 35:b5e8650a7669 306 } else if (a == 'V') {
mhowar 35:b5e8650a7669 307 if(curr_mode == MANUAL) {
chadnach1 43:f28bc869321e 308 pc.printf("MODE IS MANUAL SENT VPACE\n");
chadnach1 39:51c4ec84f6fd 309 vpace();
mhowar 35:b5e8650a7669 310 }
mhowar 35:b5e8650a7669 311 } else if (a == 'O') {
mhowar 35:b5e8650a7669 312 keyboard_needs_numeric = 1;
mhowar 35:b5e8650a7669 313 } else {
mhowar 35:b5e8650a7669 314 // do nothing for invalid char
mhowar 35:b5e8650a7669 315 }
chadnach1 31:7f0e865e3d4b 316 }
chadnach1 31:7f0e865e3d4b 317 }
chadnach1 31:7f0e865e3d4b 318 }