(Working) Code to interface 3 LoadCells to ADISense1000 and display values using the Labview code.

Fork of 4Bridge_ADISense1000_Example_copy by CAC_smartcushion

common/utils.c

Committer:
seanwilson10
Date:
2018-01-25
Revision:
0:76fed7dd9235

File content as of revision 0:76fed7dd9235:

#include <stdlib.h>

#include "utils.h"
#include "inc/adi_sense_log.h"

void utils_printStatus(
    ADI_SENSE_STATUS *pStatus)
{
    ADI_SENSE_LOG_INFO("Status Summary:");

    if (pStatus->deviceStatus == 0)
    {
        ADI_SENSE_LOG_INFO("\tNo errors detected");
    }
    else
    {
        if (pStatus->deviceStatus & ADI_SENSE_DEVICE_STATUS_BUSY)
            ADI_SENSE_LOG_INFO("\tCommand running");
        if (pStatus->deviceStatus & ADI_SENSE_DEVICE_STATUS_DATAREADY)
            ADI_SENSE_LOG_INFO("\tData ready");
        if (pStatus->deviceStatus & ADI_SENSE_DEVICE_STATUS_ERROR)
            ADI_SENSE_LOG_INFO("\tActive Errors - RESET REQUIRED");
        if (pStatus->deviceStatus & ADI_SENSE_DEVICE_STATUS_FIFO_ERROR)
            ADI_SENSE_LOG_INFO("\tActive FIFO Errors - ATTENTION REQUIRED");
        if (pStatus->deviceStatus & ADI_SENSE_DEVICE_STATUS_CONFIG_ERROR)
            ADI_SENSE_LOG_INFO("\tActive Configuration Errors - ATTENTION REQUIRED");
        if (pStatus->deviceStatus & ADI_SENSE_DEVICE_STATUS_LUT_ERROR)
            ADI_SENSE_LOG_INFO("\tActive Look-Up Table Errors - ATTENTION REQUIRED");

        if (pStatus->deviceStatus & ADI_SENSE_DEVICE_STATUS_ERROR)
        {
            ADI_SENSE_LOG_INFO("\tActive Errors - ATTENTION REQUIRED");
            ADI_SENSE_LOG_INFO("\t\tLast Error Code: %u (0x%X)",
                               pStatus->errorCode, pStatus->errorCode);

            if (pStatus->diagnosticsStatus == 0)
            {
                ADI_SENSE_LOG_INFO("\t\tNo diagnostics faults detected");
            }
            else
            {
                ADI_SENSE_LOG_INFO("\t\tActive diagnostics faults:");

                if (pStatus->diagnosticsStatus & ADI_SENSE_DIAGNOSTICS_STATUS_CHECKSUM_ERROR)
                    ADI_SENSE_LOG_INFO("\t\t\tInternal Checksum fault detected");
                if (pStatus->diagnosticsStatus & ADI_SENSE_DIAGNOSTICS_STATUS_COMMS_ERROR)
                    ADI_SENSE_LOG_INFO("\t\t\tInternal Communications fault detected");
                if (pStatus->diagnosticsStatus & ADI_SENSE_DIAGNOSTICS_STATUS_SUPPLY_MONITOR_ERROR)
                    ADI_SENSE_LOG_INFO("\t\t\tSupply Monitor fault detected");
                if (pStatus->diagnosticsStatus & ADI_SENSE_DIAGNOSTICS_STATUS_SUPPLY_CAP_ERROR)
                    ADI_SENSE_LOG_INFO("\t\t\tSupply Regulator Capacitor fault detected");
                if (pStatus->diagnosticsStatus & ADI_SENSE_DIAGNOSTICS_STATUS_AINM_UV_ERROR)
                    ADI_SENSE_LOG_INFO("\t\t\tNegative Analog Input Under-Voltage fault detected");
                if (pStatus->diagnosticsStatus & ADI_SENSE_DIAGNOSTICS_STATUS_AINM_OV_ERROR)
                    ADI_SENSE_LOG_INFO("\t\t\tNegative Analog Input Over-Voltage fault detected");
                if (pStatus->diagnosticsStatus & ADI_SENSE_DIAGNOSTICS_STATUS_AINP_UV_ERROR)
                    ADI_SENSE_LOG_INFO("\t\t\tPositive Analog Input Under-Voltage fault detected");
                if (pStatus->diagnosticsStatus & ADI_SENSE_DIAGNOSTICS_STATUS_AINP_OV_ERROR)
                    ADI_SENSE_LOG_INFO("\t\t\tPositive Analog Input Over-Voltage fault detected");
                if (pStatus->diagnosticsStatus & ADI_SENSE_DIAGNOSTICS_STATUS_CONVERSION_ERROR)
                    ADI_SENSE_LOG_INFO("\t\t\tInternal ADC Conversions fault detected");
                if (pStatus->diagnosticsStatus & ADI_SENSE_DIAGNOSTICS_STATUS_CALIBRATION_ERROR)
                    ADI_SENSE_LOG_INFO("\t\t\tInternal Device Calibrations fault detected");
            }
        }

        if (pStatus->deviceStatus & ADI_SENSE_DEVICE_STATUS_ALERT)
        {
            ADI_SENSE_LOG_INFO("\tActive Alerts - ATTENTION REQUIRED:");
            ADI_SENSE_LOG_INFO("\t\tLast Alert Code: %u (0x%X)",
                               pStatus->alertCode, pStatus->alertCode);

            for (unsigned i = 0; i < ADI_SENSE_1000_MAX_CHANNELS; i++)
            {
                if (pStatus->channelAlerts[i] == 0)
                    continue;

                ADI_SENSE_LOG_INFO("\t\tChannel #%u:", i);
                ADI_SENSE_LOG_INFO("\t\t\tLast Alert Code: %u (0x%X)",
                                   pStatus->channelAlertCodes[i],
                                   pStatus->channelAlertCodes[i]);
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_TIMEOUT)
                    ADI_SENSE_LOG_INFO("\t\t\tTimeout alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_UNDER_RANGE)
                    ADI_SENSE_LOG_INFO("\t\t\tUnder Range alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_OVER_RANGE)
                    ADI_SENSE_LOG_INFO("\t\t\tOver Range alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_LOW_LIMIT)
                    ADI_SENSE_LOG_INFO("\t\t\tLow limit alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_HIGH_LIMIT)
                    ADI_SENSE_LOG_INFO("\t\t\tHigh Limit alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_SENSOR_OPEN)
                    ADI_SENSE_LOG_INFO("\t\t\tSensor Fault alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_REF_DETECT)
                    ADI_SENSE_LOG_INFO("\t\t\tReference Detection alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_CONFIG_ERR)
                    ADI_SENSE_LOG_INFO("\t\t\tConfiguration Error alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_LUT_ERR)
                    ADI_SENSE_LOG_INFO("\t\t\tLook-Up Table Error alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_SENSOR_NOT_READY)
                    ADI_SENSE_LOG_INFO("\t\t\tSensor Not Ready alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_COMP_NOT_READY)
                    ADI_SENSE_LOG_INFO("\t\t\tCompensation Channel Not Ready alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_UNDER_VOLTAGE)
                    ADI_SENSE_LOG_INFO("\t\t\tUnder Voltage alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_OVER_VOLTAGE)
                    ADI_SENSE_LOG_INFO("\t\t\tOver Voltage alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_LUT_UNDER_RANGE)
                    ADI_SENSE_LOG_INFO("\t\t\tUnder Look-Up Table Range alert detected");
                if (pStatus->channelAlerts[i] & ADI_SENSE_CHANNEL_ALERT_LUT_OVER_RANGE)
                    ADI_SENSE_LOG_INFO("\t\t\tOver Look-Up Table Range alert detected");
            }
        }
    }
}

void utils_printSamples(
    ADI_SENSE_DATA_SAMPLE *pSampleBuffer,
    uint32_t nNumSamples)
{
    for (uint32_t i = 0; i < nNumSamples; i++)
    {
        ADI_SENSE_LOG_INFO("Sample # %2d Channel # %2d :: Raw %8d  :: Processed %.7f :: flags: %s %s",
                           i+1,
                           pSampleBuffer[i].channelId,
                           pSampleBuffer[i].rawValue,
                           pSampleBuffer[i].processedValue,
                           pSampleBuffer[i].status & ADI_SENSE_DEVICE_STATUS_ERROR ? "ERROR" : "",
                           pSampleBuffer[i].status & ADI_SENSE_DEVICE_STATUS_ALERT ? "ALERT" : "");
    }
}

static void gpioCallbackFn(ADI_SENSE_GPIO_PIN ePinId, void * pArg)
{
    volatile bool_t *pbFlag = (volatile bool_t *)pArg;
    *pbFlag = true;
}

ADI_SENSE_RESULT utils_registerCallbacks(
    ADI_SENSE_DEVICE_HANDLE hDevice,
    volatile bool_t *pbDataReady,
    volatile bool_t *pbError,
    volatile bool_t *pbAlert)
{
    ADI_SENSE_RESULT res;

    res = adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_DATAREADY,
                                         gpioCallbackFn, (void *)pbDataReady);
    if (res != ADI_SENSE_SUCCESS)
    {
        ADI_SENSE_LOG_ERROR("Failed to register DATAREADY callback");
        return res;
    }

    res = adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_ERROR,
                                         gpioCallbackFn, (void *)pbError);
    if (res != ADI_SENSE_SUCCESS)
    {
        ADI_SENSE_LOG_ERROR("Failed to register ERROR callback");
        return res;
    }

    res = adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_ALERT,
                                         gpioCallbackFn, (void *)pbAlert);
    if (res != ADI_SENSE_SUCCESS)
    {
        ADI_SENSE_LOG_ERROR("Failed to register ALERT callback");
        return res;
    }

    return ADI_SENSE_SUCCESS;
}

ADI_SENSE_RESULT utils_deregisterCallbacks(
    ADI_SENSE_DEVICE_HANDLE hDevice)
{
    ADI_SENSE_RESULT res;

    res = adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_DATAREADY,
                                         NULL, NULL);
    if (res != ADI_SENSE_SUCCESS)
    {
        ADI_SENSE_LOG_ERROR("Failed to deregister DATAREADY callback");
        return res;
    }

    res = adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_ERROR,
                                         NULL, NULL);
    if (res != ADI_SENSE_SUCCESS)
    {
        ADI_SENSE_LOG_ERROR("Failed to deregister ERROR callback");
        return res;
    }

    res = adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_ALERT,
                                         NULL, NULL);
    if (res != ADI_SENSE_SUCCESS)
    {
        ADI_SENSE_LOG_INFO("Failed to deregister ALERT callback");
        return res;
    }

    return ADI_SENSE_SUCCESS;
}

ADI_SENSE_RESULT utils_runMeasurement(
    ADI_SENSE_DEVICE_HANDLE hDevice,
    ADI_SENSE_MEASUREMENT_MODE eMeasurementMode)
{
    ADI_SENSE_RESULT res;

    volatile bool_t bDataReady = false;
    volatile bool_t bError = false;
    volatile bool_t bAlert = false;
    res = utils_registerCallbacks(hDevice, &bDataReady, &bError, &bAlert);
    if (res != ADI_SENSE_SUCCESS)
        return res;

    /*
     * Retrieve the number of samples per cycle, per DATAREADY pulse, etc. for this configuration.
     */
    ADI_SENSE_1000_OPERATING_MODE eOperatingMode;
    ADI_SENSE_1000_DATAREADY_MODE eDataReadyMode;
    uint32_t nSamplesPerDataready;
    uint32_t nSamplesPerCycle;
    res = adi_sense_1000_GetDataReadyModeInfo(hDevice,
                                              eMeasurementMode,
                                              &eOperatingMode,
                                              &eDataReadyMode,
                                              &nSamplesPerDataready,
                                              &nSamplesPerCycle);
    if (res != ADI_SENSE_SUCCESS)
        return res;

    /*
     * Allocate a buffer to store the samples retrieved on each DATAREADY pulse
     * However, if the DATAREADY pulse is per-conversion, allocate a bigger buffer
     * to accumulate a full cycle of samples before printing them
     */
    ADI_SENSE_DATA_SAMPLE *pSampleBuffer;
    if (eDataReadyMode == ADI_SENSE_1000_DATAREADY_PER_CONVERSION)
        pSampleBuffer = malloc(sizeof(ADI_SENSE_DATA_SAMPLE) * nSamplesPerCycle);
    else
        pSampleBuffer = malloc(sizeof(ADI_SENSE_DATA_SAMPLE) * nSamplesPerDataready);
    if (pSampleBuffer == NULL)
    {
        ADI_SENSE_LOG_ERROR("Failed to allocate sample buffer");
        return ADI_SENSE_NO_MEM;
    }

    /*
     * Kick off the measurement cycle(s) here
     */
    res = adi_sense_StartMeasurement(hDevice, eMeasurementMode);
    if (res != ADI_SENSE_SUCCESS)
    {
        ADI_SENSE_LOG_ERROR("Failed to start measurement");
        return res;
    }

    /*
     * Loop continuously unless operating mode is single-cycle
     */
    do {
        ADI_SENSE_STATUS status;
        uint32_t nCurrentSamples;
        uint32_t nReturned;
        nCurrentSamples = 0;

        /*
         * Accumulate the samples from a cycle and print them
         * NOTE: requires a sufficient idle time between cycles to allow printing to occur
         */
        do {
            /*
             * Wait for the cycle to complete, continuously checking DATAREADY until it is asserted
             */
            while (! (bDataReady || bError))
                ;

            if (! bError)
            {
                /*
                 * Retrieve the data samples from the measurement cycle, if no error has occurred
                 */
                bDataReady = false;
                res = adi_sense_GetData(hDevice, eMeasurementMode, &pSampleBuffer[nCurrentSamples], nSamplesPerDataready, &nReturned);
                nCurrentSamples += nReturned;
                if (res != ADI_SENSE_SUCCESS)
                {
                    if (res == ADI_SENSE_INCOMPLETE)
                    {
                        /* For this case, let's get the device status and print
                         * any samples we did get */
                        ADI_SENSE_LOG_WARN("Failed to retrieve all requested data samples");
                        break;
                    }
                    else
                    {
                        ADI_SENSE_LOG_WARN("Failed to retrieve data samples from device");
                        return res;
                    }
                }
            }
        } while (!bError && (nCurrentSamples < nSamplesPerCycle));

        /*
         * Display the data samples
         */
        utils_printSamples(pSampleBuffer, nCurrentSamples);

        /*
         * Check and print device status if errors/alerts have been triggered
         */
        if (bError || bAlert)
        {
            res = adi_sense_GetStatus(hDevice, &status);
            if (res != ADI_SENSE_SUCCESS)
            {
                ADI_SENSE_LOG_ERROR("Failed to retrieve device status");
                return res;
            }

            if (status.deviceStatus &
                (ADI_SENSE_DEVICE_STATUS_ERROR | ADI_SENSE_DEVICE_STATUS_ALERT))
            {
                utils_printStatus(&status);

                /* Break out of the loop if any errors are raised */
                if (bError)
                    break;
            }
        }
    } while (eOperatingMode != ADI_SENSE_1000_OPERATING_MODE_SINGLECYCLE);

    res = adi_sense_StopMeasurement(hDevice);
    if (res != ADI_SENSE_SUCCESS)
    {
        ADI_SENSE_LOG_ERROR("Failed to send stop measurement");
        return res;
    }

    free(pSampleBuffer);

    res = utils_deregisterCallbacks(hDevice);
    if (res != ADI_SENSE_SUCCESS)
        return res;

    return ADI_SENSE_SUCCESS;
}

ADI_SENSE_RESULT utils_printCalTable(
    ADI_SENSE_DEVICE_HANDLE hDevice)
{
    ADI_SENSE_RESULT res;
    unsigned dataLen, nRows, nColumns, maxLen = 1024;

    float *pCalDataBuffer = malloc(maxLen);
    if (pCalDataBuffer == NULL)
    {
        ADI_SENSE_LOG_ERROR("Failed to allocate calibration data buffer");
        return ADI_SENSE_NO_MEM;
    }

    res = adi_sense_1000_ReadCalTable(hDevice,
                                      pCalDataBuffer, maxLen,
                                      &dataLen, &nRows, &nColumns);
    if (res != ADI_SENSE_SUCCESS)
    {
        ADI_SENSE_LOG_ERROR("Failed to read calibration data");
        free(pCalDataBuffer);
        return res;
    }

    ADI_SENSE_LOG_INFO("Calibration Table:\r\n");
    ADI_SENSE_LOG_INFO("%6s| %10s | %10s | %10s |", "index", "25", "-40", "85");
    for (unsigned row = 0; row < nRows; row++)
    {
        ADI_SENSE_LOG_INFO("%6d| %10f | %10f | %10f |",
                           row,
                           pCalDataBuffer[(row * nColumns) + 0],
                           pCalDataBuffer[(row * nColumns) + 1],
                           pCalDataBuffer[(row * nColumns) + 2]);
    }

    free(pCalDataBuffer);
    return ADI_SENSE_SUCCESS;
}