System Management code

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers FanPump.cpp Source File

FanPump.cpp

00001 #include "FanPump.h"
00002 
00003 #define S_ATOMIC __disable_irq();
00004 #define E_ATOMIC __enable_irq();
00005 
00006 static FanPump* instance[6] = { NULL };      // Access pwm object by channel#
00007 const int PCLK = 24e6;                       // 24Mhz default clock to PWM module
00008 
00009 // Interrupt handler, must be called from static context, calls all the slew functions
00010 void pwmIRQ()
00011 {
00012     int sum = 0, items = 0;
00013     if (LPC_PWM1->IR & 1) {                 // Interrupt pending
00014         for (int i = 0; i < 6; i++) {       // Check every channel
00015             if (instance[i] != NULL) {      // Make sure it exists
00016                 items++;                    // Count each number serviced
00017                 sum += instance[i]->slew(); // Add the return values (1 if nothing was done in function)
00018             }
00019         }
00020     }
00021     LPC_PWM1->IR = 0x73F;                   // Clear interrupt
00022     if (items == sum) {
00023         LPC_PWM1->MCR = 0;  // Disable the interrupts, every duty is already where it needs to be
00024     }
00025 }
00026 
00027 // Called on each timer expire for each pwm object
00028 int FanPump::slew()
00029 {
00030     uint32_t currPulseT = *MR_base;                               // Get the current pulsewidth ticks
00031     uint32_t setPointT = setPoint_us * (PCLK/1e6);                // Convert us into ticks
00032     if (currPulseT == setPointT) return 1;                        // Nothing to slew here, already at its setpoint
00033 
00034     uint32_t currPulse_us = currPulseT / (PCLK/1e6);              // Convert to us
00035     if (currPulseT < setPointT) {
00036         if (setPoint_us - currPulse_us <= maxChange_us) pwm.pulsewidth_us(setPoint_us);  // Close to the setpoint, write it directly
00037         else pwm.pulsewidth_us(currPulse_us + maxChange_us);
00038     } else {
00039         if (currPulse_us - setPoint_us <= maxChange_us) pwm.pulsewidth_us(setPoint_us);  // Close to the setpoint, write it directly
00040         else pwm.pulsewidth_us(currPulse_us - maxChange_us);
00041     }
00042     return 0;
00043 }
00044 
00045 FanPump::FanPump(PinName pin, float period, float slew) : pwm(pin)
00046 {
00047 
00048     // Match the pin# to the PWM object for the interrupt
00049     int channel = 0;
00050     if (pin == p26 || pin == LED1) channel = 1;
00051     if (pin == p25 || pin == LED2) channel = 2;
00052     if (pin == p24 || pin == LED3) channel = 3;
00053     if (pin == p23 || pin == LED4) channel = 4;
00054     if (pin == p22)                channel = 5;
00055     if (pin == p21)                channel = 6;
00056     if (channel == 0) return;     // Invalid pin
00057     instance[channel-1] = this;   // Attach this object to an instance pointer to access from interrupt
00058 
00059     // Set the match register address
00060     if (channel == 1) MR_base = &LPC_PWM1->MR1;
00061     if (channel == 2) MR_base = &LPC_PWM1->MR2;
00062     if (channel == 3) MR_base = &LPC_PWM1->MR3;
00063     if (channel == 4) MR_base = &LPC_PWM1->MR4;
00064     if (channel == 5) MR_base = &LPC_PWM1->MR5;
00065     if (channel == 6) MR_base = &LPC_PWM1->MR6;
00066 
00067     setPoint_us = 0;
00068     period_us = period * 1.0e6;
00069     pwm.period_us(period_us);
00070     pwm = 0;
00071     maxChange_us = (period / slew) * period_us;
00072 
00073     LPC_PWM1->IR = 0x73F;    // Clear interrupts
00074     NVIC_SetVector(PWM1_IRQn, (uint32_t)&pwmIRQ);
00075     NVIC_SetPriority(PWM1_IRQn, 0);
00076     NVIC_EnableIRQ(PWM1_IRQn);
00077 }
00078 
00079 void FanPump::write(float duty)
00080 {
00081     if (duty < 0) duty = 0;
00082     if (duty > 1) duty = 1;
00083     setPoint_us = duty * period_us;
00084     LPC_PWM1->MCR = 1;       // Enable interrupt on MR0 (when the pwm period expires)
00085 }
00086 void FanPump::directOff()
00087 {
00088     S_ATOMIC                 // Ensure that it happens now, no thread-switching
00089     pwm.pulsewidth_us(0);
00090     setPoint_us = 0;
00091     E_ATOMIC
00092 }
00093 float FanPump::read()
00094 {
00095     return (float)(setPoint_us)/(float)(period_us);
00096 }
00097 float FanPump::readRaw()
00098 {
00099     uint32_t currPulseT = *MR_base;    // Get the current pulsewidth ticks
00100     return ((float)(currPulseT) / (float)(PCLK/1e6)) / (float)(period_us);
00101 }