Dependencies:   ros_lib_kinetic

Revision:
26:7c59002c9cd7
Parent:
25:88e6cccde856
Child:
27:6853ee8ffefd
--- a/LLComms.cpp	Mon Dec 17 15:09:44 2018 +0000
+++ b/LLComms.cpp	Mon Jan 28 21:24:48 2019 +0000
@@ -39,6 +39,9 @@
         // All chip selects in off state
         *cs_LL[i] = 1;
         *cs_ADC[i] = 1;
+        // Initialise pressures/positions
+        pressureSensor_bar[i] = -1.0;
+        positionSensor_mm[i] = -1.0;
     }
     pinReset = 1; // Initialise reset pin to not reset the controllers.
     wait(0.25);
@@ -67,8 +70,7 @@
 }
 
 //LLComms::~LLComms(void) { } // Destructor
-
-void LLComms::formatMessage(short int type, double dblValue, double dblMaxValue) {
+unsigned int LLComms::formatMessage(short int type, double dblValue, double dblMaxValue) {
     // Convert to a 9-bit number
     int intValue = (int) ((dblValue/dblMaxValue)*511);
     intValue = intValue & 0x1FF; // Ensure number is 9-bit
@@ -76,7 +78,7 @@
     unsigned int intMsg = intValue;
     // Calculate checksum (the decimal sum of the position data)
     int intCheckSum = 0, intTempVar = intValue;
-    while( intTempVar>0 ) { //591
+    while( intTempVar>0 ) {
         intCheckSum += intTempVar%10;
         intTempVar = floor(intTempVar/10.0);
     }
@@ -85,6 +87,7 @@
     intMsg = intMsg | intCheckSum;
     // Add type bit (0 == position, 1 == velocity)
     intMsg = intMsg<<1;
+    intMsg = intMsg | (int)type; // CAST AS BOOL
     // Calculate decimal parity check for the whole message
     unsigned int count = 0, b = 1;  
     for(short int i=0; i<32; i++) {
@@ -94,46 +97,161 @@
     bool boolParity = !(bool)(count%2);
     intMsg = intMsg<<1;
     intMsg = intMsg | (int)boolParity;
+    //printf("%i \t %i \t %i \t %i \t %i \r\n",type,intValue,intCheckSum,boolParity,intMsg);
+    return intMsg;
+}
+
+bool LLComms::CheckMessage(int msg) {
+    // Find message parity
+    short int count = 0;
+    for(short int i=0; i<32; i++) {
+        if( msg>>1 & (1<<i) ) count++;
+    }
+    int intParity = !(count%2);
+    // Find message CheckSum    
+    int intChkSum = 0;
+    int intTempVar = msg>>7;
+    while(intTempVar > 0) {
+        intChkSum += intTempVar%10;
+        intTempVar = int(intTempVar/10);
+    }
+    // Check if parity and CheckSum match
+    bool isParityCorrect = (intParity == (msg&0x1));
+    bool isChkSumCorrect = (intChkSum == ((msg>>2)&0x1F));
+    bool isCheckPassed = (isParityCorrect && isChkSumCorrect);
+    return isCheckPassed;
+}
+
+bool LLComms::PerformMasterSPI(SPI *spi, unsigned int outboundMsgs[], unsigned int inboundMsgsData[]) {
+    unsigned int dummyMsg = 0x5555;
+    bool isSuccess = true;
+    unsigned int inboundMsg, typeBit;
+    for(short int i=0; i<3; i++) { // Loop 3 times for 3 SPI messages
+        if(i==0) {
+            inboundMsg = spi->write(outboundMsgs[0]);
+        } else if(i==1) {
+            inboundMsg = spi->write(outboundMsgs[1]);
+        } else {
+            inboundMsg = spi->write(dummyMsg);
+        }
+        if((unsigned int)inboundMsg != dummyMsg) { // Message is not dummy which is only used for reply
+            typeBit = inboundMsg>>1 & 0x1;
+            inboundMsgsData[typeBit] = inboundMsg>>7 & 0x1FF;
+            if( !CheckMessage(inboundMsg) ) {
+                isSuccess = false;
+            }
+        }
+    }
+    return isSuccess;
 }
 
 void LLComms::SendReceiveData(int channel) {
     mutChannel[channel].lock(); // Lock mutex for specific Channel
     
     // Construct messages
-    unsigned int intPositionMsg = formatMessage(1,demandPosition[channel],MAX_ACTUATOR_LENGTH);
-    unsigned int intVelocityMsg = formatMessage(0,demandSpeed[channel],MAX_SPEED_MMPS);
+    unsigned int intPositionMsg = formatMessage(0,demandPosition_mm[channel],MAX_ACTUATOR_LIMIT_MM);
+    unsigned int intVelocityMsg = formatMessage(1,demandSpeed_mmps[channel],MAX_SPEED_MMPS);
+    //unsigned int intPositionMsg = formatMessage(0,demandPosition_mm[channel],MAX_ACTUATOR_LIMIT_MM);
+    //unsigned int intPositionMsg = formatMessage(0,20.0,MAX_ACTUATOR_LIMIT_MM);
+    //unsigned int intVelocityMsg = formatMessage(1,4.0,MAX_SPEED_MMPS);
+    
+    *cs_LL[channel] = 0; // Select relevant chip
+    unsigned int outboundMsgs[2] = { intPositionMsg , intVelocityMsg };
+    unsigned int inboundMsgsData[2];
+    bool isSPIsuccess = false;
+    if( channel < 4 ) {
+        isSPIsuccess = PerformMasterSPI(&spi_0,outboundMsgs,inboundMsgsData);
+    } else {
+        isSPIsuccess = PerformMasterSPI(&spi_1,outboundMsgs,inboundMsgsData);
+    }
+    *cs_LL[channel] = 1; // Deselect chip
+    if( isSPIsuccess ) {
+        isDataReady[channel] = 0; // Data no longer ready, i.e. we now require new data
+        positionSensor_mm[channel] = ((double)inboundMsgsData[0]/511)*(double)MAX_ACTUATOR_LIMIT_MM;
+        positionSensor_mm[channel] = min(max(positionSensor_mm[channel],0.0),(double)MAX_ACTUATOR_LIMIT_MM);
+        pressureSensor_bar[channel] = ((double)inboundMsgsData[1]/511)*(double)MAX_PRESSURE_LIMIT;
+        pressureSensor_bar[channel] = min(max(pressureSensor_bar[channel],0.0),(double)MAX_PRESSURE_LIMIT);
+        //printf("%.10f\t%.10f\n\r",positionSensor_mm[channel],pressureSensor_bar[channel]);
+    } else { // Data is STILL ready and will be resent at the next pin interrupt
+        //printf("SPI failed: %d%d. Resending.\n\r",isPositionValid,isPressureValid);
+    }
+    
+    mutChannel[channel].unlock();//unlock mutex for specific channel
+}
+
+/*bool LLComms::CheckMessage(int msg, short int trueType) {
+    // Find message parity
+    short int count = 0;
+    for(short int i=0; i<32; i++) {
+        if( msg>>1 & (1<<i) ) count++;
+    }
+    int intParity = !(count%2);
+    // Find message CheckSum    
+    int intChkSum = 0;
+    int intTempVar = msg>>7;
+    while(intTempVar > 0) {
+        intChkSum += intTempVar%10;
+        intTempVar = int(intTempVar/10);
+    }
+    // Check if parity, CheckSum and mesage type match
+    bool isParityCorrect = (intParity == (msg&0x1));
+    bool isChkSumCorrect = (intChkSum == ((msg>>2)&0x1F));
+    bool isTypeCorrect = ((msg>>1 & 0x1) == trueType);
+    bool isCheckPassed = (isParityCorrect && isChkSumCorrect && isTypeCorrect);
+    return isCheckPassed;
+}
+
+void LLComms::SendReceiveData(int channel) {
+    mutChannel[channel].lock(); // Lock mutex for specific Channel
+    
+    // Construct messages
+    //unsigned int intPositionMsg = formatMessage(0,demandPosition[channel],MAX_ACTUATOR_LENGTH_MM);
+    //unsigned int intVelocityMsg = formatMessage(1,demandSpeed[channel],MAX_SPEED_MMPS);
+    unsigned int intPositionMsg = formatMessage(0,15.2,30.4);
+    unsigned int intVelocityMsg = formatMessage(1,5.0,MAX_SPEED_MMPS);
     
     // Get data from controller
     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 
     *cs_LL[channel] = 0; // Select relevant chip
     if( channel < 4 ) {
-        intPosSPI_Rx[channel] = spi_0.write(intPositionMsg); // Transmit & receive
-        intPresSPI_Rx[channel] = intPresSPI_Rx[channel] | spi_0.write(intVelocityMsg); // Transmit & receive
+        spi_0.write(intPositionMsg); // Transmit target position & receive bullshit
+        intPosSPI_Rx[channel] = spi_0.write(intVelocityMsg); // Transmit target speed & receive current position
+        intPresSPI_Rx[channel] = spi_0.write(0xFFFF); // Transmit bullshit & receive current pressure
     } else {
-        intPosSPI_Rx[channel] = spi_1.write(intPositionMsg); // Transmit & receive
-        intPresSPI_Rx[channel] = intPresSPI_Rx[channel] | spi_1.write(intVelocityMsg); // Transmit & receive
+        spi_1.write(intPositionMsg); // Transmit target position & receive bullshit
+        intPosSPI_Rx[channel] = spi_1.write(intVelocityMsg); // Transmit target speed & receive current position
+        intPresSPI_Rx[channel] = spi_1.write(0xFFFF); // Transmit bullshit & receive current pressure
     }
+    //printf("%d\n\r",intPresSPI_Rx[channel]);
     *cs_LL[channel] = 1; // Deselect chip
-    isDataReady[channel] = 0; // Data no longer ready, i.e. we now require new data
+    
+    bool isPositionValid = CheckMessage(intPosSPI_Rx[channel],0);
+    bool isPressureValid = CheckMessage(intPresSPI_Rx[channel],1);
     
-    /*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;
-    positionSensor_m[channel] = (double)intPosSPI_Rx[channel]/511*(MAX_ACTUATOR_LENGTH/DBL_ACTUATOR_CONVERSION[channel])/1000;
-    //pressureSensor_bar[channel] = ...
+    if( isPositionValid && isPressureValid ) {
+        isDataReady[channel] = 0; // Data no longer ready, i.e. we now require new data
+        // Sort out received data
+        intPosSPI_Rx[channel] = intPosSPI_Rx[channel]>>7 & 0x1FF;
+        positionSensor_m[channel] = ((double)intPosSPI_Rx[channel]/511)*((double)MAX_ACTUATOR_LENGTH_MM/1000);
+        //positionSensor_m[channel] = fmin( fmax(positionSensor_m[channel],0.0) , ((double)MAX_ACTUATOR_LENGTH_MM)/1000) );
+        intPresSPI_Rx[channel] = intPresSPI_Rx[channel]>>7 & 0x1FF;
+        pressureSensor_bar[channel] = ((double)intPresSPI_Rx[channel]/511)*(double)MAX_PRESSURE_LIMIT;
+        //pressureSensor_bar[channel] = min( max(pressureSensor_bar[channel],0.0) , (double)MAX_PRESSURE_LIMIT) );
+        //printf("%.10f\t%.10f\n\r",positionSensor_m[channel],pressureSensor_bar[channel]);
+    } else {
+        // Data is STILL ready and will be resent at the next pin interrupt
+        //printf("SPI failed: %d%d. Resending.\n\r",isPositionValid,isPressureValid);
+    }
     
     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
+    //printf("%d %d common_rise_handler\n\r",channel,isDataReady[channel]);
+    if (isDataReady[channel]) { // Check if data is ready for transmission
         ThreadID[channel] = queue.call(this,&LLComms::SendReceiveData,channel); // Schedule transmission
     }
 }