Part of the Pacemaker Project; this models the Pacemaker.

Dependencies:   mbed TextLCD mbed-rtos

Committer:
amiche
Date:
Tue Dec 01 16:04:11 2015 +0000
Revision:
24:81cd9ef5c4f6
Parent:
20:dc272bfaa276
Child:
27:2c5aefcf3000
Add vsense and asense logic to pm_sense and pm_response

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