Cell voltages fork (SoC)

Dependencies:   CUER_CAN CUER_DS1820 LTC2943 LTC6804 mbed PowerControl

IVTA.cpp

Committer:
DasSidG
Date:
2017-08-19
Revision:
57:a84af3673c9b
Parent:
54:f18d3af300ba
Child:
58:40d318825b0d

File content as of revision 57:a84af3673c9b:

#include "IVTA.h";

DigitalOut IVTA_SS(p11);

SPI spi_ivta(p5, p6, p7); // mosi, miso, sclk

int ivta_transfer(uint8_t * txrx)
{
    char i;// j;
    uint16_t crc;
    
    //pc.printf("*** Into a transfer***  \r \n");
    
    // Activate IVT-A and send packet.
    IVTA_SS = 0;
    //pc.printf("Data sent");
    wait_us(3);
    for(i = 0; i < 9; i++)
    {
        spi_ivta.write(txrx[i]); 
        wait_us(3);
    }
    wait_us(3);
    IVTA_SS = 1;
    /*
       Note: we ignore the packet sent by the IVT-A
       during this communication phase. Similarly,
       we only receive data in the next phase. Essentially
       we run the IVT-A in half-duplex mode.
    */

    wait_us(500);                           // Wait between packets
    IVTA_SS = 0;                       // Activate IVT-A and receive packet.
    wait_us(3);
    for(i = 0; i < 9; i++)
    {
        txrx[i] = spi_ivta.write(0x00); // Write some dummy data(half duplex)
        wait_us(3);
    }
    wait_us(3);
    IVTA_SS = 1;
    
    return 0;
}

/*
   Initialise IVT-A.
   Write configuration:
   + Current in 300A range measured on channel A.
   + Temperature measured on channel B (currently unused).
   + Average data over 10 samples.
*/
int ivta_init(void)
{
    IVTA_SS = 1; 
    spi_ivta.format(8,0); // The format works for 0 or 1, most of testing done with 0
    spi_ivta.frequency(500000);
    /* The last 2 bytes of the package are the CRC check, upper 4 bits in the 
    command are the command code */
    int transfer;
    uint8_t packet[9] = {0x90,1,5,200,0,0,0,0x78,0xB8}; 
    //if (DEBUG) printf("Calculated init crc is %x ", calculate_IVTA_crc(packet)); 
    transfer = ivta_transfer(packet);
    return transfer;
}

   
bool ivta_get_current(int32_t &current) //returns true if crc check succeeded, false otherwise
{
    //printf("In get current \r \n");
    //int r_val;
    uint8_t packet[9] = {0x10,1,0,0,0,0,0,0x0B,0x10};       // Command code 1.
    //printf("Calculated current crc is %x ", calculate_IVTA_crc(packet)); 
    //printf("In get current \r \n");
    int r_val = ivta_transfer(packet);
    
   /* printf("Packet1 : %d \r", packet[1]);
    printf("Packet1 : %d \r", packet[2]);
    printf("Packet1 : %d \r", packet[3]);
    printf("Packet1 : %d \r", packet[4]);*/
    uint8_t measurements[6];
    uint8_t received_crc_bytes[2];
             
    measurements[0] = packet[1];                        // Must shift the index of the packet
    measurements[1] = packet[2];
    measurements[2] = packet[3];
    measurements[3] = packet[4];
    measurements[4] = packet[5];
    measurements[5] = packet[6];
    received_crc_bytes[0] = packet[7];
    received_crc_bytes[1] = packet[8];
    
    uint16_t calculated_crc = calculate_IVTA_crc(packet);
    //printf("calculated current crc is %x \r\n", calculated_crc);
    uint16_t received_crc = (uint16_t) received_crc_bytes[0];
    received_crc |= (uint16_t) received_crc_bytes[1] <<8;
    //printf("received current crc is %x \r\n", received_crc);
    
    
    
    /*for (int i = 0; i < 6; ++i) {
        printf ("Current measurements %d is %d \r\n", i, measurements[i]);
    }*/
    
    if (calculated_crc == received_crc) {
        uint32_t unsigned_current = ((uint32_t)measurements[0]);
        unsigned_current = unsigned_current | (((uint32_t)measurements[1]<<8));
        unsigned_current = unsigned_current | (((uint32_t)measurements[2]<<16));
        
        if(measurements[2] & 0x80){ //For some reason converting using 2's complement ¯\_(ツ)_/¯
            uint32_t convertedData = ((~unsigned_current) + 1) & 0x00FFFFFF;
            int32_t convertedData2 = (~convertedData)+1;
            if (DEBUG) printf("*** Signed IVT-A Current measurement value: %d ***  \r \n",convertedData2); 
            current = convertedData2;
        }
        else{
            if (DEBUG) printf("*** Unsigned IVT-A Current measurement value: %d ***  \r \n", (int32_t)unsigned_current);
            current = unsigned_current;
        }
        
         return true;
    }
    else return false;
}

