Penn Electric Racing / Mbed 2 deprecated SystemManagement

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

SysMngmt.cpp

Committer:
martydd3
Date:
2014-10-07
Revision:
3:1345f882d8f3
Parent:
2:baeb80c778f7
Child:
4:e31528929150

File content as of revision 3:1345f882d8f3:

/*
    Reads CAN Messages and various data inputs, outputs using Xbee radio modules

    Revised Sept 30, 2014: Began analyzing and commenting program, trying to figure out what the hell it does (Martin Deng)
*/

#include"SysMngmt.h"
#include"Get_IMD.h"
#include"PollSwitch.h"
#include"TemperatureRead.h"
#include"Store_RTC.h"
#include"XBee_Lib.h"
#include"CANBuffer.h"

#include"mbed.h"
#include"rtos.h"

//Possible problems in IMD coz change of counter
//Possible problems in BatteryStatus coz change in library

/*

Attach Ticker every 10msec to 
Get IMD
Poll Switches
Temperature Read
Get Battery State
End Ticker Send message through CAN

CAN interrupt Rx Interrupt
Recieve CAN message into a buffer. Return
Buffer values(as long as !empty) -> SD Card, Xbee -> remove element

extern "C" void CAN_IRQHandler(void)
{
    CANMessage Rxmsg;
    CAN_SysM.read(Rxmsg);
    RecieveBuffer.add(Rxmsg);
}

    http://developer.mbed.org/users/AjK/notebook/getting-closer-to-the-hardware/
    
    extern "C" means this is linked assuming it's C code
    C++ linker appearently adds extra crap with the function arguments keeping functions of this kind from linking properly
    
    Interrupt handler, This is probably linked to the Timer 2 interrupt request somewhere by the libraries

extern "C" void TIMER2_IRQHandler(void)
{
    if((LPC_TIM2->IR & 0x01) == 0x01) // if MR0 interrupt
    {
        // This probably shouldn't be here, never have a printf() in an interrupt, locks up the main thread
        // printf("Every 1ms\n\r");
        
        LPC_TIM2->IR |= 1 << 0; // Clear MR0 interrupt flag
        
        // gonna hope all these calculations are correct
        // writes to RTC store, but there's no read code here
        // 2 misleading things. First, RTC store writes to a general purpose register
        // secondly, no code reads from this register in this .cpp, but maybe some other code does
        
        Bat_I_Ratio=BatISense.read();
        BATA_msec=(((Bat_I_Ratio*3.3) - BAT_ISENSE_OFFSET_V)/BAT_ISENSE_INCREMENT);
        BATmA_Hr+=(BATA_msec*MSEC_HRS);
        store.write(BATmA_Hr,0);
                
        DC_I_Ratio=DCSense.read(); 
        DCA_msec=(((DC_I_Ratio*3.3) - DC_DC_ISENSE_OFFSET_V)/DC_DC_ISENSE_INCREMENT);
        store.write(DCA_msec,1);
        
        LPC_TIM2->TCR       |=  (1<<1);                     //Reset Timer1
        LPC_TIM2->TCR       &=  ~(1<<1);                    //Re Enable Timer1   
    }
}    

    Appears to read a whole bunch of DigitalOut pins in void PollSwitch(), store the value in uint16_t Rxpoll,
    and write the result to the CAN bus

void Poll()
{
    uint16_t Rxpoll;
    uint16_t recv,temp,i=0;              //Test
    char Result[4]={0};
    Rxpoll=PollSwitch();
    
    Result[0]=(char)(Rxpoll&0x00ff);
    Result[1]=(char)((Rxpoll&0xff00)>>8);    
    CANMessage Txmsg(410,Result,sizeof(Result));
    CAN_SysM.write(Txmsg);
    
    //Test
    recv=(((uint16_t)Txmsg.data[1]<<8) | (0x00ff&(uint16_t)Txmsg.data[0]));
    printf("Recv:%d\n\r",recv);
    
    while(i <= 12)
    {
        temp=recv;
        if(((temp & (1 << i))>>i)==1)
            pc.printf("Switch OFF:%d\n\r",i);
        ++i;
    }
}    


void Temp()
{
    float DC_DC_Temperature, Coolant1_Temperature, Coolant2_Temperature, ChargerFET_Temperature;
    float Resistance;
    float Vadc;
    int i;
    ftc send, recv;
    recv.FLOAT=0.0;
    send.FLOAT=0.0;
        
    Vadc=DC_DC.read()*VDD;
    Resistance=((float)R10K*Vadc)/((float)VDD + Vadc);
    DC_DC_Temperature=ReadTemp(TR_NXFT15XH103FA_Map, Resistance, TABLE_SIZE_NXFT15XH103FA); 
    send.FLOAT=DC_DC_Temperature;
    CANMessage Txmsg_DC_DC(450,send.C_FLOAT,sizeof(send.C_FLOAT));
    CAN_SysM.write(Txmsg_DC_DC);
    
    for(i=0; i<4;i++)
        recv.C_FLOAT[i]=Txmsg_DC_DC.data[i];
    pc.printf("DC_DC:%f\n\r",recv.FLOAT);
    
    Vadc=ChargerFET.read()*VDD;
    Resistance=((float)R10K*Vadc)/((float)VDD + Vadc);
    ChargerFET_Temperature=ReadTemp(TR_NXFT15XH103FA_Map, Resistance, TABLE_SIZE_NXFT15XH103FA);       
    send.FLOAT=ChargerFET_Temperature;
    CANMessage Txmsg_ChargerFET(451,send.C_FLOAT,sizeof(send.C_FLOAT));
    CAN_SysM.write(Txmsg_ChargerFET);
    
    for(i=0; i<4;i++)
        recv.C_FLOAT[i]=Txmsg_ChargerFET.data[i];
    pc.printf("ChargerFET:%f\n\r",recv.FLOAT);
    
    Vadc=Coolant1.read()*VDD;
    Resistance=((float)R10K*Vadc)/((float)VDD + Vadc);
    Coolant1_Temperature=ReadTemp(TR_NTCLP00E3103H_Map, Resistance, TABLE_SIZE_NTCLP00E3103H);
    send.FLOAT=Coolant1_Temperature;
    CANMessage Txmsg_Coolant1(452,send.C_FLOAT,sizeof(send.C_FLOAT));
    CAN_SysM.write(Txmsg_Coolant1);
    //Control Fans
    
    for(i=0; i<4;i++)
        recv.C_FLOAT[i]=Txmsg_Coolant1.data[i];
    pc.printf("Coolant1:%f\n\r",recv.FLOAT);
    
    Vadc=Coolant2.read()*VDD;
    Resistance=((float)R10K*Vadc)/((float)VDD + Vadc);
    Coolant2_Temperature=ReadTemp(TR_NTCLP00E3103H_Map, Resistance, TABLE_SIZE_NTCLP00E3103H);   
    send.FLOAT=Coolant2_Temperature;
    CANMessage Txmsg_Coolant2(453,send.C_FLOAT,sizeof(send.C_FLOAT));
    CAN_SysM.write(Txmsg_Coolant2);
    //Control Fans
    
    for(i=0; i<4;i++)
        recv.C_FLOAT[i]=Txmsg_Coolant2.data[i];
    pc.printf("Coolant2:%f\n\r",recv.FLOAT);
}    

void IMD()
{
    IMD_Measurement_Output IMD_Signal;
    char status[4];
    ftc send;
    
    IMD_Signal=Get_Measurement();
    send.FLOAT=IMD_Signal.Frequency;
    CANMessage Txmsg_Frequency(421,send.C_FLOAT,sizeof(send.C_FLOAT));
    CAN_SysM.write(Txmsg_Frequency);
    
    send.FLOAT=IMD_Signal.Duty_Cycle;
    CANMessage Txmsg_DutyCycle(422,send.C_FLOAT,sizeof(send.C_FLOAT));
    CAN_SysM.write(Txmsg_DutyCycle);
    
    status[0]=Result.Encoded_Status;
    CANMessage Txmsg_Status(423,status,sizeof(status));
    CAN_SysM.write(Txmsg_Status);
}    

void Battery()
{
    RTCStore reg;
    ftc send;

    send.FLOAT=reg.read(0);
    CANMessage Txmsg_BATmA_Hr(440,send.C_FLOAT,sizeof(send.C_FLOAT));
    CAN_SysM.write(Txmsg_BATmA_Hr);
    
    send.FLOAT=reg.read(1);
    CANMessage Txmsg_DCA_msec(442,send.C_FLOAT,sizeof(send.C_FLOAT));     
    CAN_SysM.write(Txmsg_DCA_msec);
}    

    Activates a whole crapload of functions and pins on the chip

void Init()
{   
    
        Timers to call various functions at different intervals
        These things behave weirdly when wait(ms) is involved. Probably have to rewrite

    
    //ReadIMD.attach(&IMD,0.1);
    //PollSDSwitch.attach(&Poll,0.1);
    
    //ReadTemperature.attach(&Temp,0.1);
    //ReadBatteryState.attach(&Battery,0.1);
    

        Initialize Timer2 for Battery State
        
        LPC_SC                      0x400F C000 (System Control)
        ->PCONP                     0x400F C0C4 (Power Control for Peripherals Register) 
        |= (1<<22)                  22 Bit (Timer 2 power/clock control bit)
        
        ->PCLKSEL1                  Peripheral Clock Selection register 1 (controls rate of clock signal supplied to peripheral)
        |= ((1<<12) | (1<<13));     12:13 Bits (Peripheral Clock Selection for TIMER2)
        
        LPC_TIM2                    0x4009 0000 (Timer 2)
        ->TCR                       0x4009 0004 (Timer Control Register)
        |= (1<<0);                  0 Bit (Counter Enable)
        
        ->MR0                       0x4009 0018 (Match Register)
        
        ->MCR                       0x4009 0014 (Match Control Register) What to do when Match Register matches the Timer Counter
        |= (1<<0);                  0 Bit (Interrupt on MR0, interrupt generated when MR0 matches the value in TC)
        

    LPC_SC->PCONP       |= (1<<22);                     //PoewerOn Timer/Counter2
    LPC_SC->PCLKSEL1    |= ((1<<12) | (1<<13));         //Prescale Timer2 CCLK/8  
    LPC_TIM2->TCR       |=  (1<<0);                     //Enable Timer2
    LPC_TIM2->MR0       =   11999;                      // 1msec
    LPC_TIM2->MCR       |=  (1<<0);

        Nested Vectored Interrupt Controller (NVIC)
        
        NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
            sets priority of an interrupt
        
        IRQn_Type
            Interrupt number definitions
            Interrupt Request (IRQ)
        
        NVIC_EnableIRQ(IRQn_Type IRQn)
            Enable external interrupt (in this case, the TIMER2_IRQHandler(void) function above gets called every time
            Timer2 generates an interrupt signal)
            

    NVIC_SetPriority(TIMER0_IRQn,200);                  //IMD Capture Interrupt
    NVIC_SetPriority(TIMER1_IRQn,200);                  //IMD 1msec sampling Interrupt
    NVIC_SetPriority(TIMER2_IRQn,1);                    //Battery 1msec sampling Interrupt
    NVIC_SetPriority(TIMER3_IRQn,255);                  //mbed Timer/Ticker/Wait Interrupt
    NVIC_SetPriority(CAN_IRQn,2);
    
    NVIC_EnableIRQ(TIMER2_IRQn);                        //Enable TIMER2 IRQ 
    
    CAN_SysM.mode(CAN::GlobalTest);
    

    //NVIC_EnableIRQ(CAN_IRQn);
    //NVIC_EnableIRQ(CANActivity_IRQn);
}    


    Main Loop: Currently reads CANMessages from Can interface (Pins: rd = p30, td = p29)
    Send CANMessage data through XBee radio transmitters
*/


