Dependencies:   ros_lib_kinetic

LLComms.cpp

Committer:
dofydoink
Date:
2018-12-14
Revision:
23:61526647cc8a
Parent:
22:82871f00f89d
Child:
24:bc852aa89e7a

File content as of revision 23:61526647cc8a:

// LLComms.cpp

#include "LLComms.h"

LLComms::LLComms() : 
    queue(32 * EVENTS_EVENT_SIZE), //32 //8 * EVENTS_EVENT_SIZE
    pinGate6(PE_11),
    spi_0(PC_12, PC_11, PC_10),
    spi_1(PF_9, PF_8, PF_7),
    pinCheck(PE_5),
    // These interrupt pins have to be declared AFTER SPI declaration. No Clue Why.
    pinGate0(PF_11),
    pinGate1(PG_14),
    pinGate2(PF_15),
    pinGate3(PF_12),
    pinGate4(PF_3),
    pinGate5(PF_13),
    //pinGate6(PE_11), // See above nonsense
    pinGate7(PE_13),
    pinReset(PD_2)
{ // Constructor

    PinName LLPins[8] = {PD_15, PE_10, PD_11, PD_14, PE_7, PD_12, PF_10, PD_13};
    //PinName LLPins[8] = {PD_15, PE_10, PD_14, PD_11, PE_7, PD_12, PF_10, PD_13};
    PinName ADCPins[8] = {PG_12, PG_9, PE_1, PG_0, PD_0, PD_1, PF_0, PF_1};
    for (short int i = 0; i < 8; i++) {
        isDataReady[i] = 0;
        cs_LL[i] = new DigitalOut(LLPins[i]);
        cs_ADC[i] = new DigitalOut(ADCPins[i]);
    }
    
    // Initialise relevant variables
    for(short int i = 0; i<N_CHANNELS; i++) {
        // All chip selects in off state
        *cs_LL[i] = 1;
        *cs_ADC[i] = 1;
    }
    pinReset = 1; // Initialise reset pin to not reset the controllers.
    wait(0.25);
    pinReset=0; // Reset controllers to be safe
    wait(0.25);
    pinReset = 1; // Ready to go
    
    // Set up rise interrupts MIGHT NOT NEED TO BE POINTERS
    pinGate0.rise(callback(this,&LLComms::rise0));
    pinGate1.rise(callback(this,&LLComms::rise1));
    pinGate2.rise(callback(this,&LLComms::rise2));
    pinGate3.rise(callback(this,&LLComms::rise3));
    pinGate4.rise(callback(this,&LLComms::rise4));
    pinGate5.rise(callback(this,&LLComms::rise5));
    pinGate6.rise(callback(this,&LLComms::rise6));
    pinGate7.rise(callback(this,&LLComms::rise7));
    // Set up fall interrupts MIGHT NOT NEED TO BE POINTERS
    pinGate0.fall(callback(this,&LLComms::fall0));
    pinGate1.fall(callback(this,&LLComms::fall1));
    pinGate2.fall(callback(this,&LLComms::fall2));
    pinGate3.fall(callback(this,&LLComms::fall3));
    pinGate4.fall(callback(this,&LLComms::fall4));
    pinGate5.fall(callback(this,&LLComms::fall5));
    pinGate6.fall(callback(this,&LLComms::fall6));
    pinGate7.fall(callback(this,&LLComms::fall7));
}

//LLComms::~LLComms(void) { } // Destructor