void ivta_reset_Ah_meter() { //sets Ah meter to zero
    uint8_t packet[9] = {0xA0,0x01,0x00,0x00,0x00,0x00,0x00,0xBA,0xDB};       // Command code 10.
    ivta_transfer(packet);
}

bool ivta_read_Ah_meter(float &Ah) { //return Ah meter reading in units of Ah
    uint8_t packet[9] = {0x50,0x01,0x00,0x00,0x00,0x00,0x00,0x4A,0xD4};       // Command code 5.
    //printf("Calculated read_Ah crc is %x ", calculate_IVTA_crc(packet)); 
    ivta_transfer(packet);
    uint8_t measurements[6];
    uint8_t received_crc_bytes[2];
                            
    measurements[0] = packet[1];                        // Must shift the index of the packet
    measurements[1] = packet[2];
    measurements[2] = packet[3];
    measurements[3] = packet[4];
    measurements[4] = packet[5];
    measurements[5] = packet[6];
    received_crc_bytes[0] = packet[7];
    received_crc_bytes[1] = packet[8];
    
    uint16_t calculated_crc = calculate_IVTA_crc(packet);
    uint16_t received_crc = (uint16_t) received_crc_bytes[0];
    received_crc |= (uint16_t) received_crc_bytes[1] <<8;
    
    /*for (int i = 0; i < 6; ++i) {
        printf ("Ah Measurements %d is %d \r\n", i, measurements[i]);
    }*/
    if (received_crc == calculated_crc) {
        uint64_t mAs = ((uint64_t)measurements[0]);
        mAs = mAs | (((uint64_t)measurements[1]<<8));
        mAs = mAs | (((uint64_t)measurements[2]<<16));
        mAs = mAs | (((uint64_t)measurements[3]<<24));
        mAs = mAs | (((uint64_t)measurements[4]<<32));
        mAs = mAs | (((uint64_t)measurements[5]<<40));
        
        if(measurements[5] & 0x80){ //For some reason converting using 2's complement ¯\_(ツ)_/¯
            uint64_t convertedData = ((~mAs) + 1) & 0x0000FFFFFFFFFFFF;
            uint64_t convertedData2 = (~convertedData)+1;
            Ah = convertedData2/(1000.0*3600);
            if(DEBUG) printf("*** Signed IVT-A Ah measurement value: %f ***  \r \n",Ah); 
        }
        else{
            Ah = mAs /(1000.0*3600);
            if(DEBUG) printf("*** Unsigned IVT-A Ah measurement value: %f ***  \r \n", Ah);
        }
        return true;
    }
    else return false;
}

uint16_t calculate_IVTA_crc(uint8_t data[]) {
    uint16_t crc = 0xFFFF;
    for (int i = 0; i < 7; ++i) {
        crc = crc16_update(crc, data[i]);
    }
    return crc;
}

uint16_t crc16_update(uint16_t crc, uint8_t a)
{
    crc ^= a;
    for (int i = 0; i < 8; ++i)
    {
        if (crc & 1) crc = (crc >> 1) ^ 0xA001;
        else crc = (crc >> 1);
    }
    return crc;
}