System Management code

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Committer:
pspatel321
Date:
Thu Nov 13 10:53:10 2014 +0000
Revision:
30:91af74a299e1
Child:
36:0afc0fc8f86b
Parth's edits for the week.; DC-DC completed and fixed, IMD updated, LatchMonitor and Temperature added.  Serial dashboard updated.  File structure changed Everything tested.  Compiles and runs.; Still need to write CAN in/out interface.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pspatel321 30:91af74a299e1 1 #include "IMD.h"
pspatel321 30:91af74a299e1 2 #include <math.h>
pspatel321 30:91af74a299e1 3
pspatel321 30:91af74a299e1 4 static IMD* instance[4] = { 0 }; // Access member from static frame, one IMD permitted per timer module (4 total IMD objects)
pspatel321 30:91af74a299e1 5
pspatel321 30:91af74a299e1 6 const uint32_t PCLK = 24000000; // Timer counting clock = 24Mhz
pspatel321 30:91af74a299e1 7 const uint32_t TIMEOUT_TICKS = PCLK*ZERO_HZ_TIMEOUT; // Zeroing timeout in clock ticks = seconds * PCLK
pspatel321 30:91af74a299e1 8 const float EXTRA = 0.01; // Margin on the IMD PWM limits
pspatel321 30:91af74a299e1 9
pspatel321 30:91af74a299e1 10 // Interrupt functions, must be static context
pspatel321 30:91af74a299e1 11 void tim0_IRQ() {
pspatel321 30:91af74a299e1 12 if (LPC_TIM0->IR & (1<<4|1<<5)) instance[0]->edgeIRQ(); // Capture pin interrupt
pspatel321 30:91af74a299e1 13 if (LPC_TIM0->IR & 1) instance[0]->zeroIRQ(); // MR0 interrupt
pspatel321 30:91af74a299e1 14 LPC_TIM0->IR=0x3F; // Clear interrupt flags
pspatel321 30:91af74a299e1 15 }
pspatel321 30:91af74a299e1 16 void tim1_IRQ() {
pspatel321 30:91af74a299e1 17 if (LPC_TIM1->IR & (1<<4|1<<5)) instance[1]->edgeIRQ();
pspatel321 30:91af74a299e1 18 if (LPC_TIM1->IR & 1) instance[1]->zeroIRQ();
pspatel321 30:91af74a299e1 19 LPC_TIM1->IR=0x3F; // Clear interrupt flags
pspatel321 30:91af74a299e1 20 }
pspatel321 30:91af74a299e1 21 void tim2_IRQ() {
pspatel321 30:91af74a299e1 22 if (LPC_TIM2->IR & (1<<4|1<<5)) instance[2]->edgeIRQ();
pspatel321 30:91af74a299e1 23 if (LPC_TIM2->IR & 1) instance[2]->zeroIRQ();
pspatel321 30:91af74a299e1 24 LPC_TIM2->IR=0x3F; // Clear interrupt flags
pspatel321 30:91af74a299e1 25 }
pspatel321 30:91af74a299e1 26 void tim3_IRQ() {
pspatel321 30:91af74a299e1 27 if (LPC_TIM3->IR & (1<<4|1<<5)) instance[3]->edgeIRQ();
pspatel321 30:91af74a299e1 28 if (LPC_TIM3->IR & 1) instance[3]->zeroIRQ();
pspatel321 30:91af74a299e1 29 LPC_TIM3->IR=0x3F; // Clear interrupt flags
pspatel321 30:91af74a299e1 30 }
pspatel321 30:91af74a299e1 31
pspatel321 30:91af74a299e1 32 bool cmpPin(LPC_pin p1, LPC_pin p2) {
pspatel321 30:91af74a299e1 33 if (p1.gpio_addr == p2.gpio_addr && p1.gpio_num == p2.gpio_num) return true;
pspatel321 30:91af74a299e1 34 else return false;
pspatel321 30:91af74a299e1 35 }
pspatel321 30:91af74a299e1 36
pspatel321 30:91af74a299e1 37 IMD::IMD(LPC_pin _pin) {
pspatel321 30:91af74a299e1 38 // Setup the timer/pin access variables
pspatel321 30:91af74a299e1 39 if (cmpPin(_pin, p1_26)) { // CAP0.0
pspatel321 30:91af74a299e1 40 timer=0;
pspatel321 30:91af74a299e1 41 pin=0;
pspatel321 30:91af74a299e1 42 timerBase=LPC_TIM0;
pspatel321 30:91af74a299e1 43 } else if (cmpPin(_pin, p1_27)) { // CAP0.1
pspatel321 30:91af74a299e1 44 timer=0;
pspatel321 30:91af74a299e1 45 pin=1;
pspatel321 30:91af74a299e1 46 timerBase=LPC_TIM0;
pspatel321 30:91af74a299e1 47 } else if (cmpPin(_pin, p1_18)) { // CAP1.0
pspatel321 30:91af74a299e1 48 timer=1;
pspatel321 30:91af74a299e1 49 pin=0;
pspatel321 30:91af74a299e1 50 timerBase=LPC_TIM1;
pspatel321 30:91af74a299e1 51 } else if (cmpPin(_pin, p1_19)) { // CAP1.1
pspatel321 30:91af74a299e1 52 timer=1;
pspatel321 30:91af74a299e1 53 pin=1;
pspatel321 30:91af74a299e1 54 timerBase=LPC_TIM1;
pspatel321 30:91af74a299e1 55 } else if (cmpPin(_pin, p0_4)) { // CAP2.0
pspatel321 30:91af74a299e1 56 timer=2;
pspatel321 30:91af74a299e1 57 pin=0;
pspatel321 30:91af74a299e1 58 timerBase=LPC_TIM2;
pspatel321 30:91af74a299e1 59 } else if (cmpPin(_pin, p0_5)) { // CAP2.1
pspatel321 30:91af74a299e1 60 timer=2;
pspatel321 30:91af74a299e1 61 pin=1;
pspatel321 30:91af74a299e1 62 timerBase=LPC_TIM2;
pspatel321 30:91af74a299e1 63 } else if (cmpPin(_pin, p0_23)) { // CAP3.0
pspatel321 30:91af74a299e1 64 timer=3;
pspatel321 30:91af74a299e1 65 pin=0;
pspatel321 30:91af74a299e1 66 timerBase=LPC_TIM3;
pspatel321 30:91af74a299e1 67 } else if (cmpPin(_pin, p0_24)) { // CAP3.1
pspatel321 30:91af74a299e1 68 timer=3;
pspatel321 30:91af74a299e1 69 pin=1;
pspatel321 30:91af74a299e1 70 timerBase=LPC_TIM3;
pspatel321 30:91af74a299e1 71 } else { // Invalid pin
pspatel321 30:91af74a299e1 72 timerBase=0;
pspatel321 30:91af74a299e1 73 pin=0;
pspatel321 30:91af74a299e1 74 timer=0;
pspatel321 30:91af74a299e1 75 return;
pspatel321 30:91af74a299e1 76 }
pspatel321 30:91af74a299e1 77
pspatel321 30:91af74a299e1 78 instance[timer] = this;
pspatel321 30:91af74a299e1 79 first = true;
pspatel321 30:91af74a299e1 80
pspatel321 30:91af74a299e1 81 startTime = 0;
pspatel321 30:91af74a299e1 82 widthTicks = 0; // Zero low, so that duty = 0/1 = 0%
pspatel321 30:91af74a299e1 83 periodTicks = 1;
pspatel321 30:91af74a299e1 84
pspatel321 30:91af74a299e1 85 // Enable power and set pclk at 24Mhz
pspatel321 30:91af74a299e1 86 if (timer==0) {
pspatel321 30:91af74a299e1 87 LPC_SC->PCONP |= (1<<1);
pspatel321 30:91af74a299e1 88 LPC_SC->PCLKSEL0 &= ~(3<<2);
pspatel321 30:91af74a299e1 89 } if (timer==1) {
pspatel321 30:91af74a299e1 90 LPC_SC->PCONP |= (1<<2);
pspatel321 30:91af74a299e1 91 LPC_SC->PCLKSEL0 &= ~(3<<4);
pspatel321 30:91af74a299e1 92 } if (timer==2) {
pspatel321 30:91af74a299e1 93 LPC_SC->PCONP |= (1<<22);
pspatel321 30:91af74a299e1 94 LPC_SC->PCLKSEL1 &= ~(3<<12);
pspatel321 30:91af74a299e1 95 } if (timer==3) {
pspatel321 30:91af74a299e1 96 LPC_SC->PCONP |= (1<<23);
pspatel321 30:91af74a299e1 97 LPC_SC->PCLKSEL1 &= ~(3<<14);
pspatel321 30:91af74a299e1 98 }
pspatel321 30:91af74a299e1 99
pspatel321 30:91af74a299e1 100 *(_pin.pinsel_addr) |= 3 << _pin.selmode_num; // Set pin as capture pin
pspatel321 30:91af74a299e1 101 *(_pin.pinmode_addr) |= 3 << _pin.selmode_num; // Pull down
pspatel321 30:91af74a299e1 102
pspatel321 30:91af74a299e1 103 timerBase->TCR=2; // Stop counter and hold at 0, for configuration
pspatel321 30:91af74a299e1 104 timerBase->IR=0x3F; // Clear any interrupt flags
pspatel321 30:91af74a299e1 105 timerBase->CTCR=0; // Use pclk, not external pin
pspatel321 30:91af74a299e1 106 timerBase->PR=0; // No prescale value, clock at full pclk=24Mhz
pspatel321 30:91af74a299e1 107 timerBase->EMR=0; // Do not use external match pins
pspatel321 30:91af74a299e1 108
pspatel321 30:91af74a299e1 109 if (timer == 0) NVIC_SetVector(TIMER0_IRQn, (uint32_t)&tim0_IRQ); // Set irq handler for timer0
pspatel321 30:91af74a299e1 110 if (timer == 1) NVIC_SetVector(TIMER1_IRQn, (uint32_t)&tim1_IRQ); // Set irq handler for timer1
pspatel321 30:91af74a299e1 111 if (timer == 2) NVIC_SetVector(TIMER2_IRQn, (uint32_t)&tim2_IRQ); // Set irq handler for timer2
pspatel321 30:91af74a299e1 112 if (timer == 3) NVIC_SetVector(TIMER3_IRQn, (uint32_t)&tim3_IRQ); // Set irq handler for timer3
pspatel321 30:91af74a299e1 113
pspatel321 30:91af74a299e1 114 NVIC_EnableIRQ((IRQn_Type)(timer+1));
pspatel321 30:91af74a299e1 115 NVIC_SetPriority((IRQn_Type)(timer+1), 0); // Highest priority (default)
pspatel321 30:91af74a299e1 116
pspatel321 30:91af74a299e1 117 timerBase->CCR = pin?5<<3:5; // Generate interrupt on rising edge of capture pin
pspatel321 30:91af74a299e1 118 timerBase->MCR = 1; // Interrupt on MR0 to establish the zero speed timeout
pspatel321 30:91af74a299e1 119 zeroIRQ(); // Zero the values
pspatel321 30:91af74a299e1 120 timerBase->TCR = 1; // Start counting, GO!
pspatel321 30:91af74a299e1 121 }
pspatel321 30:91af74a299e1 122
pspatel321 30:91af74a299e1 123 void IMD::edgeIRQ() {
pspatel321 30:91af74a299e1 124 bool rising = pin?timerBase->CCR&(1<<3):timerBase->CCR&1;
pspatel321 30:91af74a299e1 125 uint32_t capTime = pin?timerBase->CR1:timerBase->CR0; // Get the time of the capture event
pspatel321 30:91af74a299e1 126 timerBase->MR0 = capTime + TIMEOUT_TICKS; // Move the zero timeout ahead
pspatel321 30:91af74a299e1 127
pspatel321 30:91af74a299e1 128 // Special case - on first pulse after a timeout or on startup, period cannot be calculated
pspatel321 30:91af74a299e1 129 // so set startTime such that periodTicks remains unchanged from its zero state (periodTicks=1)
pspatel321 30:91af74a299e1 130 if (first) {
pspatel321 30:91af74a299e1 131 first = false;
pspatel321 30:91af74a299e1 132 startTime = capTime - 1;
pspatel321 30:91af74a299e1 133 }
pspatel321 30:91af74a299e1 134 if (rising) {
pspatel321 30:91af74a299e1 135 periodTicks = capTime - startTime; // Get the period on Rising edge
pspatel321 30:91af74a299e1 136 startTime = capTime; // Set the start of the next pulse
pspatel321 30:91af74a299e1 137 } else {
pspatel321 30:91af74a299e1 138 widthTicks = capTime - startTime; // Get the pulse width on Falling edge
pspatel321 30:91af74a299e1 139 }
pspatel321 30:91af74a299e1 140
pspatel321 30:91af74a299e1 141 // Switch interrupt types to capture the next edge
pspatel321 30:91af74a299e1 142 if (rising) timerBase->CCR = pin?6<<3:6;
pspatel321 30:91af74a299e1 143 else timerBase->CCR = pin?5<<3:5;
pspatel321 30:91af74a299e1 144 }
pspatel321 30:91af74a299e1 145
pspatel321 30:91af74a299e1 146 void IMD::zeroIRQ() {
pspatel321 30:91af74a299e1 147 periodTicks = 1;
pspatel321 30:91af74a299e1 148 first = true; // Reset the first edge detection case
pspatel321 30:91af74a299e1 149
pspatel321 30:91af74a299e1 150 bool rising = pin?timerBase->CCR&(1<<3):timerBase->CCR&1;
pspatel321 30:91af74a299e1 151 // Timeout occurred after FALLING edge, RISING edge never happened
pspatel321 30:91af74a299e1 152 if (rising) {
pspatel321 30:91af74a299e1 153 widthTicks = 0; // Signal is low = 0/1 = 0% duty
pspatel321 30:91af74a299e1 154 } else {
pspatel321 30:91af74a299e1 155 widthTicks = 1; // Signal is high = 1/1 = 100% duty
pspatel321 30:91af74a299e1 156 }
pspatel321 30:91af74a299e1 157 }
pspatel321 30:91af74a299e1 158 float IMD::frequency() {
pspatel321 30:91af74a299e1 159 // Handle the case where we want to say 0Hz not infinity Hz
pspatel321 30:91af74a299e1 160 if (periodTicks == 1 || periodTicks == 0) return 0;
pspatel321 30:91af74a299e1 161 else return (float)(PCLK)/(float)(periodTicks);
pspatel321 30:91af74a299e1 162 }
pspatel321 30:91af74a299e1 163 float IMD::duty() {
pspatel321 30:91af74a299e1 164 return (float)(widthTicks)/(float)(periodTicks);
pspatel321 30:91af74a299e1 165 }
pspatel321 30:91af74a299e1 166
pspatel321 30:91af74a299e1 167 char IMD::status() {
pspatel321 30:91af74a299e1 168 float freq = frequency();
pspatel321 30:91af74a299e1 169 if (freq == 0) return OFF; // IMD off
pspatel321 30:91af74a299e1 170 else if (05 < freq && freq <= 15) return NORMAL; // 10Hz normal mode
pspatel321 30:91af74a299e1 171 else if (15 < freq && freq <= 25) return UNDERVOLT; // 20Hz undervoltage mode
pspatel321 30:91af74a299e1 172 else if (25 < freq && freq <= 35) return SPEEDSTART; // 30Hz speed start mode
pspatel321 30:91af74a299e1 173 else if (35 < freq && freq <= 45) return ERROR; // 40Hz IMD error
pspatel321 30:91af74a299e1 174 else if (45 < freq && freq <= 55) return GROUNDERR; // 50Hz Ground error
pspatel321 30:91af74a299e1 175 else return INVALID; // Invalid
pspatel321 30:91af74a299e1 176 }
pspatel321 30:91af74a299e1 177
pspatel321 30:91af74a299e1 178 float IMD::resistance() {
pspatel321 30:91af74a299e1 179 char stat = status();
pspatel321 30:91af74a299e1 180 float dut = duty();
pspatel321 30:91af74a299e1 181
pspatel321 30:91af74a299e1 182 // In normal or undervoltage mode, where Rf is available
pspatel321 30:91af74a299e1 183 if (stat == NORMAL || stat == UNDERVOLT) {
pspatel321 30:91af74a299e1 184 if (0.05-EXTRA <= dut && dut <= 0.95+EXTRA) {
pspatel321 30:91af74a299e1 185 if (dut > 0.95) dut = 0.95; // Ceiling
pspatel321 30:91af74a299e1 186 if (dut < 0.05) dut = 0.05; // Floor so it doesnt mess up the equation below
pspatel321 30:91af74a299e1 187 float rf = (0.9*1200e3/(dut-0.05)) - 1200e3;
pspatel321 30:91af74a299e1 188 if (rf < 1000) rf = 0; // Floor to hit 0
pspatel321 30:91af74a299e1 189 if (rf > 50e6) rf = 50e6; // Ceil to stay at 50e6
pspatel321 30:91af74a299e1 190 return rf;
pspatel321 30:91af74a299e1 191 }
pspatel321 30:91af74a299e1 192 else return NAN;
pspatel321 30:91af74a299e1 193 }
pspatel321 30:91af74a299e1 194 // In speed start, where only good/bad estimate is available
pspatel321 30:91af74a299e1 195 if (stat == SPEEDSTART) {
pspatel321 30:91af74a299e1 196 if (0.05-EXTRA <= dut && dut <= 0.10+EXTRA) return 50e6; // Good
pspatel321 30:91af74a299e1 197 else if (0.90-EXTRA <= dut && dut <= 0.95+EXTRA) return 0; // Bad
pspatel321 30:91af74a299e1 198 else return NAN;
pspatel321 30:91af74a299e1 199 }
pspatel321 30:91af74a299e1 200 return NAN; // Measurement not available in this mode
pspatel321 30:91af74a299e1 201 }