CANBuffer rxBuffer(CAN1, MEDIUM);
XBee250x XbeeTx;

int sysCANId = 0;                   // change this later

char fanId = 0;                     // first byte of CANData, last byte states the duty cycle, second-last states which fan to control

Thread *fan_Threads[4] = {NULL, NULL, NULL, NULL};     // Threads currently running on the 4 output pins

/*
    Pins for Fans and Pumps
    PUMP_PWM = p2.0
    FAN1_PWM = p2.1
    FAN2_PWM = p2.2
    FAN3_PWM = p2.3
*/

PwmOut pump_pwm(P2_0);
PwmOut fan1_pwm(P2_1);
PwmOut fan2_pwm(P2_2);
PwmOut fan3_pwm(P2_3);

// duty goes from 0 to 100
void rampFans(void const *arg){
    
    static int fan1_duty = 0;
    static int fan2_duty = 0;
    static int fan3_duty = 0;
    static int pump_duty = 0;
    
    int *data = (int *)arg;
    
    int duty = data[7];
    if(duty < 0 || duty > 100)
        return;
    
    int pin_ID = data[6];
    int *cur_duty;
    PwmOut *out_pin;
    
    switch(pin_ID){
        case 0: cur_duty = &pump_duty;
            out_pin = &pump_pwm;
            break;
        case 1: cur_duty = &fan1_duty;
            out_pin = &fan1_pwm;
            break;
        case 2: cur_duty = &fan2_duty;
            out_pin = &fan2_pwm;
            break;
        case 3: cur_duty = &fan3_duty;
            out_pin = &fan3_pwm;
            break;
        default:
            return;
    }
    
    while(*cur_duty != duty){
        
        if(duty > *cur_duty){
            *cur_duty += 10;
            
            if(*cur_duty > duty)
                *cur_duty = duty;   
        } else if(duty < *cur_duty){
            *cur_duty -= 10;
            
            if(*cur_duty < duty)
                *cur_duty = duty;   
        }
        
        out_pin->write((*cur_duty)*0.01);
        
        Thread::wait(10);
    }
}

char dcCANId = 1;                   // first byte of CANData, last byte states whether to toggle on (1) or off (0)
DigitalOut dcPin(p20);

void toggleDC_DC(bool toggle){
    static bool dc_on = false;
    
    //dcPin turns on DC_DC converter when 0, off when 1
    
    if(toggle && !dc_on){
        dcPin = 0;
        dc_on = true;
    } else if(!toggle && dc_on){
        dcPin = 1;
        dc_on = false;   
    }
}

int main() {
    CANMessage rx_msg;    

    //turn off DC-DC converter on startup
    toggleDC_DC(false);

    while(1)
    {
        if(rxBuffer.rxRead(rx_msg) && rx_msg.id == sysCANId){
            if(rx_msg.data[0] == fanId){
                
                int pin_id = (int)rx_msg.data[6];
                
                if(pin_id < 4 && pin_id >= 0 && fan_Threads[pin_id] != NULL){
                    fan_Threads[pin_id]->terminate();
                    free(fan_Threads[pin_id]);
                }
                
                fan_Threads[pin_id] = new Thread(rampFans, rx_msg.data);
            }
            if(rx_msg.data[0] == dcCANId){
                toggleDC_DC((bool)rx_msg.data[7]);   
            }
        }
    }
}