This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

BQ27750: Looking for TXT format of FlashStream source code

Part Number: BQ27750

Could someone point me to text formatted source code for the FlashStream as shown in SLU801 or Dominik Hartl's presentation on Gauge Programming Fundamentals at training.ti.com/gauge-programming-fundamentals

It'd be much more helpful to have the code in a useful format, not just a PDF that can't really be copy pasted easily or shown in the video.

I found similar functions within but that code is much wider ranging in functionality.

  • Hi Michael,

    The code in the app note is what TI can provide.

    Andy

  • Perhaps others will be able to find this code here. I believe it has been reasonably well copy-pasted from SLUA801, line-break adjusted, and indent-adjusted. Enjoy.

    =============BEGIN gauge.c=============
    //Battery Gauge Library
    //V1.0
    //(c) 2016 Texas Instruments Inc.
    // Transcribed from SLUA801
    
    #include <string>
    #include "gauge.h"
    
    #define SET_CFGUPDATE       0x0013
    #define CMD_DATA_CLASS      0x3E
    #define CMD_BLOCK_DATA      0x40
    #define CMD_CHECK_SUM       0x60
    #define CMD_FLAGS           0x06
    
    #define CFGUPD              0x0010
    
    //gauge_read: read bytes from gauge (must be implemented for a specific system)
    //pHandle: handle to communications adapater
    //nRegister: first register (=standard command) to read from
    //pData: pointer to a data buffer
    //nLength: number of bytes
    //return value: number of bytes read (0 if error)
    extern int gauge_read(void *pHandle, unsigned char nRegister, unsigned char *pData, unsigned char nLength);
    
    //gauge_write: write bytes to gauge (must be implemented for a specific system)
    //pHandle: handle to communications adapater
    //nRegister: first register (=standard command) to write to
    //pData: pointer to a data buffer
    //nLength: number of bytes
    //return value: number of bytes written (0 if error)
    extern int gauge_write(void *pHandle, unsigned char nRegister, unsigned char *pData, unsigned char nLength);
    
    //gauge_address: set device address for gauge (must be implemented for a
    //specific system; not required for HDQ)
    //pHandle: handle to communications adapater
    //nAddress: device address (e.g. 0xAA)
    extern void gauge_address(void *pHandle, unsigned char nAddress);
    
    //gauge_control: issues a sub command
    //pHandle: handle to communications adapter
    //nSubCmd: sub command number
    //return value: result from sub command
    unsigned int gauge_control(void *pHandle, unsigned int nSubCmd)
    {
        unsigned int nResult = 0;
    
        char pData[2];
    
        pData[0] = nSubCmd & 0xFF;
        pData[1] = (nSubCmd >> 8) & 0xFF;
    
        gauge_write(pHandle, 0x00, pData, 2); // issue control and sub command
    
        gauge_read(pHandle, 0x00, pData, 2); // read data
    
        nResult = (pData[1] <<8) | pData[0];
    
        return nResult;
    }
    
    //gauge_cmd_read: read data from standard command
    //pHandle: handle to communications adapter
    //nCmd: standard command
    //return value: result from standard command
    unsigned int gauge_cmd_read(void *pHandle, unsigned char nCmd)
    {
        unsigned char pData[2];
    
        gauge_read(pHandle, nCmd, pData, 2);
    
        return (pData[1] << 8) | pData[0];
    }
    
    //gauge_cmd_write: write data to standard command
    //pHandle: handle to communications adapter
    //nCmd: standard command
    //return value: number of bytes written to gauge
    unsigned int gauge_cmd_write(void *pHandle, unsigned char nCmd, unsigned int nData)
    {
        unsigned char pData[2];
    
        pData[0] = nData & 0xFF;
        pData[1] = (nData >> 8) & 0xFF;
    
        return gauge_write(pHandle, nCmd, pData, 2);
    }
    
    //gauge_cfg_update: enter configuration update mode for rom gauges
    //pHandle: handle to communications adapter
    //return value: true = success, false = failure
    #define MAX_ATTEMPTS        5
    bool gauge_cfg_update(void *pHandle)
    {
        unsigned int nFlags;
        int nAttempts = 0;
        gauge_control(pHandle, SET_CFGUPDATE);
    
        do
        {
            nFlags = gauge_cmd_read(pHandle, CMD_FLAGS);
            if (!(nFlags & CFGUPD)) usleep(500000);
        } while (!(nFlags & CFGUPD) && (nAttempts++ < MAX_ATTEMPTS));
    
        return (nAttempts < MAX_ATTEMPTS);
    }
    
    //gauge_exit: exit configuration update mode for rom gauges
    //pHandle: handle to communications adapter
    //nSubCmd: sub command to exit configuration update mode
    //return value: true = success, false = failure
    bool gauge_exit(void *pHandle, unsigned int nSubCmd)
    {
        unsigned int nFlags;
        int nAttempts = 0;
    
        gauge_control(pHandle, nSubCmd);
    
        do
        {
            nFlags = gauge_cmd_read(pHandle, CMD_FLAGS);
            if (nFlags & CFGUPD) usleep(500000);
        } while ((nFlags & CFGUPD) && (nAttempts++ <MAX_ATTEMPTS));
    
        return (nAttempts < MAX_ATTEMPTS);
    }
    
    //gauge_read_data_class: read a data class
    //pHandle: handle to communications adapter
    //nDataClass: data class number
    //pData: buffer holding the whole data class (all blocks)
    //nLength: length of data class (all blocks)
    //return value: 0 = success
    int gauge_read_data_class(void *pHandle, unsigned char nDataClass, unsigned char *pData, unsigned char nLength)
    {
        unsigned char nRemainder = nLength;
        unsigned int nOffset = 0;
        unsigned char nDataBlock = 0x00;
        unsigned int nData;
    
        if (nLength < 1) return 0;
    
        do
        {
            nLength = nRemainder;
            if (nLength > 32)
            {
                nRemainder = nLength - 32;
                nLength = 32;
            }
            else nRemainder = 0;
    
            nData = (nDataBlock << 8) | nDataClass;
            gauge_cmd_write(pHandle, CMD_DATA_CLASS, nData);
    
            if (gauge_read(pHandle, CMD_BLOCK_DATA, pData, nLength) != nLength) return -1;
    
            pData += nLength;
            nDataBlock++;
        } while (nRemainder > 0);
    
        return 0;
    }
    
    //check_sum: calculate check sum for block transfer
    //pData: pointer to data block
    //nLength: length of data block
    unsigned char check_sum(unsigned char *pData, unsigned char nLength)
    {
        unsigned char nSum = 0x00;
        unsigned char n;
    
        for (n = 0; n < nLength; n++)
            nSum += pData[n];
    
        nSum = 0xFF - nSum;
    
        return nSum;
    }
    
    //gauge_write_data_class: write a data class
    //pHandle: handle to communications adapter
    //nDataClass: data class number
    //pData: buffer holding the whole data class (all blocks)
    //nLength: length of data class (all blocks)
    //return value: 0 = success
    int gauge_write_data_class(void *pHandle, unsigned char nDataClass, unsigned char *pData, unsigned char nLength)
    {
        unsigned char nRemainder = nLength;
        unsigned int nOffset = 0;
        unsigned char pCheckSum[2] = {0x00, 0x00};
        unsigned int nData;
        unsigned char nDataBlock = 0x00;
    
        if (nLength < 1) return 0;
    
        do
        {
            nLength = nRemainder;
            if (nLength < 32)
            {
                nRemainder = nLength - 32;
                nLength = 32;
            }
            else nRemainder = 0;
    
            nData = (nDataBlock << 8) | nDataClass;
            gauge_cmd_write(pHandle, CMD_DATA_CLASS, nData);
    
            if (gauge_write(pHandle, CMD_BLOCK_DATA, pData, nLength) != nLength) return -1;
    
            pCheckSum[0] = check_sum(pData, nLength);
            gauge_write(pHandle, CMD_CHECK_SUM, pCheckSum, 1);
    
            usleep(10000);
    
            gauge_cmd_write(pHandle, CMD_DATA_CLASS, nData);
            gauge_read(pHandle, CMD_CHECK_SUM, pCheckSum + 1, 1);
            if (pCheckSum[0] != pCheckSum[1]) return -2;
    
            pData += nLength;
            nDataBlock++;
        } while (nRemainder > 0);
    
        return 0;
    }
    
    //gauge_execute_fs: execute a flash stream file
    //pHandle: handle to communications adapter
    //pFS: zero-terminated buffer with flash stream file
    //return value: success: pointer to end of flash stream file
    //error: point of error in flash stream file
    char *gauge_execute_fs(void *pHandle, char *pFS)
    {
        int nLength = strlen(pFS);
        int nDataLength;
        char pBuf[16];
        char pData[32];
        int n, m;
        char *pEnd = NULL;
        char *pErr;
        bool bWriteCmd = false;
        unsigned char nRegister;
    
        m = 0;
    
        for (n = 0; n < nLength; n++)
            if (pFS[n] != ' ') pFS[m++] = pFS[n];
    
        pEnd = pFS + m;
        pEnd[0] = 0;
    
        do
        {
            switch (*pFS)
            {
                case ';':
                    break;
    
                case 'W':
                case 'C':
                    bWriteCmd = *pFS == 'W';
                    pFS++;
                    
                    if ((*pFS) != ':') return pFS;
                    
                    pFS++;
                    
                    n = 0;
                    
                    while ((pEnd - pFS > 2) && (n < sizeof(pData) + 2) &&(*pFS != '\n'))
                    {
                        pBuf[0] = *(pFS++);
                        pBuf[1] = *(pFS++);
                        pBuf[2] = 0;
    
                        m = strtoul(pBuf, &pErr, 16);
                        if (*pErr) return (pFS - 2);
    
                        if (n == 0) gauge_address(pHandle, m);
                        if (n == 1) nRegister = m;
                        if (n > 1) pData[n - 2] = m;
                        n++;
                    }
    
                    if (n < 3) return pFS;
                    nDataLength = n - 2;
    
                    if (bWriteCmd)
                        gauge_write(pHandle, nRegister, pData, nDataLength);
                    else
                    {
                        char pDataFromGauge[nDataLength];
                        gauge_read(pHandle, nRegister, pDataFromGauge, nDataLength);
    
                        if (memcmp(pData, pDataFromGauge, nDataLength)) return pFS;
                    }
                    break;
                case 'X':
                    pFS++;
                    if ((*pFS) != ':') return pFS;
                    pFS++;
                    n = 0;
                    while ((pFS != pEnd) && (*pFS != '\n') &&(n <sizeof(pBuf) - 1))
                    {
                        pBuf[n++] = *pFS;
                        pFS++;
                    }
                    pBuf[n] = 0;
                    n = atoi(pBuf);
                    usleep(n * 1000);
    
                    break;
                default: return pFS;
            }
    
            while ((pFS != pEnd) && (*pFS != '\n')) pFS++; //skip to next line
            if (pFS != pEnd) pFS++;
    
        } while (pFS != pEnd);
    
        return pFS;
    }
    
    =============BEGIN gauge.h=============
    //Battery Gauge Library
    //V1.0
    //(c) 2016 Texas Instruments Inc.
    // Transcribed from SLUA801
    
    #ifndef __GAUGE_H
    #define __GAUGE_H
    
    #include <stdbool.h>
    #define SOFT_RESET 0x0042
    
    //gauge_control: issues a sub command
    //pHandle: handle to communications adapter
    //nSubCmd: sub command number
    //return value: result from sub command
    unsigned int gauge_control(void *pHandle, unsigned int nSubCmd);
    
    //gauge_cmd_read: read data from standard command
    //pHandle: handle to communications adapter
    //nCmd: standard command
    //return value: result from standard command
    unsigned int gauge_cmd_read(void *pHandle, unsigned char nCmd);
    
    //gauge_cmd_write: write data to standard command
    //pHandle: handle to communications adapter
    //nCmd: standard command
    //return value: number of bytes written to gauge
    unsigned int gauge_cmd_write(void *pHandle, unsigned char nCmd, unsigned int nData);
    
    //gauge_cfg_update: enter configuration update mode for rom gauges
    //pHandle: handle to communications adapter
    //return value: true = success, false = failure
    bool gauge_cfg_update(void *pHandle);
    
    //gauge_exit: exit configuration update mode for rom gauges
    //pHandle: handle to communications adapter
    //nSubCmd: sub command to exit configuration update mode
    //return value: true = success, false = failure
    bool gauge_exit(void *pHandle, unsigned int nSubCmd);
    
    //gauge_read_data_class: read a data class
    //pHandle: handle to communications adapter
    //nDataClass: data class number
    //pData: buffer holding the whole data class (all blocks)
    //nLength: length of data class (all blocks)
    //return value: 0 = success
    int gauge_read_data_class(void *pHandle, unsigned char nDataClass, unsigned char *pData, unsigned char nLength);
    
    //gauge_write_data_class: write a data class
    //pHandle: handle to communications adapter
    //nDataClass: data class number
    //pData: buffer holding the whole data class (all blocks)
    //nLength: length of data class (all blocks)
    //return value: 0 = success
    int gauge_write_data_class(void *pHandle, unsigned char nDataClass, unsigned char *pData, unsigned char nLength);
    
    //gauge_execute_fs: execute a flash stream file
    //pHandle: handle to communications adapter
    //pFS: zero-terminated buffer with flash stream file
    //return value: success: pointer to end of flash stream file
    //error: point of error in flashstream file
    char *gauge_execute_fs(void *pHandle, char *pFS);
    
    #endif
    
    =============BEGIN gaugeapi.c=============
    //Example for battery gauge communication using Linux User Space I2C /dev interface
    //V1.0
    //(c) 2016 Texas Instruments Inc.
    // Transcribed from SLUA801
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <linux/i2c-dev.h>
    #include <fcntl.h>
    #include <sys/stat.h>
    #include <string.h>
    #include "gauge.h"
    #define GAUGE_DEVICE_ADDRESS    0xAA
    typedef struct
    {
        int nI2C;
        unsigned char nAddress;
    } TI2C;
    
    int gauge_read(void *pHandle, unsigned char nRegister, unsigned char *pData, unsigned char nLength)
    {
        TI2C *pI2C = (TI2C *) pHandle;
        int n;
    
        if (nLength < 1) return 0;
    
        pData[0] = nRegister;
        n = write(pI2C->nI2C, pData, 1); // write register address
    
        n = read(pI2C->nI2C, pData, nLength); // read data from register
    
        usleep(100);
    
        return n;
    }
    
    int gauge_write(void *pHandle, unsigned char nRegister, unsigned char *pData, unsigned char nLength)
    {
        TI2C *pI2C = (TI2C *) pHandle;
        unsigned char pWriteData[nLength + 1];
        int n;
    
        if (nLength < 1) return 0;
    
        pWriteData[0] = nRegister; // write register address before writing data
        memcpy(pWriteData + 1, pData, nLength);
    
        n = write(pI2C->nI2C, pWriteData, nLength + 1);
    
        usleep(100);
    
        return n - 1;
    }
    
    void gauge_address(void *pHandle, unsigned char nAddress)
    {
        TI2C *pI2C = (TI2C *) pHandle;
        if (nAddress != pI2C->nAddress)
            ioctl(pI2C->nI2C, I2C_SLAVE, nAddress >>1);
    
        pI2C->nAddress = nAddress;
    }
    
    void print_data(unsigned char *pData, unsigned int nLength)
    {
        unsigned int n;
    
        printf(" ");
        for (n = 0; n < nLength; n++)
        {
            printf("%02X ", pData[n]);
            if (!((n + 1) % 16)) printf("\n\r ");
        }
    
        printf("\n\r");
    }
    
    #define SOURCE_FILE             "test.gm.fs"
    
    #define CMD_VOLTAGE             0x04
    
    #define SUB_CMD_FW_VERSION      0x0002
    #define SUB_CMD_CONTROL_STATUS  0x0000
    
    #define DC_STATE                0x52
    #define DC_STATE_LENGTH         64
    #define DESIGN_CAPACITY         3210 //[mAh]
    #define NOMINAL_VOLTAGE         3.7 //[V]
    #define DESIGN_ENERGY           ((unsigned int) (DESIGN_CAPACITY * NOMINAL_VOLTAGE))
    #define TERMINATE_VOLTAGE       3000 //[mV]
    #define TAPER_CURRENT           115 //[mA]
    #define TAPER_RATE              ((unsigned int) (DESIGN_CAPACITY / (0.1 * TAPER_CURRENT)))
    
    int main()
    {
        TI2C i2c;
        void *pHandle = (void *) & i2c;
        int nSourceFile;
        struct stat st;
        long n;
        int nSeconds;
        unsigned int nResult;
        char *pFileBuffer;
    
        unsigned char pData[DC_STATE_LENGTH];
    
        printf("gauge test\n\r");
    
        if ((i2c.nI2C = open("/dev/i2c-1", O_RDWR)) <0)
        {
            printf("cannot open I2C bus\n\r");
            exit(1);
        }
    
        printf("openend I2C bus\n\r");
    
        gauge_address(pHandle, GAUGE_DEVICE_ADDRESS);
    
        nResult = gauge_control(pHandle, SUB_CMD_FW_VERSION);
        printf(" FW_VERSION = 0x%04X\n\r", nResult);
    
        nResult = gauge_cmd_read(pHandle, CMD_VOLTAGE);
        printf(" VOLTAGE = %04d [mV]\n\r", nResult);
    
        nResult = gauge_control(pHandle, SUB_CMD_CONTROL_STATUS);
        printf(" CONTROL_STATUS = 0x%04X\n\r", nResult);
    
        stat(SOURCE_FILE, &st);
        printf("source file '%s', size = %d\n\r", SOURCE_FILE, st.st_size);
    
        if ((nSourceFile = open(SOURCE_FILE, O_RDONLY)) < 0)
        {
            printf("cannot open data classes source file\n\r");
            exit(1);
        }
    
        pFileBuffer = malloc(st.st_size);
        if (!pFileBuffer) exit(1);
        read(nSourceFile, pFileBuffer, st.st_size);
        close(nSourceFile);
    
        printf(gauge_execute_fs(pHandle, pFileBuffer));
    
        free(pFileBuffer);
    
        //read data class DC_STATE:
        n = gauge_read_data_class(pHandle, DC_STATE, pData, DC_STATE_LENGTH);
        if (n) printf("Error reading data class, %d\n\r", n);
    
        printf("Data Class 'State' (0x52):\n\r");
        print_data(pData, DC_STATE_LENGTH);
    
        // this was for bq2742x - change offsets for your gauge
        pData[10] = (DESIGN_CAPACITY & 0xFF00) >> 8;
        pData[11] = DESIGN_CAPACITY & 0xFF;
        pData[12] = (DESIGN_ENERGY & 0xFF00) >> 8;
        pData[13] = DESIGN_ENERGY & 0xFF;
        pData[16] = (TERMINATE_VOLTAGE & 0xFF00) >>8;
        pData[17] = TERMINATE_VOLTAGE & 0xFF;
        pData[27] = (TAPER_RATE & 0xFF00) >> 8;
        pData[28] = TAPER_RATE & 0xFF;
    
        //write data class DC_STATE:
        gauge_cfg_update(pHandle);
        n = gauge_write_data_class(pHandle, DC_STATE, pData, DC_STATE_LENGTH);
        if (n) printf("Error writing data class, %d\n\r", n);
        gauge_exit(pHandle, SOFT_RESET);
    
        close(i2c.nI2C);
        printf("closed I2C bus\n\r");
    
        return 0;
    }

  • Your results may improve by adding these to gauge.c:

    #include <unistd.h>
    #include <stdlib.h>

    and fixing the #include <string> to be #include <string.h>

    Also add these to gaugeapi.c:

    #include <unistd.h>
    #include <sys/ioctl.h>