void LLComms::SendReceiveData(int channel) {
    //pinTesty = 1;
    int intPosSPI_Rx[N_CHANNELS]; // 16bit position value received over SPI from the actuator 
    int intPresSPI_Rx[N_CHANNELS]; // 16bit pressure value received over SPI from the actuator 
    int intSumPosition=0;
    int intSumVelocity=0;
    int intPositionParity, intVelocityParity;
    unsigned int intParityPosition, intParityVelocity, intPositionMsg, intVelocityMsg;

    unsigned int count = 0, i, b = 1;
    
    int intTempVar;
    
    mutChannel[channel].lock(); // Lock mutex for specific Channel
    //construct Position message
    intPositionMsg = demandPosition[channel];
    
    //calculate the sum of the position data 

    intTempVar = demandPosition[channel];
    
    while (intTempVar >0)
    {
        intSumPosition += intTempVar%10;
        intTempVar = int(intTempVar/10);
    }
    
    //add to message
    intPositionMsg = intPositionMsg<<5;
    intPositionMsg = intPositionMsg | intSumPosition;
    
    //add type bit (0 == position, 1 == velocity)
    intPositionMsg = intPositionMsg<<1;
    
    //calculate decimal parity on whole message
 
    for(i = 0; i < 32; i++){
        if( intPositionMsg & (b << i) ){count++;}
    }

    if( (count % 2) ){ intPositionParity = 0;}
    else {intPositionParity = 1;}
    
    //add parity bit to message
    intPositionMsg = intPositionMsg<<1;
    intPositionMsg = intPositionMsg | intPositionParity;
    
    //
    //rinse and repeat for velocity message
    intVelocityMsg = demandSpeed[channel];
    
    //calculate the sum of the position data 

    intTempVar = demandSpeed[channel];
    
    while (intTempVar >0)
    {
        intSumVelocity += intTempVar%10;
        intTempVar = int(intTempVar/10);
    }
    
    //add to message
    intVelocityMsg = intVelocityMsg<<5;
    intVelocityMsg = intVelocityMsg | intSumVelocity;
    
    //add type bit (0 == position, 1 == velocity)
    intVelocityMsg = intVelocityMsg<<1;
    intVelocityMsg = intVelocityMsg |1;
    
    //calculate decimal parity on whole message
 
    for(i = 0; i < 32; i++){
        if( intVelocityMsg & (b << i) ){count++;}
    }

    if( (count % 2) ){ intVelocityParity = 0;}
    else {intVelocityParity = 1;}
    
    //add parity bit to message
    intVelocityMsg = intVelocityMsg<<1;
    intVelocityMsg = intVelocityMsg | intVelocityParity;
    
    //Combine
    
    
    // Get data from controller
    if( channel < 4 ) {
        spi_0.format(16,2); // !! Can probably move to constructor 
        spi_0.frequency(LOW_LEVEL_SPI_FREQUENCY);
        *cs_LL[channel] = 0; // Select relevant chip
        intPosSPI_Rx[channel] = spi_0.write(intPositionMsg); // Transmit & receive
        
        intPresSPI_Rx[channel] = intPosSPI_Rx[channel] | spi_0.write(intVelocityMsg); // Transmit & receive
        *cs_LL[channel] = 1; // Deselect chip
    } else {
        spi_1.format(16,2); // !! Can probably move to constructor 
        spi_1.frequency(LOW_LEVEL_SPI_FREQUENCY);
        *cs_LL[channel] = 0; // Select relevant chip
        intPosSPI_Rx[channel] = spi_0.write(intPositionMsg); // Transmit & receive
        
        intPresSPI_Rx[channel] = intPosSPI_Rx[channel] | spi_0.write(intVelocityMsg); // Transmit & receive
        *cs_LL[channel] = 1; // Deselect chip
    }
    isDataReady[channel] = 0; // Data no longer ready, i.e. we now require new data
    /*if(channel == 0) {
        intGlobalTest = intPosSPI_Rx[channel];
        dblGlobalTest = ((double) (intPosSPI_Rx[channel])/8191.0*52.2);
    }*/
    
    // Sort out received data
    //STILL TO DO!!!!!!

    intPosSPI_Rx[channel] = intPosSPI_Rx[channel]>>7 & 0x1FF;
    dblPosition_mtrs[channel] = (double)intPosSPI_Rx[channel]/511*(MAX_ACTUATOR_LENGTH/DBL_ACTUATOR_CONVERSION[channel])/1000;
    mutChannel[channel].unlock();//unlock mutex for specific channel
}

