Part of the Pacemaker Project; this models the Pacemaker.

Dependencies:   mbed TextLCD mbed-rtos

Committer:
lucastai
Date:
Mon Nov 30 21:36:01 2015 +0000
Revision:
22:365d51eb3783
Parent:
18:d4cd9d12345e
added to pm test;

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
lucastai 2:5e9c4d83d038 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;
chadnach1 16:ae9df4194011 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
lucastai 2:5e9c4d83d038 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
lucastai 18:d4cd9d12345e 45 DigitalOut apace(p22):
lucastai 18:d4cd9d12345e 46 DigitalOut vpace(p21):
lucastai 18:d4cd9d12345e 47
lucastai 2:5e9c4d83d038 48 // hardware interrupt handler, adapted from code in piazza post by Dagaen
lucastai 2:5e9c4d83d038 49 extern "C" void TIMER0_IRQHandler (void)
lucastai 2:5e9c4d83d038 50 {
lucastai 2:5e9c4d83d038 51 if((LPC_TIM0->IR & 0x01) == 0x01) // if MR0 interrupt, proceed
lucastai 2:5e9c4d83d038 52 {
lucastai 2:5e9c4d83d038 53 LPC_TIM0->IR |= 1 << 0; // Clear MR0 interrupt flag
lucastai 2:5e9c4d83d038 54 timer_count++; //increment timer_count
lucastai 2:5e9c4d83d038 55 }
lucastai 2:5e9c4d83d038 56 }
lucastai 2:5e9c4d83d038 57
lucastai 2:5e9c4d83d038 58 // init the hardware interrupt (timer0), adapted same as above
lucastai 2:5e9c4d83d038 59 void timer0_init(void)
lucastai 2:5e9c4d83d038 60 {
lucastai 2:5e9c4d83d038 61 LPC_SC->PCONP |=1<1; //timer0 power on
lucastai 2:5e9c4d83d038 62 LPC_SC-> PCLKSEL0 |= 1 << 2; // set timer clock to CCLCK nondivided (1 clock cycle = 1 increment)
lucastai 2:5e9c4d83d038 63 LPC_TIM0->MR0 = 1000000; //100mhz clock cycle, 1 cycle = 10ns, 10ms = 10 000 000 ns = 1M cycles
lucastai 2:5e9c4d83d038 64 LPC_TIM0->MCR = 3; //interrupt and reset control
lucastai 2:5e9c4d83d038 65 //3 = Interrupt & reset timer0 on match (111) sets all three bits
lucastai 2:5e9c4d83d038 66 NVIC_EnableIRQ(TIMER0_IRQn); //enable timer0 interrupt
chadnach1 0:d92e0b71c6b5 67 }
chadnach1 0:d92e0b71c6b5 68
lucastai 2:5e9c4d83d038 69
lucastai 2:5e9c4d83d038 70 void PM_ALARM(void const *argument){
lucastai 2:5e9c4d83d038 71
lucastai 2:5e9c4d83d038 72 // min hr alarm
lucastai 2:5e9c4d83d038 73 if( beats < MIN_PM_RT){
lucastai 2:5e9c4d83d038 74 lcd.locate(0,1);
lucastai 2:5e9c4d83d038 75 lcd.printf("!<");
lucastai 2:5e9c4d83d038 76 }
lucastai 2:5e9c4d83d038 77
lucastai 2:5e9c4d83d038 78 // max hr alarm
lucastai 2:5e9c4d83d038 79 if(beats > MAX_PM_RT){
lucastai 2:5e9c4d83d038 80 lcd.locate(0,1);
lucastai 2:5e9c4d83d038 81 lcd.printf("!>");
lucastai 2:5e9c4d83d038 82 }
chadnach1 0:d92e0b71c6b5 83
chadnach1 0:d92e0b71c6b5 84 }
chadnach1 0:d92e0b71c6b5 85
lucastai 2:5e9c4d83d038 86 // hw interrupt callback, deal with the keyboard input from PC
mhowar 5:9eee15818b0e 87 void keyboard_handler() {
lucastai 2:5e9c4d83d038 88
lucastai 2:5e9c4d83d038 89 // get the char, put it on the PC command line
lucastai 2:5e9c4d83d038 90 char a = pc.getc();
lucastai 2:5e9c4d83d038 91
mhowar 5:9eee15818b0e 92 if (keyboard_needs_numeric) {
mhowar 5:9eee15818b0e 93 if (a >= '0' && a <= '9') {
mhowar 5:9eee15818b0e 94 // update observation interval
mhowar 9:fd8477284185 95 obs_int = (a - '0' + 1) * 5;
mhowar 5:9eee15818b0e 96 } else {
mhowar 5:9eee15818b0e 97 pc.printf("Expected numeric key\n");
mhowar 5:9eee15818b0e 98 }
lucastai 22:365d51eb3783 99 keyboard_needs_numeric = 0;
mhowar 5:9eee15818b0e 100 } else if(a == 'N'){
mhowar 5:9eee15818b0e 101 // if the char is N, update bounds to normal mode
lucastai 2:5e9c4d83d038 102 curr_mode = NORMAL;
lucastai 2:5e9c4d83d038 103 upper_bound = 100;
lucastai 2:5e9c4d83d038 104 lower_bound = 40;
lucastai 2:5e9c4d83d038 105 pc.printf("MODE IS N\n");
lucastai 2:5e9c4d83d038 106 // if the char is S, set bounds to sleep
lucastai 2:5e9c4d83d038 107 }else if (a == 'S'){
lucastai 2:5e9c4d83d038 108 curr_mode = SLEEP;
lucastai 2:5e9c4d83d038 109 upper_bound = 60;
lucastai 2:5e9c4d83d038 110 lower_bound = 30;
lucastai 2:5e9c4d83d038 111 pc.printf("MODE IS S\n");
lucastai 2:5e9c4d83d038 112 // if the char is E, set bounds to exercise
lucastai 2:5e9c4d83d038 113 }else if (a == 'E'){
lucastai 2:5e9c4d83d038 114 curr_mode = EXERCISE;
lucastai 2:5e9c4d83d038 115 upper_bound = 175;
lucastai 2:5e9c4d83d038 116 lower_bound = 100;
lucastai 2:5e9c4d83d038 117 pc.printf("MODE IS E\n");
lucastai 2:5e9c4d83d038 118 beats = 2;
lucastai 2:5e9c4d83d038 119 // if the char is M, set to manual
lucastai 2:5e9c4d83d038 120 }else if (a == 'M'){
lucastai 2:5e9c4d83d038 121 curr_mode = MANUAL;
lucastai 2:5e9c4d83d038 122 upper_bound = 175;
lucastai 2:5e9c4d83d038 123 lower_bound = 30;
lucastai 2:5e9c4d83d038 124 beats = 300;
lucastai 2:5e9c4d83d038 125 pc.printf("MODE IS MANUAL\n");
lucastai 2:5e9c4d83d038 126 // check for A if mode is manual
lucastai 2:5e9c4d83d038 127 }else if (a == 'A'){
lucastai 2:5e9c4d83d038 128 if(curr_mode == MANUAL){
lucastai 2:5e9c4d83d038 129 pc.printf("MODE IS MANUAL GOT APACE\n");
lucastai 2:5e9c4d83d038 130 }
lucastai 2:5e9c4d83d038 131 // check for V is mode is manual
lucastai 2:5e9c4d83d038 132 }else if (a == 'V'){
lucastai 2:5e9c4d83d038 133 if(curr_mode == MANUAL){
lucastai 2:5e9c4d83d038 134 pc.printf("MODE IS MANUAL GOT VPACE\n");
lucastai 2:5e9c4d83d038 135 }
mhowar 5:9eee15818b0e 136 }else if (a == 'O'){
mhowar 5:9eee15818b0e 137 keyboard_needs_numeric = 1;
mhowar 5:9eee15818b0e 138 } else{
lucastai 2:5e9c4d83d038 139 // do nothing for invalid char
lucastai 2:5e9c4d83d038 140 }
lucastai 2:5e9c4d83d038 141
lucastai 22:365d51eb3783 142 keyboard_needs_number = 0;
lucastai 22:365d51eb3783 143
lucastai 2:5e9c4d83d038 144
lucastai 2:5e9c4d83d038 145 }
lucastai 2:5e9c4d83d038 146
amiche 3:44d132582373 147 void pm_sense() {
chadnach1 4:f04eb7f96f4b 148
chadnach1 4:f04eb7f96f4b 149 while(1) {
chadnach1 4:f04eb7f96f4b 150
chadnach1 4:f04eb7f96f4b 151 if (timer_count >= VRP) {
chadnach1 4:f04eb7f96f4b 152 //wait for Vget;
chadnach1 4:f04eb7f96f4b 153 timer_count = 0;
chadnach1 4:f04eb7f96f4b 154 // do something with Vsense!
chadnach1 4:f04eb7f96f4b 155 } else if (timer_count < VRP) {
chadnach1 4:f04eb7f96f4b 156 // wait for Vget
chadnach1 4:f04eb7f96f4b 157 }
chadnach1 4:f04eb7f96f4b 158
chadnach1 4:f04eb7f96f4b 159 if (timer_count < PVARP) {
chadnach1 4:f04eb7f96f4b 160 // wait for Aget?
chadnach1 4:f04eb7f96f4b 161 } else if (timer_count >= PVARP) {
chadnach1 4:f04eb7f96f4b 162 // wait for Aget?
chadnach1 4:f04eb7f96f4b 163 // do something with Asense!
chadnach1 4:f04eb7f96f4b 164 }
chadnach1 4:f04eb7f96f4b 165
chadnach1 4:f04eb7f96f4b 166 }
amiche 3:44d132582373 167 }
amiche 3:44d132582373 168
amiche 3:44d132582373 169 void pm_response() {
chadnach1 4:f04eb7f96f4b 170
chadnach1 4:f04eb7f96f4b 171 while(1) {
chadnach1 4:f04eb7f96f4b 172 if (timer_count >= LRI-AVI) {
chadnach1 16:ae9df4194011 173
chadnach1 16:ae9df4194011 174 // PM_A! sets the LED high
chadnach1 17:c89cddf30925 175 led_apace = 1;
chadnach1 16:ae9df4194011 176
chadnach1 4:f04eb7f96f4b 177 // avi_clk = 0
chadnach1 16:ae9df4194011 178 avi_clk.reset();
chadnach1 16:ae9df4194011 179
chadnach1 16:ae9df4194011 180 apace();
chadnach1 7:af6c040f0421 181 } else if (timer_count < LRI - AVI) {
chadnach1 16:ae9df4194011 182
chadnach1 7:af6c040f0421 183 // avi_clk = 0
chadnach1 16:ae9df4194011 184 avi_clk.reset();
chadnach1 16:ae9df4194011 185
chadnach1 16:ae9df4194011 186 // wait for Asense? naaah
chadnach1 7:af6c040f0421 187 }
chadnach1 7:af6c040f0421 188
chadnach1 7:af6c040f0421 189 // At Atrial Event State
chadnach1 16:ae9df4194011 190 while (avi_clk.read() < AVI);
chadnach1 7:af6c040f0421 191
chadnach1 7:af6c040f0421 192 // Ventricular Event
chadnach1 7:af6c040f0421 193 timer_count = 0;
chadnach1 16:ae9df4194011 194
chadnach1 16:ae9df4194011 195 // PM_V! sets the LED high
chadnach1 17:c89cddf30925 196 led_vpace = 1;
chadnach1 16:ae9df4194011 197
chadnach1 7:af6c040f0421 198 timer_count = 0;
chadnach1 16:ae9df4194011 199 vpace();
chadnach1 4:f04eb7f96f4b 200 }
amiche 3:44d132582373 201 }
lucastai 2:5e9c4d83d038 202
lucastai 2:5e9c4d83d038 203
lucastai 2:5e9c4d83d038 204 void apace() {
chadnach1 17:c89cddf30925 205
lucastai 11:14b15f4604ad 206 apace = 1;
lucastai 14:a16b636c2bbc 207 led_apace = 1;
lucastai 11:14b15f4604ad 208 Thread::wait(10);
lucastai 11:14b15f4604ad 209 apace = 0;
lucastai 13:2a25dd47478e 210
lucastai 2:5e9c4d83d038 211 }
lucastai 2:5e9c4d83d038 212
lucastai 2:5e9c4d83d038 213 void vpace() {
chadnach1 17:c89cddf30925 214
lucastai 11:14b15f4604ad 215 vpace = 1;
lucastai 14:a16b636c2bbc 216 led_vpace = 1;
lucastai 11:14b15f4604ad 217 Thread::wait(10);
lucastai 11:14b15f4604ad 218 vpace = 0;
chadnach1 17:c89cddf30925 219
chadnach1 0:d92e0b71c6b5 220 }
chadnach1 0:d92e0b71c6b5 221
amiche 3:44d132582373 222
chadnach1 0:d92e0b71c6b5 223 int main() {
chadnach1 16:ae9df4194011 224 // https://developer.mbed.org/users/chadnach1/code/PacemakerController/
lucastai 2:5e9c4d83d038 225 // connect the serial device (PC keybd) to the interrupt
mhowar 5:9eee15818b0e 226 pc.attach(&keyboard_handler);
lucastai 2:5e9c4d83d038 227
chadnach1 16:ae9df4194011 228 // Start LED's Off
chadnach1 17:c89cddf30925 229 led_apace = 0;
chadnach1 17:c89cddf30925 230 led_vpace = 0;
chadnach1 16:ae9df4194011 231
chadnach1 16:ae9df4194011 232 // Start the avi_clock
chadnach1 16:ae9df4194011 233 avi_clk.start();
chadnach1 16:ae9df4194011 234
amiche 3:44d132582373 235 Thread t3(pm_sense);
amiche 3:44d132582373 236 Thread t4(pm_response);
amiche 3:44d132582373 237
amiche 3:44d132582373 238 Thread t2(PM_ALARM);
amiche 3:44d132582373 239 Thread t5();
amiche 3:44d132582373 240
chadnach1 17:c89cddf30925 241 }