// Common rise handler function 
void LLComms::common_rise_handler(int channel) {
    pinCheck = 1;
    if (isDataReady[channel]) { // Check if data is ready for tranmission
        ThreadID[channel] = queue.call(this,&LLComms::SendReceiveData,channel); // Schedule transmission
    }
}

// Common fall handler functions
void LLComms::common_fall_handler(int channel) {
    pinCheck = 0;
    queue.cancel(ThreadID[channel]); // Cancel relevant queued event
}

// Stub rise functions
void LLComms::rise0(void) { common_rise_handler(0); }
void LLComms::rise1(void) { common_rise_handler(1); }
void LLComms::rise2(void) { common_rise_handler(2); }
void LLComms::rise3(void) { common_rise_handler(3); }
void LLComms::rise4(void) { common_rise_handler(4); }
void LLComms::rise5(void) { common_rise_handler(5); }
void LLComms::rise6(void) { common_rise_handler(6); }
void LLComms::rise7(void) { common_rise_handler(7); }
// Stub fall functions
void LLComms::fall0(void) { common_fall_handler(0); }
void LLComms::fall1(void) { common_fall_handler(1); }
void LLComms::fall2(void) { common_fall_handler(2); }
void LLComms::fall3(void) { common_fall_handler(3); }
void LLComms::fall4(void) { common_fall_handler(4); }
void LLComms::fall5(void) { common_fall_handler(5); }
void LLComms::fall6(void) { common_fall_handler(6); }
void LLComms::fall7(void) { common_fall_handler(7); }

// NEEDS CALIBRATING
double LLComms::ReadADCPosition_mtrs(int channel) {
    unsigned int outputA;
    unsigned int outputB;
    int output;
    double dblOutput;

    if( channel < 4 ) {
        spi_0.format(8,0);
        spi_0.frequency(1000000);
        
        *cs_ADC[channel] = 0;
        spi_0.write(PREAMBLE);
        outputA = spi_0.write(CHAN_3);
        outputB = spi_0.write(0xFF);
        *cs_ADC[channel] = 1;
    } else {
        spi_1.format(8,0);
        spi_1.frequency(1000000);
        
        *cs_ADC[channel] = 0;
        spi_1.write(PREAMBLE);
        outputA = spi_1.write(CHAN_3);
        outputB = spi_1.write(0xFF);
        *cs_ADC[channel] = 1;
    }
    
    outputA = outputA & DATA_MASK;
    outputA = outputA<<8;
    output = (outputA | outputB);
    output = 4095- output;
    dblOutput = (double) (output);
    dblOutput = dblOutput*0.0229 - 21.582;
    return dblOutput;
}
    
double LLComms::ReadADCPressure_bar(int channel) {
    unsigned int outputA;
    unsigned int outputB;
    int output;
    double dblOutput;

    if( channel < 4 ) {
        spi_0.format(8,0);
        spi_0.frequency(1000000);
        
        *cs_ADC[channel] = 0;
        spi_0.write(PREAMBLE);
        outputA = spi_0.write(CHAN_1);
        outputB = spi_0.write(0xFF);
        *cs_ADC[channel] = 1;
    } else {
        spi_1.format(8,0);
        spi_1.frequency(1000000);
        
        *cs_ADC[channel] = 0;
        spi_1.write(PREAMBLE);
        outputA = spi_1.write(CHAN_1);
        outputB = spi_1.write(0xFF);
        *cs_ADC[channel] = 1;
    }
    
    outputA = outputA & DATA_MASK;
    outputA = outputA<<8;
    output = (outputA | outputB);
    
    dblOutput = (double)(output);
    dblOutput = dblOutput-502.0;
    dblOutput = dblOutput/4095.0*8.0;
    return dblOutput;
}