CAC_smartcushion
/
ADISense1000_Smartcushion_v1_ble_reply_over_usb2ser
Proswift with BLE EV-BL652ARDZ
Fork of ADISense1000_Example_FW by
Revision 1:25a2bf666957, committed 2018-08-24
- Comitter:
- nfathurr
- Date:
- Fri Aug 24 08:58:48 2018 +0000
- Parent:
- 0:76fed7dd9235
- Commit message:
- test
Changed in this revision
diff -r 76fed7dd9235 -r 25a2bf666957 ADISense1000_MBED.c --- a/ADISense1000_MBED.c Thu Jan 25 16:00:23 2018 +0000 +++ b/ADISense1000_MBED.c Fri Aug 24 08:58:48 2018 +0000 @@ -1,114 +1,193 @@ -/*! - ****************************************************************************** - * @file: config.c - * @brief: - *----------------------------------------------------------------------------- - * -Copyright (c) 2017 Emutex Ltd. / Analog Devices, Inc. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - Modified versions of the software must be conspicuously marked as such. - - This software is licensed solely and exclusively for use with processors - manufactured by or for Analog Devices, Inc. - - This software may not be combined or merged with other code in any manner - that would cause the software to become subject to terms and conditions - which differ from those listed here. - - Neither the name of Analog Devices, Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - The use of this software may or may not infringe the patent rights of one - or more patent holders. This license does not release you from the - requirement that you obtain separate licenses from these patent holders - to use this software. - -THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, -TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN -NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF CLAIMS OF INTELLECTUAL -PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, -EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ - -#include "inc/adi_sense_config_types.h" - -ADI_SENSE_CONFIG config = { - .versionId = { .major = 1, .minor = 4 }, - .adisense1000 = { - .power = { - .powerMode = ADI_SENSE_1000_POWER_MODE_FULL, - .supplyVoltage = 3.3, - }, - .measurement = { - .operatingMode = ADI_SENSE_1000_OPERATING_MODE_CONTINUOUS, - .dataReadyMode = ADI_SENSE_1000_DATAREADY_PER_CYCLE, - .cycleInterval = 0, - }, - .channels = { - [ADI_SENSE_1000_CHANNEL_ID_SENSOR_0] = { - .enableChannel = true, - .disablePublishing = false, - .compensationChannel = ADI_SENSE_1000_CHANNEL_ID_CJC_0, - .measurementsPerCycle = 1, - .extraSettlingTime = 0.0000, - .measurementUnit = ADI_SENSE_1000_MEASUREMENT_UNIT_CELSIUS, - .adcChannelConfig = { - .sensor = ADI_SENSE_1000_ADC_SENSOR_THERMOCOUPLE_T_DEF_L1, - .gain = ADI_SENSE_1000_ADC_GAIN_128X, - .current = { - .outputLevel = ADI_SENSE_1000_ADC_EXC_CURRENT_NONE, - .swapOption = ADI_SENSE_1000_ADC_EXC_CURRENT_SWAP_NONE, - }, - .filter = { - .type = ADI_SENSE_1000_ADC_FILTER_SINC4, - .fs = 1920, - }, - .reference = { - .type = ADI_SENSE_1000_ADC_REFERENCE_VOLTAGE_INTERNAL, - .disableBuffer = false, - }, - .enableVbias = true, - }, - }, - [ADI_SENSE_1000_CHANNEL_ID_CJC_0] = { - .enableChannel = true, - .disablePublishing = false, - .compensationChannel = ADI_SENSE_1000_CHANNEL_ID_NONE, - .measurementsPerCycle = 1, - .extraSettlingTime = 0.0000, - .measurementUnit = ADI_SENSE_1000_MEASUREMENT_UNIT_CELSIUS, - .adcChannelConfig = { - .sensor = ADI_SENSE_1000_ADC_SENSOR_RTD_2WIRE_PT100_DEF_L1, - .gain = ADI_SENSE_1000_ADC_GAIN_128X, - .current = { - .outputLevel = ADI_SENSE_1000_ADC_EXC_CURRENT_500uA, - .swapOption = ADI_SENSE_1000_ADC_EXC_CURRENT_SWAP_NONE, - }, - .filter = { - .type = ADI_SENSE_1000_ADC_FILTER_SINC4, - .fs = 1920, - }, - .reference = { - .type = ADI_SENSE_1000_ADC_REFERENCE_RESISTOR_INTERNAL_1, - .disableBuffer = false, - }, - .enableVbias = false, - }, - }, - }, - }, -}; +/*! + ****************************************************************************** + * @file: config.c + * @brief: + *----------------------------------------------------------------------------- + * +Copyright (c) 2018 Analog Devices, Inc. + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + - Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + - Modified versions of the software must be conspicuously marked as such. + - This software is licensed solely and exclusively for use with processors + manufactured by or for Analog Devices, Inc. + - This software may not be combined or merged with other code in any manner + that would cause the software to become subject to terms and conditions + which differ from those listed here. + - Neither the name of Analog Devices, Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + - The use of this software may or may not infringe the patent rights of one + or more patent holders. This license does not release you from the + requirement that you obtain separate licenses from these patent holders + to use this software. + +THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, +TITLE, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +NO EVENT SHALL ANALOG DEVICES, INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF CLAIMS OF INTELLECTUAL +PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS +OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#include "inc/adi_sense_config_types.h" +ADI_SENSE_CONFIG adi_sense_config = { + .versionId = { .major = 1, .minor = 4 }, + .productId = ADI_SENSE_PRODUCT_ID_1000, + .adisense1000 = { + .power = { + .powerMode = ADI_SENSE_1000_POWER_MODE_FULL, + .supplyVoltage = 3.3, + }, + .measurement = { + .operatingMode = ADI_SENSE_1000_OPERATING_MODE_CONTINUOUS, + .dataReadyMode = ADI_SENSE_1000_DATAREADY_PER_CYCLE, + .cycleInterval = 0, + }, + .channels = { + [ADI_SENSE_1000_CHANNEL_ID_CJC_0] = { + .enableChannel = true, + .disablePublishing = false, + .compensationChannel = ADI_SENSE_1000_CHANNEL_ID_NONE, + .measurementsPerCycle = 1, + .extraSettlingTime = 0.0000, + .measurementUnit = ADI_SENSE_1000_MEASUREMENT_UNIT_CELSIUS, + .adcChannelConfig = { + .sensor = ADI_SENSE_1000_ADC_SENSOR_RTD_2WIRE_PT100_DEF_L1, + .gain = ADI_SENSE_1000_ADC_GAIN_32X, + .current = { + .outputLevel = ADI_SENSE_1000_ADC_EXC_CURRENT_500uA, + .swapOption = ADI_SENSE_1000_ADC_EXC_CURRENT_SWAP_NONE, + }, + .filter = { + .type = ADI_SENSE_1000_ADC_FILTER_FIR_25SPS, + .fs = 0, + //.type = ADI_SENSE_1000_ADC_FILTER_SINC4, + //.fs = 1920, + }, + .reference = { + .type = ADI_SENSE_1000_ADC_REFERENCE_RESISTOR_INTERNAL_1, + .disableBuffer = false, + }, + .enableVbias = false, + }, + }, + [ADI_SENSE_1000_CHANNEL_ID_SENSOR_0] = { + .enableChannel = true, + .disablePublishing = false, + .compensationChannel = ADI_SENSE_1000_CHANNEL_ID_CJC_0, + .measurementsPerCycle = 1, + .extraSettlingTime = 0.0000, + .measurementUnit = ADI_SENSE_1000_MEASUREMENT_UNIT_CELSIUS, + .adcChannelConfig = { + .sensor = ADI_SENSE_1000_ADC_SENSOR_THERMOCOUPLE_K_DEF_L1, + .gain = ADI_SENSE_1000_ADC_GAIN_128X, + .current = { + .outputLevel = ADI_SENSE_1000_ADC_EXC_CURRENT_NONE, + .swapOption = ADI_SENSE_1000_ADC_EXC_CURRENT_SWAP_NONE, + }, + .filter = { + .type = ADI_SENSE_1000_ADC_FILTER_FIR_25SPS, + .fs = 0, + //.type = ADI_SENSE_1000_ADC_FILTER_SINC4, + //.fs = 1920, + }, + .reference = { + .type = ADI_SENSE_1000_ADC_REFERENCE_VOLTAGE_INTERNAL, + .disableBuffer = false, + }, + .enableVbias = true, + }, + }, + [ADI_SENSE_1000_CHANNEL_ID_VOLTAGE_0] = { + .enableChannel = true, + .disablePublishing = false, + .compensationChannel = ADI_SENSE_1000_CHANNEL_ID_NONE, + .measurementsPerCycle = 1, + .extraSettlingTime = 0.0000, + .measurementUnit = ADI_SENSE_1000_MEASUREMENT_UNIT_DEFAULT, + .adcChannelConfig = { + .sensor = ADI_SENSE_1000_ADC_SENSOR_VOLTAGE_PRESSURE_AMPHENOL_NPA300X, + .gain = ADI_SENSE_1000_ADC_GAIN_2X, + .current = { + .outputLevel = ADI_SENSE_1000_ADC_EXC_CURRENT_NONE, + .swapOption = ADI_SENSE_1000_ADC_EXC_CURRENT_SWAP_NONE, + }, + .filter = { + .type = ADI_SENSE_1000_ADC_FILTER_FIR_25SPS, + .fs = 0, + //.type = ADI_SENSE_1000_ADC_FILTER_SINC4, + //.fs = 1920, + }, + .reference = { + .type = ADI_SENSE_1000_ADC_REFERENCE_VOLTAGE_INTERNAL, + .disableBuffer = false, + }, + .enableVbias = false, + }, + }, + [ADI_SENSE_1000_CHANNEL_ID_I2C_0] = { + .enableChannel = true, + .disablePublishing = false, + .compensationChannel = ADI_SENSE_1000_CHANNEL_ID_NONE, + .measurementsPerCycle = 1, + .extraSettlingTime = 0.0000, + .i2cChannelConfig = { + .sensor = ADI_SENSE_1000_I2C_SENSOR_HUMIDITY_SENSIRION_SHT3X, + .deviceAddress = 0x44, + }, + }, + [ADI_SENSE_1000_CHANNEL_ID_SPI_0] = { + /* Accelerometer X-Axis (and common settings for physical channel) */ + .enableChannel = true, + .disablePublishing = false, + .compensationChannel = ADI_SENSE_1000_CHANNEL_ID_NONE, + .measurementsPerCycle = 1, + .extraSettlingTime = 10, + .offsetAdjustment = -0.15, + /* Optional threshold limits applied to the processed measurement results */ + .lowThreshold = -2.0, + .highThreshold = 2.0, + .spiChannelConfig = { + .sensor = ADI_SENSE_1000_SPI_SENSOR_ACCELEROMETER_ADI_ADXL362, + .configurationCommand = { + .command = { 0x0A, 0x2C, 0x03 }, /* +/-8G range */ + .commandLength = 3, + }, + }, + }, + [ADI_SENSE_1000_CHANNEL_ID_SPI_1] = { + /* Accelerometer Y-Axis (virtual channel) */ + .enableChannel = true, + .offsetAdjustment = -0.15, + /* Optional threshold limits applied to the processed measurement results */ + .lowThreshold = -2.0, + .highThreshold = 2.0, + }, + [ADI_SENSE_1000_CHANNEL_ID_SPI_2] = { + /* Accelerometer Z-Axis (virtual channel) */ + .enableChannel = true, + /* Optional adjustment applied to the PROCESSED OUTPUT value from the sensor */ + .offsetAdjustment = -0.4, + /* Optional threshold limits applied to the processed measurement results */ + .lowThreshold = -2, + .highThreshold = 2, + }, + }, + }, +}; +
diff -r 76fed7dd9235 -r 25a2bf666957 common/utils.c --- a/common/utils.c Thu Jan 25 16:00:23 2018 +0000 +++ b/common/utils.c Fri Aug 24 08:58:48 2018 +0000 @@ -1,389 +1,455 @@ -#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; -} +#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" : ""); + } +} + +void utils_printSamples_alt( + ADI_SENSE_DATA_SAMPLE *pSampleBuffer, + uint32_t nNumSamples) +{ + //for (uint32_t i = 0; i < nNumSamples; i++) + //{ + //temp_comp temp pressure himidity AccX AccY AccZ + ADI_SENSE_LOG_INFO("%8d\t%.5f\t%8d\t%.5f\t%8d\t%.5f\t%8d\t%.5f\t%8d\t%.5f\t%8d\t%.5f\t%8d\t%.5f\t", + //temp_comp + pSampleBuffer[0].rawValue, + pSampleBuffer[0].processedValue, + //temp + pSampleBuffer[1].rawValue, + pSampleBuffer[1].processedValue, + //pressure + pSampleBuffer[2].rawValue, + pSampleBuffer[2].processedValue, + //humidity + pSampleBuffer[3].rawValue, + pSampleBuffer[3].processedValue, + //AccX + pSampleBuffer[4].rawValue, + pSampleBuffer[4].processedValue, + //AccY + pSampleBuffer[5].rawValue, + pSampleBuffer[5].processedValue, + //AccZ + pSampleBuffer[6].rawValue, + pSampleBuffer[6].processedValue); + //} +} + +void utils_printSamples_pro( + ADI_SENSE_DATA_SAMPLE *pSampleBuffer, + uint32_t nNumSamples) +{ + //for (uint32_t i = 0; i < nNumSamples; i++) + //{ + //temp_comp temp pressure himidity AccX AccY AccZ + ADI_SENSE_LOG_INFO("%.5f %.5f %.5f %.5f %.5f %.5f %.5f", + //temp_comp + //pSampleBuffer[0].rawValue, + pSampleBuffer[0].processedValue, + //temp + //pSampleBuffer[1].rawValue, + pSampleBuffer[1].processedValue, + //pressure + //pSampleBuffer[2].rawValue, + pSampleBuffer[2].processedValue, + //humidity + //pSampleBuffer[3].rawValue, + pSampleBuffer[3].processedValue, + //AccX + //pSampleBuffer[4].rawValue, + pSampleBuffer[4].processedValue, + //AccY + //pSampleBuffer[5].rawValue, + pSampleBuffer[5].processedValue, + //AccZ + //pSampleBuffer[6].rawValue, + pSampleBuffer[6].processedValue); + //} +} + +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); + //use alternative print utils + //utils_printSamples_alt(pSampleBuffer, nCurrentSamples); + utils_printSamples_pro(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; +} +
diff -r 76fed7dd9235 -r 25a2bf666957 common/utils.h --- a/common/utils.h Thu Jan 25 16:00:23 2018 +0000 +++ b/common/utils.h Fri Aug 24 08:58:48 2018 +0000 @@ -1,46 +1,56 @@ -#ifndef __UTILS_H__ -#define __UTILS_H__ - -#include "inc/adi_sense_api.h" -#include "inc/adi_sense_1000/adi_sense_1000_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Utility function to print the status read from the ADI Sense device */ -void utils_printStatus( - ADI_SENSE_STATUS *pStatus); - -/* Utility function to print data samples read from the ADI Sense device */ -void utils_printSamples( - ADI_SENSE_DATA_SAMPLE *pSampleBuffer, - uint32_t numSamples); - -/* Utility function to register callbacks for ADI Sense device notification signals */ -ADI_SENSE_RESULT utils_registerCallbacks( - ADI_SENSE_DEVICE_HANDLE hDevice, - volatile bool_t *pbDataReady, - volatile bool_t *pbError, - volatile bool_t *pbAlert); - -/* Utility function to de-register callbacks for ADI Sense device notification signals */ -ADI_SENSE_RESULT utils_deregisterCallbacks( - ADI_SENSE_DEVICE_HANDLE hDevice); - -/* Utility function to run measurements on ADI Sense device, according to its current - * configuration, and display data samples and device status following each cycle */ -ADI_SENSE_RESULT utils_runMeasurement( - ADI_SENSE_DEVICE_HANDLE hDevice, - ADI_SENSE_MEASUREMENT_MODE eMeasurementMode); - -/* Utility function to retrieve and print the factory calibration coefficients table from the ADI Sense device */ -ADI_SENSE_RESULT utils_printCalTable( - ADI_SENSE_DEVICE_HANDLE hDevice); - -#ifdef __cplusplus -} -#endif - -#endif /* __UTILS_H__ */ +#ifndef __UTILS_H__ +#define __UTILS_H__ + +#include "inc/adi_sense_api.h" +#include "inc/adi_sense_1000/adi_sense_1000_api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Utility function to print the status read from the ADI Sense device */ +void utils_printStatus( + ADI_SENSE_STATUS *pStatus); +/* Utility function to print data samples read from the ADI Sense device */ +void utils_printSamples( + ADI_SENSE_DATA_SAMPLE *pSampleBuffer, + uint32_t numSamples); + +/* Alternative print utility */ +void utils_printSamples_alt( + ADI_SENSE_DATA_SAMPLE *pSampleBuffer, + uint32_t numSamples); + +/* Alternative print utility */ +void utils_printSamples_pro( + ADI_SENSE_DATA_SAMPLE *pSampleBuffer, + uint32_t numSamples); + +/* Utility function to register callbacks for ADI Sense device notification signals */ +ADI_SENSE_RESULT utils_registerCallbacks( + ADI_SENSE_DEVICE_HANDLE hDevice, + volatile bool_t *pbDataReady, + volatile bool_t *pbError, + volatile bool_t *pbAlert); + +/* Utility function to de-register callbacks for ADI Sense device notification signals */ +ADI_SENSE_RESULT utils_deregisterCallbacks( + ADI_SENSE_DEVICE_HANDLE hDevice); + +/* Utility function to run measurements on ADI Sense device, according to its current + * configuration, and display data samples and device status following each cycle */ +ADI_SENSE_RESULT utils_runMeasurement( + ADI_SENSE_DEVICE_HANDLE hDevice, + ADI_SENSE_MEASUREMENT_MODE eMeasurementMode); + +/* Utility function to retrieve and print the factory calibration coefficients table from the ADI Sense device */ +ADI_SENSE_RESULT utils_printCalTable( + ADI_SENSE_DEVICE_HANDLE hDevice); + +#ifdef __cplusplus +} +#endif + +#endif /* __UTILS_H__ */ +
diff -r 76fed7dd9235 -r 25a2bf666957 inc/JENKINS_AUTOGEN_PLATFORM.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/JENKINS_AUTOGEN_PLATFORM.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,7 @@ +#ifndef _JENKINS_AUTOGEN_PLATFORM_H_ +#define _JENKINS_AUTOGEN_PLATFORM_H_ + +#define PROSWIFT //#define MYSWIFT + +#endif +
diff -r 76fed7dd9235 -r 25a2bf666957 inc/adisense1000_boot.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/adisense1000_boot.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,24 @@ +#ifndef __ADISENSE1000_BOOT_ +#define __ADISENSE1000_BOOT_ + +#include "adi_sense_api.h" +#include "pc_interface/pc_serial.h" +#include "mbed.h" +#include "pc_interface/pc_interface.h" + +//config structs for channels +extern ADI_SENSE_CONFIG adi_sense_config; + +/* + Definitions +*/ + +/* + Function Prototypes +*/ + +//reset device to known state +uint8_t Adisense1000_Boot(void); + +#endif +
diff -r 76fed7dd9235 -r 25a2bf666957 inc/ble_interface/bl652.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/ble_interface/bl652.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,50 @@ +#ifndef __BL652_H_ +#define __BL652_H_ + + +/******************************************************************************/ +/* Include Files */ +/******************************************************************************/ + +#include <stdint.h> + +/******************************************************************************/ +/* BLE parameters */ +/******************************************************************************/ + +//size of buffers used +#define BLE_PACKET_SIZE 20 + +//parameters for da14580 +#define RESET_LENGTH 10 //ms + +#define BLE_TX_PACKET_DELAY 100 //ms + +#define AT_COMMAND_DELIMITER '\r' + +#define AT_COMMAND_ERROR "ERROR" + + +/******************************************************************************/ +/* Function Prototypes */ +/******************************************************************************/ + +//boot BLE module +uint32_t Bl652_Boot( void ); + +//Write to BLE over UART +uint32_t Bl652_Write( char *txBuffer, uint32_t byteCount ); + +//Read from BLE over UART +uint32_t Bl652_Read( char *rxBuffer, uint32_t byteCount ); + +//setup for callback based read +uint32_t Bl652_SetupReadCb( void *rxBuffer, uint32_t maxSize, volatile bool *bMessageReadFlag ); + +//clear read callback +uint32_t Bl652_ClearCb( void ); + +//wait until BLE is awake +uint32_t Bl652_WaitUntilAvailable( void ); + +#endif
diff -r 76fed7dd9235 -r 25a2bf666957 inc/ble_interface/ble_interface.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/ble_interface/ble_interface.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,27 @@ +#ifndef __BLE_INTERFACE_H_ +#define __BLE_INTERFACE_H_ + +#include "mbed.h" +#include "adi_sense_api.h" +#include "inc/adi_sense_1000/adi_sense_1000_api.h" +#include "myproswift_error_codes.h" +#include "myproswift_periph.h" +#include "bl652.h" + +/* + Definitions +*/ + +#define MAX_MEASUREMENT_CYCLES 1 + +#define BLE_PACKET_SIZE 20 +#define MEASUREMENT_NAME_MAX_LEN 15 +#define UNIT_NAME_MAX_LEN 3 +#define FIELD_NAMES_MAX_SIZE 16 + + +//parse a ble command, reading further bytes as required +uint32_t Ble_ParseCommand( char *bleRxBuffer ); + +#endif +
diff -r 76fed7dd9235 -r 25a2bf666957 inc/bootloader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/bootloader.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,18 @@ + +#ifndef __BOOTLOADER_H_ +#define __BOOTLOADER_H_ + + +#include <stdint.h> + +#include "mbed.h" + + +#define BOOTLOADER_FLAG_BACKUP_REG 0x00 + + +// Enter bootloader mode +void Bootloader_Init( void ); + + +#endif
diff -r 76fed7dd9235 -r 25a2bf666957 inc/communications.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/communications.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,28 @@ +#ifndef __COMMUNICATIONS_H_ +#define __COMMUNICATIONS_H_ + +#include "mbed.h" + +/* + Definitions +*/ + +#define TIMEOUT_3_SEC 3.0f + +/* + Function Prototypes +*/ + +//init a uart handle +int Uart_Init( Serial &serialHandle, int baudrate ); + +//write to serial comms using comms handle +int Uart_Write( Serial &serialHandle, const char* txBuffer, unsigned int length ); + +//read from serial comms using comms handle +int Uart_ReadCb( Serial &serialHandle, void ( *callback )( void ) ); + +//clear attached callback +int Uart_ClearCb( Serial &serialHandle ); + +#endif
diff -r 76fed7dd9235 -r 25a2bf666957 inc/eeprom_virtual/eeprom.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/eeprom_virtual/eeprom.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,130 @@ +/** + ****************************************************************************** + * @file EEPROM/EEPROM_Emulation/inc/eeprom.h + * @author MCD Application Team + * @brief This file contains all the functions prototypes for the EEPROM + * emulation firmware library. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright © 2017 STMicroelectronics International N.V. + * All rights reserved.</center></h2> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __EEPROM_H +#define __EEPROM_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f4xx_hal.h" + +/* Exported constants --------------------------------------------------------*/ + + + +/* EEPROM emulation firmware error codes */ +#define EE_OK (uint32_t)HAL_OK +#define EE_ERROR (uint32_t)HAL_ERROR +#define EE_BUSY (uint32_t)HAL_BUSY +#define EE_TIMEOUT (uint32_t)HAL_TIMEOUT + +/* Define the size of the sectors to be used */ +#define PAGE_SIZE (uint32_t)0x4000 /* Page size = 16KByte */ + +/* Device voltage range supposed to be [2.7V to 3.6V], the operation will + be done by word */ +#define VOLTAGE_RANGE (uint8_t)VOLTAGE_RANGE_3 + +/* EEPROM start address in Flash */ +#define EEPROM_START_ADDRESS ((uint32_t)0x08008000) /* EEPROM emulation start address: + from sector2 : after 16KByte of used + Flash memory */ + +/* Pages 0 and 1 base and end addresses */ +#define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0000)) +#define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1))) +#define PAGE0_ID FLASH_SECTOR_2 + +#define PAGE1_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + PAGE_SIZE)) +#define PAGE1_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1))) +#define PAGE1_ID FLASH_SECTOR_3 + +/* Used Flash pages for EEPROM emulation */ +#define PAGE0 ((uint16_t)0x0000) +#define PAGE1 ((uint16_t)0x0001) /* Page nb between PAGE0_BASE_ADDRESS & PAGE1_BASE_ADDRESS*/ + +/* No valid page define */ +#define NO_VALID_PAGE ((uint16_t)0x00AB) + +/* Page status definitions */ +#define ERASED ((uint16_t)0xFFFF) /* Page is empty */ +#define RECEIVE_DATA ((uint16_t)0xEEEE) /* Page is marked to receive data */ +#define VALID_PAGE ((uint16_t)0x0000) /* Page containing valid data */ + +/* Valid pages in read and write defines */ +#define READ_FROM_VALID_PAGE ((uint8_t)0x00) +#define WRITE_IN_VALID_PAGE ((uint8_t)0x01) + +/* Page full define */ +#define PAGE_FULL ((uint8_t)0x80) + +/* Variables' number */ +#define NB_OF_VAR ((uint8_t)0x02) + +//not sure why this is needed by the eeprom library +static uint16_t VirtAddVarTab[NB_OF_VAR] = {0x00, 0x01}; + +/* Exported types ------------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +uint16_t EE_Init(void); +uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data); +uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data); + +#ifdef __cplusplus +} +#endif + +#endif /* __EEPROM_H */ + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +
diff -r 76fed7dd9235 -r 25a2bf666957 inc/led.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/led.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,19 @@ +#ifndef __LED_H_ +#define __LED_H_ + +#include "myproswift_periph.h" + +#define LED_BLINK_PERIOD 0.2//s + +// Blink led to indicate device is booting +void Led_Boot( void ); + +// Hold led on to indicate boot complete +void Led_Idle( void ); + +// Function to toggle led +void Led_On( bool_t state ); + + +#endif +
diff -r 76fed7dd9235 -r 25a2bf666957 inc/myproswift_error_codes.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/myproswift_error_codes.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,42 @@ + + +/** + * @file my_proswift_error_codes.h + * @author Jake Greaves + * @date 05 Feb 2018 + * @brief Error codes used by both interfaces + */ + +#ifndef __MY_PROSWIFT_ERROR_CODES_H_ +#define __MY_PROSWIFT_ERROR_CODES_H_ + + +/** + * @brief Error values that may be returned. + */ +enum ErrorType { + NO_ERROR = 0x00, + NO_ERROR_BOOTLOADER = 0x01, + ERROR_NO_COMMAND_MATCHED = 0x10, + ERROR_EXPECTED_DELIMITER = 0x11, + ERROR_SET_CONFIG = 0x20, + ERROR_UPDATE_CONFIG = 0x21, + ERROR_EXPECTED_COMMAND = 0x22, + ERROR_GET_DRDY_INFO = 0x30, + ERROR_ALLOCATE_BUFFER = 0x31, + ERROR_GPIO_CALLBACK_REG = 0x32, + ERROR_START_MEASUREMENT = 0x33, + ERROR_GET_DATA = 0x34, + ERROR_SAMPLE_COUNT_MISMATCH = 0x35, + ERROR_STREAM_NOT_STARTED = 0x36, + ERROR_STOP_MEASUREMENT = 0x37, + ERROR_EXPECTED_CHANNEL = 0x40, + ERROR_EXPECTED_KEYWORD = 0x41, + ERROR_EXPECTED_VALUE = 0x42, + ERROR_CONVERSION_FAILED = 0x43, + ERROR_ATTR_NOT_SUPPORTED_ON_CHANNEL = 0x44, + ERROR_UNDEFINED = 0xF0 +}; + + +#endif
diff -r 76fed7dd9235 -r 25a2bf666957 inc/myproswift_eval.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/myproswift_eval.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,20 @@ +#ifndef __MYSWIFT_H_ +#define __MYSWIFT_H_ + +#include <stdint.h> +#include <stdbool.h> + +/* + Definitions +*/ + +#define MSG_BUFFER_MAX_SIZE 500 +#define BLE_BUFFER_MAX_SIZE 20 + +/* + Function Prototypes +*/ + +int32_t MyProSwift_Command( bool bleActive ); + +#endif \ No newline at end of file
diff -r 76fed7dd9235 -r 25a2bf666957 inc/myproswift_periph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/myproswift_periph.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,157 @@ +#ifndef __MYSWIFT_PERIPH_H_ +#define __MYSWIFT_PERIPH_H_ + + +#include "mbed.h" +#include "adi_sense_api.h" +#include "JENKINS_AUTOGEN_PLATFORM.h" + + +#ifdef MYSWIFT +#define DEVICE_NAME "ADI MySwift" +#define FIRMWARE_VERSION "Version 1.0" +#endif + + +#ifdef PROSWIFT +#define DEVICE_NAME "ADI ProSwift" +#define FIRMWARE_VERSION "Version 1.0" +#endif + + +#if defined(MYSWIFT) && defined(PROSWIFT) +#error "Only one platform must be defined" +#endif + + +#if !(defined(MYSWIFT) || defined(PROSWIFT)) +#error "At least one platform must be defined" +#endif + +#define BL652 + +/* + ****************************************************************************** + * ADISense1000 + *----------------------------------------------------------------------------- + */ + +#ifdef MYSWIFT +#define SENSE_SPI_FREQUENCY 2000000 +#define SENSE_SPI_MOSI PA_7 +#define SENSE_SPI_MISO PA_6 +#define SENSE_SPI_SCK PA_5 +#define SENSE_SPI_CS PC_7 +//pin declarations +#define SENSE_RST_PIN PB_10 +#define SENSE_ERROR_PIN PB_3 +#define SENSE_ALERT_PIN PB_5 +#define SENSE_DREADY_PIN PB_4 +#endif + + +#ifdef PROSWIFT +//spi frequency +#define SENSE_SPI_FREQUENCY 2000000 +#define SENSE_SPI_MOSI SPI_MOSI +#define SENSE_SPI_MISO SPI_MISO +#define SENSE_SPI_SCK SPI_SCK +#define SENSE_SPI_CS SPI_CS +//pin declarations +#define SENSE_RST_PIN PB_10 +#define SENSE_ERROR_PIN PB_3 +#define SENSE_ALERT_PIN PB_5 +#define SENSE_DREADY_PIN PB_4 +#endif + +/* + ****************************************************************************** + * Bluetooth Low Energy + *----------------------------------------------------------------------------- + */ + +#ifdef BL652 + +#ifdef MYSWIFT +//pin declarations +#define BLE_RST_PIN PA_8 +#define BLE_RTS_PIN PA_0 +#define BLE_CTS_PIN PB_2 +//uart pins and baudrate +#define BLE_BAUD_RATE 115200 +#define BLE_SERIAL_TX PA_2 +#define BLE_SERIAL_RX PA_3 +//mode pins +#define BLE_MODE_0_PIN PB_0 +#define BLE_MODE_1_PIN PA_1 +#endif + +#ifdef PROSWIFT +//pin declarations +#define BLE_RST_PIN PA_0 +#define BLE_RTS_PIN PA_8 +#define BLE_CTS_PIN PA_10 +//uart pins and baudrate +#define BLE_BAUD_RATE 115200 +#define BLE_SERIAL_TX PA_2 +#define BLE_SERIAL_RX PA_3 +//mode pins +#define BLE_MODE_0_PIN PB_0 +#define BLE_MODE_1_PIN PA_4 +#endif + +#endif + + +/* + ****************************************************************************** + * PC Serial + *----------------------------------------------------------------------------- + */ + +#ifdef MYSWIFT +#define PC_UART_TX_PIN PA_9 +#define PC_UART_RX_PIN PA_10 +#define PC_UART_BAUDRATE 921600 +#endif + + +#ifdef PROSWIFT +#define PC_UART_TX_PIN PA_11 +#define PC_UART_RX_PIN PA_12 +#define PC_UART_BAUDRATE 115200 +#endif + +/* + ****************************************************************************** + * Battery + *----------------------------------------------------------------------------- + */ +#ifdef MYSWIFT +//#define VCC 3.3 +//#define BATTERY_V_PIN PH_0 +#endif + +/* + ****************************************************************************** + * Status LED + *----------------------------------------------------------------------------- + */ + +#ifdef MYSWIFT +#define STATUS_LED_PIN PC_8 +#endif + +#ifdef PROSWIFT +#define STATUS_LED_PIN LED1 +#endif + +#endif + +/* + ****************************************************************************** + * VIRT_EEPROM + *----------------------------------------------------------------------------- + */ + +#undef VIRT_EEPROM
diff -r 76fed7dd9235 -r 25a2bf666957 inc/pc_interface/pc_conversions.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/pc_interface/pc_conversions.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,346 @@ +/** + * @file pc_conversions.h + * @author Jake Greaves + * @date 15 Dec 2017 + * @brief Conversions between config file values and register settings + */ + + +#ifndef __PC_CONVERSIONS_H_ +#define __PC_CONVERSIONS_H_ + + +#include "adi_sense_config_types.h" + + +/*! Calculate sizeof struct array containing possible values */ +#if !defined(ARRAY_SIZE) +#define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) +#endif + + +/*! Struct typedef of possible config values, coupled with equivalent register values */ +typedef struct { + char *stringVal; + int32_t structVal; +} StringToStructVals; + +/*! Struct containing config file keyword, paired with the conversion struct array and the array size */ +struct keywordConvert { + char *stringEquiv; + StringToStructVals *valsConvert; + unsigned int valCount; +}; + + +/*! ProductID Values */ +static StringToStructVals productIdVals[] = { + {"N/A", ADI_SENSE_PRODUCT_ID_1000}, + {"0x0020", ADI_SENSE_PRODUCT_ID_1000} +}; + +/*! OperationalMode Values */ +static StringToStructVals operationalModeVals[] = { + {"N/A", ADI_SENSE_1000_OPERATING_MODE_SINGLECYCLE}, + {"SingleCycle", ADI_SENSE_1000_OPERATING_MODE_SINGLECYCLE}, + {"ContinuousConversion", ADI_SENSE_1000_OPERATING_MODE_CONTINUOUS}, + {"MultiCycle", ADI_SENSE_1000_OPERATING_MODE_MULTICYCLE} +}; + +/*! PowerMode Values */ +static StringToStructVals powerModeVals[] = { + {"N/A", ADI_SENSE_1000_POWER_MODE_LOW}, + {"Low", ADI_SENSE_1000_POWER_MODE_LOW}, + {"Mid", ADI_SENSE_1000_POWER_MODE_MID}, + {"Full", ADI_SENSE_1000_POWER_MODE_FULL} +}; + +/*! CycleTime Values */ +static StringToStructVals cycleTimeVals[] = { + {"N/A", 0} +}; + +/*! DataReadyMode Values */ +static StringToStructVals dataReadyModeVals[] = { + {"N/A", ADI_SENSE_1000_DATAREADY_PER_CONVERSION}, + {"PerMeasurement", ADI_SENSE_1000_DATAREADY_PER_CONVERSION}, + {"PerCycle", ADI_SENSE_1000_DATAREADY_PER_CYCLE}, + {"PerFifoFill", ADI_SENSE_1000_DATAREADY_PER_MULTICYCLE_BURST} +}; + +/*! GlobalDiagnostic Values */ +static StringToStructVals globalDiagnosticVals[] = { + {"N/A", 1}, + {"False", 1}, + {"True", 0} +}; + +/*! MeasurementDiagnostic Values */ +static StringToStructVals measurementDiagnosticVals[] = { + {"N/A", 1}, + {"False", 1}, + {"True", 0} +}; + +/*! DiagnosticFrequency Values */ +static StringToStructVals diagnosticFrequencyVals[] = { + {"N/A", ADI_SENSE_1000_OPEN_SENSOR_DIAGNOSTICS_DISABLED}, + {"None", ADI_SENSE_1000_OPEN_SENSOR_DIAGNOSTICS_DISABLED}, + {"PerCycle", ADI_SENSE_1000_OPEN_SENSOR_DIAGNOSTICS_PER_CYCLE}, + {"Per100Cycles", ADI_SENSE_1000_OPEN_SENSOR_DIAGNOSTICS_PER_100_CYCLES}, + {"Per1000Cycles", ADI_SENSE_1000_OPEN_SENSOR_DIAGNOSTICS_PER_1000_CYCLES} +}; + +/*! EnableChannel Values */ +static StringToStructVals enableChannelVals[] = { + {"N/A", 0}, + {"False", 0}, + {"True", 1} +}; + +/*! MeasurementsPerCycle Values */ +static StringToStructVals measurementsPerCycleVals[] = { + {"N/A", 1} +}; + +/*! MeasurementsPerCycle Values */ +static StringToStructVals settlingTimeVals[] = { + {"N/A", 0} +}; + +/*! PublishMeasurement Values */ +static StringToStructVals publishMeasurementVals[] = { + {"N/A", 0}, + {"False", 1}, + {"True", 0} +}; +/*! ChannelID Values */ +static StringToStructVals channelIdVals[] = { + {"N/A", ADI_SENSE_1000_CHANNEL_ID_NONE}, + {"Cjc0", ADI_SENSE_1000_CHANNEL_ID_CJC_0}, + {"Cjc1", ADI_SENSE_1000_CHANNEL_ID_CJC_1}, + {"Sensor0", ADI_SENSE_1000_CHANNEL_ID_SENSOR_0}, + {"Sensor1", ADI_SENSE_1000_CHANNEL_ID_SENSOR_1}, + {"Sensor2", ADI_SENSE_1000_CHANNEL_ID_SENSOR_2}, + {"Sensor3", ADI_SENSE_1000_CHANNEL_ID_SENSOR_3}, + {"Voltage0", ADI_SENSE_1000_CHANNEL_ID_VOLTAGE_0}, + {"Current0", ADI_SENSE_1000_CHANNEL_ID_CURRENT_0}, + {"I2c0", ADI_SENSE_1000_CHANNEL_ID_I2C_0}, + {"I2c1", ADI_SENSE_1000_CHANNEL_ID_I2C_1}, + {"Spi0", ADI_SENSE_1000_CHANNEL_ID_SPI_0}, + {"Spi1", ADI_SENSE_1000_CHANNEL_ID_SPI_1}, + {"Spi2", ADI_SENSE_1000_CHANNEL_ID_SPI_2} +}; + +/*! UnitTranslation Values */ +static StringToStructVals unitTranslationVals[] = { + {"N/A", ADI_SENSE_1000_MEASUREMENT_UNIT_DEFAULT}, + {"Celsius", ADI_SENSE_1000_MEASUREMENT_UNIT_CELSIUS}, + {"Fahrenheit", ADI_SENSE_1000_MEASUREMENT_UNIT_FAHRENHEIT}, + {"Psi", ADI_SENSE_1000_MEASUREMENT_UNIT_DEFAULT}, //handle as default + {"%", ADI_SENSE_1000_MEASUREMENT_UNIT_DEFAULT} //handle as default +}; + +/*! SensorID Values */ +static StringToStructVals sensorVals[] = { + {"N/A", ADI_SENSE_1000_ADC_SENSOR_THERMOCOUPLE_T_DEF_L1}, + {"Thermocouple.T.Def.L1", ADI_SENSE_1000_ADC_SENSOR_THERMOCOUPLE_T_DEF_L1}, + {"Thermocouple.J.Def.L1", ADI_SENSE_1000_ADC_SENSOR_THERMOCOUPLE_J_DEF_L1}, + {"Thermocouple.K.Def.L1", ADI_SENSE_1000_ADC_SENSOR_THERMOCOUPLE_K_DEF_L1}, + + {"RTD.2W.PT100.Def.L1", ADI_SENSE_1000_ADC_SENSOR_RTD_2WIRE_PT100_DEF_L1}, + {"RTD.2W.PT1000.Def.L1", ADI_SENSE_1000_ADC_SENSOR_RTD_2WIRE_PT1000_DEF_L1}, + {"RTD.3W.PT100.Def.L1", ADI_SENSE_1000_ADC_SENSOR_RTD_3WIRE_PT100_DEF_L1}, + {"RTD.3W.PT1000.Def.L1", ADI_SENSE_1000_ADC_SENSOR_RTD_3WIRE_PT1000_DEF_L1}, + {"RTD.4W.PT100.Def.L1", ADI_SENSE_1000_ADC_SENSOR_RTD_4WIRE_PT100_DEF_L1}, + {"RTD.4W.PT1000.Def.L1", ADI_SENSE_1000_ADC_SENSOR_RTD_4WIRE_PT1000_DEF_L1}, + + {"Thermistor.10K.A.Def.L1", ADI_SENSE_1000_ADC_SENSOR_THERMISTOR_A_10K_DEF_L1}, + {"Thermistor.10K.B.Def.L1", ADI_SENSE_1000_ADC_SENSOR_THERMISTOR_B_10K_DEF_L1}, + + {"Voltage.Pressure.A.Def.L1", ADI_SENSE_1000_ADC_SENSOR_VOLTAGE_PRESSURE_HONEYWELL_TRUSTABILITY}, + {"Voltage.Pressure.B.Def.L1", ADI_SENSE_1000_ADC_SENSOR_VOLTAGE_PRESSURE_AMPHENOL_NPA300X}, + + {"Current.Pressure.A.Def.L1", ADI_SENSE_1000_ADC_SENSOR_CURRENT_PRESSURE_HONEYWELL_PX2}, + + {"I2C.Pressure.A.Def.L1", ADI_SENSE_1000_I2C_SENSOR_HUMIDITY_HONEYWELL_HUMIDICON}, + {"I2C.Pressure.B.Def.L1", ADI_SENSE_1000_I2C_SENSOR_HUMIDITY_SENSIRION_SHT3X}, + + {"SPI.Pressure.A.Def.L1", ADI_SENSE_1000_SPI_SENSOR_PRESSURE_HONEYWELL_TRUSTABILITY}, + {"SPI.Accelerometer.A.Def.L1",ADI_SENSE_1000_SPI_SENSOR_ACCELEROMETER_ADI_ADXL362} +}; + +/*! MeasurementMaxValue Values */ +static StringToStructVals measurementMaxVals[] = { + {"N/A", 0} +}; + +/*! MeasurementMinValue Values */ +static StringToStructVals measurementMinVals[] = { + {"N/A", 0} +}; + +/*! Gain Values */ +static StringToStructVals gainVals[] = { + {"N/A", ADI_SENSE_1000_ADC_GAIN_1X}, + {"1", ADI_SENSE_1000_ADC_GAIN_1X}, + {"2", ADI_SENSE_1000_ADC_GAIN_2X}, + {"4", ADI_SENSE_1000_ADC_GAIN_4X}, + {"8", ADI_SENSE_1000_ADC_GAIN_8X}, + {"16", ADI_SENSE_1000_ADC_GAIN_16X}, + {"32", ADI_SENSE_1000_ADC_GAIN_32X}, + {"64", ADI_SENSE_1000_ADC_GAIN_64X}, + {"128", ADI_SENSE_1000_ADC_GAIN_128X} +}; + +/*! CurrentOutput Values */ +static StringToStructVals currentOutputLevelVals[] = { + {"N/A", ADI_SENSE_1000_ADC_EXC_CURRENT_NONE}, + {"0.00005", ADI_SENSE_1000_ADC_EXC_CURRENT_50uA}, + {"0.0001", ADI_SENSE_1000_ADC_EXC_CURRENT_100uA}, + {"0.00025", ADI_SENSE_1000_ADC_EXC_CURRENT_250uA}, + {"0.0005", ADI_SENSE_1000_ADC_EXC_CURRENT_500uA}, + {"0.00075", ADI_SENSE_1000_ADC_EXC_CURRENT_750uA}, + {"0.001", ADI_SENSE_1000_ADC_EXC_CURRENT_1000uA} +}; + +/*! FilterType Values */ +static StringToStructVals filterTypeVals[] = { + {"N/A", ADI_SENSE_1000_ADC_FILTER_SINC4}, + {"Sinc.4", ADI_SENSE_1000_ADC_FILTER_SINC4}, + {"FIR.20SPS", ADI_SENSE_1000_ADC_FILTER_FIR_20SPS}, + {"FIR.25SPS", ADI_SENSE_1000_ADC_FILTER_FIR_25SPS} +}; + +/*! FS Values */ +static StringToStructVals fsVals[] = { + {"N/A", 0} +}; + +/*! Truth table used to determine reference settings due to differences in header and config file*/ +#define REF_SELECT_REFIN1 "Refin1" +#define REF_SELECT_REFIN2 "Refin2" +#define REF_SELECT_INTERNAL "Internal" + +/*! ReferenceResistorSelect Values*/ +#define REF_RES_SELECT_INTERNAL "Internal" +#define REF_RES_SELECT_EXTERNAL "External" +#define REF_RES_SELECT_NA "N/A" + +/*! ReferenceDisable Values */ +static StringToStructVals referenceDisableBufferVals[] = { + {"N/A", 0}, + {"False", 0}, + {"True", 1} +}; + +/*! EnableVbias Values */ +static StringToStructVals enableVbiasVals[] = { + {"N/A", 0}, + {"False", 0}, + {"True", 1} +}; + +/*! DeviceAddress Values */ +static StringToStructVals deviceAddressVals[] = { + {"N/A", 0} +}; + + +/*! Enum to identify the keyword being parsed. This relates directly to keywordConvert[]*/ +enum CONFIG_ATTRIBUTE { + PRODUCT_ID = 0, + OPERATIONAL_MODE, + POWER_MODE, + CYCLE_TIME, + DATA_READY_MODE, + GLOBAL_DIAGNOSTICS, + MEASUREMENT_SPECIFIC_DIAGNOSTICS, + DIAGNOSTIC_MEASUREMENT_FREQUENCY, + + MEASUREMENT_ENABLE, + MEASUREMENTS_PER_CYCLE, + SETTLING_TIME, + SENSOR_TYPE, + MEASUREMENT_MAX_VALUE, + MEASUREMENT_MIN_VALUE, + GAIN, + VBIAS_ENABLE, + EXCITATION_CURRENT, + REFERENCE, + FILTER_TYPE, + FILTER_FS, + ASSIGNED_COMPENSATION_MEASUREMENT_CHANNEL, + PUBLISH_MEASUREMENT, + DISPLAY_UNIT, + + DEVICE_ADDRESS, + //NOT NEEDED FOR FIRST SAMPLING + /* + READ_COMMAND, + CONFIG_COMMAND, + NUMBER_OF_BITS, + FRAME_WIDTH, + LEFT_ALIGNMENT, + DATA_ENDIANNESS, + OFFSET, + CODING, + CPOL_CPHA, + */ + + //size of enum + ENUM_ATTRIBUTE_SIZE +}; + + +/*! Struct used to match a keyword from the config file and locate a struct array of possible values*/ +static struct keywordConvert keywordConvert[] = { + //string //string values to struct values//amount of possible string values + //device wide parameters + {"ProductID", productIdVals, ARRAY_SIZE(productIdVals)}, + {"OperationalMode", operationalModeVals, ARRAY_SIZE(operationalModeVals)}, + {"PowerMode", powerModeVals, ARRAY_SIZE(powerModeVals)}, + {"CycleTime", cycleTimeVals, ARRAY_SIZE(cycleTimeVals)}, + {"DataReadyMode", dataReadyModeVals, ARRAY_SIZE(dataReadyModeVals)}, + {"GlobalDiagnostics", globalDiagnosticVals, ARRAY_SIZE(globalDiagnosticVals)}, + {"MeasurementSpecificDiagnostics", measurementDiagnosticVals, ARRAY_SIZE(measurementDiagnosticVals)}, + {"DiagnosticMeasurementFrequency", diagnosticFrequencyVals, ARRAY_SIZE(diagnosticFrequencyVals)}, + + //channel parameters + {"MeasurementEnable", enableChannelVals, ARRAY_SIZE(enableChannelVals)}, + {"MeasurementsPerCycle", measurementsPerCycleVals, ARRAY_SIZE(measurementsPerCycleVals)}, + {"SettlingTime", settlingTimeVals, ARRAY_SIZE(settlingTimeVals)}, /*< Requires two arguments, see documentation */ + {"SensorType", sensorVals, ARRAY_SIZE(sensorVals)}, + {"MeasurementMaxValue", measurementMaxVals, ARRAY_SIZE(measurementMaxVals)}, + {"MeasurementMinValue", measurementMinVals, ARRAY_SIZE(measurementMinVals)}, + {"Gain", gainVals, ARRAY_SIZE(gainVals)}, + {"VBiasEnable", enableVbiasVals, ARRAY_SIZE(enableVbiasVals)}, + {"ExcitationCurrent", currentOutputLevelVals, ARRAY_SIZE(currentOutputLevelVals)}, + {"Reference", 0, 0}, /*< Requires four arguments, see documentation. Handled by #define truth table */ + {"FilterType", filterTypeVals, ARRAY_SIZE(filterTypeVals)}, + {"FS", fsVals, ARRAY_SIZE(fsVals)}, + {"AssignedCompensationMeasurementChannel", channelIdVals, ARRAY_SIZE(channelIdVals)}, + {"PublishMeasurement", publishMeasurementVals, ARRAY_SIZE(publishMeasurementVals)}, + {"DisplayUnit", unitTranslationVals, ARRAY_SIZE(unitTranslationVals)}, + + //LUT and COEFF Table input here + + //digital parameters + {"DeviceAddress", deviceAddressVals, ARRAY_SIZE(deviceAddressVals)} + //NOT NEEDED FOR FIRST SAMPLING + /* + {"ReadCommand", NULL, 0}, + {"ConfigCommand", NULL, 0}, + {"NumberOfBits", NULL, 0}, + {"FrameWidth", NULL, 0}, + {"LeftAlignment", NULL, 0}, + {"DataEndianness", NULL, 0}, + {"Offset", NULL, 0}, + {"Coding", NULL, 0}, + {"CPOL_CPHA", NULL, 0} + */ +}; + + +#endif +
diff -r 76fed7dd9235 -r 25a2bf666957 inc/pc_interface/pc_interface.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/pc_interface/pc_interface.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,217 @@ + + +/** + * @file pc_interface.h + * @author Jake Greaves + * @date 21 Dec 2017 + * @brief The main interface to the pc application. + * + * This file handles all commands to and from the PC + * application. + */ + +#ifndef __PC_INTERFACE_H_ +#define __PC_INTERFACE_H_ + +#include "string.h" +#include "adi_sense_api.h" +#include "adi_sense_1000/adi_sense_1000_api.h" +#include "pc_interface/pc_serial.h" +#include "pc_interface/pc_conversions.h" +#include "myproswift_periph.h" +#include "core_cm4.h" +#include "myproswift_error_codes.h" +#include "rcc_backup_registers/rcc_backup_registers.h" +#include "eeprom_virtual/eeprom.h" + +/* + Definitions +*/ + +#define RESPONSE_BUFFER_SIZE 256 +#define PC_DELIMITER '\n' +#define PC_SEPERATOR ',' + +#undef DEBUG +#define BITP_VALID_DATA (7) + +/* + Command List +*/ + + +#define COMMAND_DEVICE_INFO 'i' +#define COMMAND_FLASH_LED 'f' +#define COMMAND_RESET 'r' +#define COMMAND_CONFIGURE 'c' +#define COMMAND_APPLY 'u' +#define COMMAND_SAMPLE 's' +#define COMMAND_START_STREAM 'd' +#define COMMAND_STOP_STREAM 'h' +#define COMMAND_UPDATE_FW_VERSION 'v' + +//not sure why this is needed by the eeprom library +extern uint16_t VirtAddVarTab[NB_OF_VAR]; + +/* + Function Prototypes +*/ + +/** + * @brief Tell any connected device that device is ready to use + * + * @param bBootLoader If device is entering bootloader, a different success code is given. + */ +int Pc_ResetSuccess(bool_t bBootLoader); + +/** + * @brief Read the next arg from a string. + * + * This function scans through the given command string + * searching for either the seperator value or the delimiter. + * On finding either of these chars, all text before is returned + * as the argument. If the size limit is reached before a delimiter + * this functions returns an error. The flag variable is set when + * the delimiter is found, useful for debugging and error handling + * when more arguments might be expected. + * + * @param command Command string to be analysed. + * @param arg A found arg will be returned to this address. + * @param size The max size of the arg buffer. + * @param flag Set when delimiter is found. + * + * @return Returns 0 on success, 1 on error. + * + * @see PC_DELIMITER + * @see PC_SEPERATOR + */ +static int pc_read_next_arg(char *command, char *arg, int size, bool *flag); + +/** + * @brief Parse the device info command. + * + * This function handles the device info command, responding to the PC + * with the device name, battery voltage and firmware version. + * + * @return Returns 0 on success, 1 on error. + */ +static int pc_parse_device_info(void); + +/** + * @brief Parse the flash led command. + * + * This function handles the flash led command, pulsing an led + * to identify this device. This function also responds to the PC + * with the status code. + * + * @return Returns 0 on success, 1 on error. + */ +static int pc_parse_flash_led(void); + +/** + * @brief Reset the device. + * + * This function handles the reset command, performing a soft + * reset on the device. The reponse to the pc is handled in the boot + * sequence for this device. + * + * @return Returns 0 on success, 1 on error. + */ +static int pc_parse_reset(void); + +/** + * @brief Parse the configure command. + * + * This function handles the configure command. Identifiers such as channel, + * keyword and value are parsed and converted to struct values. The + * configure struct is updated and applied to the device. + * + * @param commandString Args are parsed from this string. + * + * @return Returns 0 on success, 1 on error. + */ +static int pc_parse_configure(char *commandString); + +/** + * @brief Support for the parse configure command. + * + * If the configure command receives no channel, the configuration is for the + * entire device. This function parses and applies the new value to the + * configuration struct. + * + * @param attribute The attribute enum identifying which part of the struct + * is to be changed. + * + * @param commandString The command string incase arguments are expected. + * + * @return Returns 0 on success, 1 on error. + */ +static int pc_parse_configure_device(CONFIG_ATTRIBUTE attribute, char *commandString); + +/** + * @brief Support for the parse configure command. + * + * If the configure command receives a channel, the configuration is channel + * specific. This function parses and applies the new value to the + * configuration struct. + * + * @param channelIndex Which channel is to be configured. + * + * @param attribute The attribute enum identifying which part of the struct + * is to be changed. + * + * @param commandString The command string incase arguments are expected. + * + * @return Returns 0 on success, 1 on error. + */ +static int pc_parse_configure_channel(ADI_SENSE_1000_CHANNEL_ID channelIndex, CONFIG_ATTRIBUTE attribute, char *commandString); + +/** + * @brief Callback for sampling. Drdy is tied to this. + */ +static void pc_data_ready_callback( + ADI_SENSE_GPIO_PIN ePinId, + void *pArg); + +/** + * @brief Parse the sample command. + * + * Obtain as many samples as required for the given channels and return the raw + * 32-bit floats to the PC. + * + * @param commandString The amount of measurement cycles are obtained from this. + * + * @return Returns 0 on success, 1 on error. + */ +static int pc_parse_sample(char *commandString); + +/** + * @brief Parse the start stream command. + * + * Begin the sample stream, pushing out samples as fast as possible to the PC. + * + * @return Returns 0 on success, 1 on error. + */ +static int pc_parse_start_stream(void); + +/** + * @brief Handle an error. + * + * Send an error code to the PC. + * + * @return Returns 0 on success, 1 on error. + */ +int pc_handle_error(ErrorType error); + +/** + * @brief Find which command to be executed. + * + * parse the command character and execute the appropriate command. + * + * @param commandString the received command from the PC + * + * @return Returns 0 on success, 1 on error. + */ +int Pc_ParseCommand( char *commandString ); + +#endif
diff -r 76fed7dd9235 -r 25a2bf666957 inc/pc_interface/pc_serial.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/pc_interface/pc_serial.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,42 @@ +#ifndef __PC_SERIAL_H_ +#define __PC_SERIAL_H_ + +#include "mbed.h" +#include "stdarg.h" +#include "inc/communications.h" + +/* + Definitions +*/ + +//size of buffers used +#define PC_BUFFER_SIZE 100 + +//uart pins and baudrate +#define PC_BAUD_RATE 115200 +#define PC_SERIAL_TX PA_11 +#define PC_SERIAL_RX PA_12 + +/* + Function Prototypes +*/ + +//setup the callbck and vars necessary to read a pc json message +uint32_t Pc_SetupReadLineCb( char *rxBuffer, uint32_t maxSize, volatile bool *bMessageReadFlag ); + +//clear callback on pc serial handle +uint32_t Pc_ClearReadLineCb( void ); + +//read from pc +uint32_t Pc_Read( char *rxBuffer, uint32_t maxSize ); + +//wrapper for printf for general messages +uint32_t Pc_Write( const char* txBuffer, uint32_t size ); + +//wrapper for printf for error messages +uint32_t Pc_WriteError( const char* txBuffer, ... ); + +//wrapper for printf for debug messages +uint32_t Pc_WriteDebug( const char* txBuffer, ... ); + +#endif
diff -r 76fed7dd9235 -r 25a2bf666957 inc/rcc_backup_registers/rcc_backup_registers.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/inc/rcc_backup_registers/rcc_backup_registers.h Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,37 @@ +/** + * @file rcc_backup_registers.h + * @author Jake Greaves + * @date 12 Feb 2018 + * @brief Interface functions for writing to back-up registers + */ + +#ifndef __RCC_BACKUP_REGISTERS_H_ +#define __RCC_BACKUP_REGISTERS_H_ + + +#include "stm32f4xx_hal.h" + +/** + * @brief Read a variable from the RCC registers + * + * Read back a variable from a given register and return it. + * + * @param BackupRegister The register to read. + * + * @return Returns the value of the register. + */ +uint32_t Rcc_ReadBackupReg( uint32_t BackupRegister ); + +/** + * @brief Parse the device info command. + * + * This function handles the device info command, responding to the PC + * with the device name, battery voltage and firmware version. + * + * @return Returns 0 on success, 1 on error. + */ +void Rcc_WriteBackupReg( uint32_t BackupRegister, uint32_t data ); + + +#endif +
diff -r 76fed7dd9235 -r 25a2bf666957 main.cpp --- a/main.cpp Thu Jan 25 16:00:23 2018 +0000 +++ b/main.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -2,144 +2,92 @@ ****************************************************************************** * file: main.cpp *----------------------------------------------------------------------------- - * -Copyright 2017 (c) Analog Devices, Inc. - -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - - Neither the name of Analog Devices, Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - The use of this software may or may not infringe the patent rights - of one or more patent holders. This license does not release you - from the requirement that you obtain separate licenses from these - patent holders to use this software. - - Use of the software either in source or binary form, must be run - on or directly connected to an Analog Devices Inc. component. - -THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, -INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * *****************************************************************************/ #include "mbed.h" #include "inc/adi_sense_api.h" -#include "inc/adi_sense_1000/adi_sense_1000_api.h" #include "inc/adi_sense_log.h" #include "common/utils.h" -extern ADI_SENSE_CONFIG config; - -/* Change the following pointer to select any of the configurations above */ -static ADI_SENSE_CONFIG *pSelectedConfig = &config; +//additional libraries +#include "adisense1000_boot.h" +#include "ble_interface/ble_interface.h" +#include "myproswift_eval.h" +#include "eeprom_virtual/eeprom.h" +#include "myproswift_periph.h" +#include "led.h" +#include "bootloader.h" +#include "rcc_backup_registers.h" -static ADI_SENSE_CONNECTION connectionInfo = { - .type = ADI_SENSE_CONNECTION_TYPE_SPI, - .spi = { - .mosiPin = SPI_MOSI, - .misoPin = SPI_MISO, - .sckPin = SPI_SCK, - .csPin = D10, - .maxSpeedHz = 2000000, - }, - .gpio = { - .resetPin = D6, - .errorPin = D3, - .alertPin = D4, - .datareadyPin = D5, - }, -}; +#ifdef BL652 +#include "ble_interface/bl652.h" +#endif -int main() + +int main( void ) { - ADI_SENSE_RESULT res; - ADI_SENSE_DEVICE_HANDLE hDevice; - ADI_SENSE_MEASUREMENT_MODE eMeasurementMode = ADI_SENSE_MEASUREMENT_MODE_NORMAL; - bool_t bDeviceReady; - - /* - * Open an ADI Sense device instance. - */ - res = adi_sense_Open(0, &connectionInfo, &hDevice); - if (res != ADI_SENSE_SUCCESS) - { - ADI_SENSE_LOG_ERROR("Failed to open device instance"); - return res; - } - - /* - * Reset the given ADI Sense device.... - */ - ADI_SENSE_LOG_INFO("Resetting ADI Sense device, please wait..."); - res = adi_sense_Reset(hDevice); - if (res != ADI_SENSE_SUCCESS) - { - ADI_SENSE_LOG_ERROR("Failed to reset device"); - return res; + int ret = 1; + bool bleActive; + + // Indicate device is booting + Led_Boot(); + + // Check if device needs to enter bootloader function, this is set via a PC command + // Flag is stored in RTC registers that persist while vbat is powered + bool_t bBootLoader = Rcc_ReadBackupReg( BOOTLOADER_FLAG_BACKUP_REG ) == 1 ? true : false; + if( bBootLoader ) { + + // Let user know device is entering bootloader mode + Pc_ResetSuccess( bBootLoader ); + + // Jump to bootloader + Bootloader_Init(); } - /* - * ...and wait until the device is ready. - */ - do { - wait_ms(100); - res = adi_sense_GetDeviceReadyState(hDevice, &bDeviceReady); - if (res != ADI_SENSE_SUCCESS) - { - ADI_SENSE_LOG_ERROR("Failed to get device ready-state"); - return res; - } - } while (! bDeviceReady); - ADI_SENSE_LOG_INFO("ADI Sense device ready"); + + // Otherwise, boot main program + + // Boot the adisense1000 to a known state + ret = Adisense1000_Boot(); + bool adiSense1000Active = !ret; + +#ifdef BL652 + //boot BLE device + ret = Bl652_Boot(); + if (ret == 0) { + ADI_SENSE_LOG_INFO("BLE Boot success.."); + } else { + ADI_SENSE_LOG_INFO("BLE Boot unsuccessful.."); + } +#endif - /* - * Write configuration settings to the device registers. - * Settings are not applied until adi_sense_ApplyConfigUpdates() is called. - */ - ADI_SENSE_LOG_INFO("Setting device configuration"); - res = adi_sense_SetConfig(hDevice, pSelectedConfig); - if (res != ADI_SENSE_SUCCESS) - { - ADI_SENSE_LOG_ERROR("Failed to set device configuration"); - return res; + // Set if ble is present or not + // If not, the PC interface can still be initialised + bleActive = !ret; + + // Check adisense has booted correctly + if( adiSense1000Active ) { + Pc_ResetSuccess( bBootLoader ); + ADI_SENSE_LOG_INFO("ADIsense boot successful..."); } - res = adi_sense_ApplyConfigUpdates(hDevice); - if (res != ADI_SENSE_SUCCESS) - { - ADI_SENSE_LOG_ERROR("Failed to apply device configuration"); - return res; + else { + // Cannot continue without adi_sense module + exit( 1 ); } - - /* - * Kick off the measurement cycle here - */ - ADI_SENSE_LOG_INFO("Configuration completed, starting measurement cycles"); - utils_runMeasurement(hDevice, eMeasurementMode); - - /* - * Clean up and exit - */ - res = adi_sense_Close(hDevice); - if (res != ADI_SENSE_SUCCESS) - { - ADI_SENSE_LOG_ERROR("Failed to close device instance"); - return res; + + // Set led on to indicate boot has completed + + ADI_SENSE_LOG_INFO("Set LED Idle..."); + Led_Idle(); + + // Begin main program + ADI_SENSE_LOG_INFO("Begin main program..."); + while(1) { + // Read in a command and handle appropriately + ret = MyProSwift_Command( bleActive ); + if( ret != 0 ) { + // Errors should be handled at lower levels, using reponse codes + // to the appropriate active interface + // exit(1); + } } - - return 0; }
diff -r 76fed7dd9235 -r 25a2bf666957 src/adisense1000_boot.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/adisense1000_boot.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,108 @@ +/* + * ADISense1000 - Reset Device functions + * + * Author: Jake Greaves + */ + +#include "inc/adisense1000_boot.h" + +ADI_SENSE_DEVICE_HANDLE hDevice; + +//connection information for initialising ADISense1000 +extern ADI_SENSE_CONNECTION connectionInfo; + +extern ADI_SENSE_CONFIG adi_sense_config; +extern ADI_SENSE_CONFIG adi_sense_config_eeprom; +//extern ADI_SENSE_DSP_LUT_RAW adi_sense_dsp_lut; + +/*************************************************************** +* Function Name: ADISense1000_Boot +* Description : open the ADISense1000 and reset it, + loading default config +***************************************************************/ +uint8_t Adisense1000_Boot(void) +{ + bool_t bDeviceReady; + ADI_SENSE_PRODUCT_ID productId; + + //Open an ADI Sense device instance. + if(adi_sense_Open(0, &connectionInfo, &hDevice) != ADI_SENSE_SUCCESS) + return 1; + + //Reset the given ADI Sense device, and wait until the device is ready + if(adi_sense_Reset(hDevice) != ADI_SENSE_SUCCESS) + return 1; + + + //Wait until the device is ready. + do { + wait_ms(100); + if(adi_sense_GetDeviceReadyState(hDevice, &bDeviceReady) != ADI_SENSE_SUCCESS) + return 1; + } while (! bDeviceReady); + + /* + * Read the product ID from the device registers. + */ + if(adi_sense_GetProductID(hDevice, &productId) != ADI_SENSE_SUCCESS) + return 1; + + //apply config + if(adi_sense_SetConfig(hDevice, &adi_sense_config) != ADI_SENSE_SUCCESS) + return 1; + //if(adi_sense_SetDspData(hDevice, &adi_sense_dsp_lut) == ADI_SENSE_SUCCESS); + if(adi_sense_ApplyConfigUpdates(hDevice) != ADI_SENSE_SUCCESS) + return 1; + +// Prototype for saving and reading from EEPROM +// Still needs testing +#ifdef VIRT_EEPROM + //recall config from emulated eeprom + //Unlock the Flash Program Erase controller + HAL_FLASH_Unlock(); + + //EEPROM Init + //cleans up eeprom area and handles pages + if(EE_Init() == EE_OK) { + + //flag to set if eeprom is currently valid + uint16_t eepromConfigValid; + + //if read of flag is successful + if((EE_ReadVariable(VirtAddVarTab[0], &eepromConfigValid)) == HAL_OK) { + + //if eeprom config is valid, read into working config struct + //0xAF is generic flag + if(eepromConfigValid == 0xAF) { + //read eeprom to adisenseconfig + uint16_t *p = (uint16_t*)&adi_sense_config_eeprom; + int i = 0; + + //read back all bytes, on error, read is broken + for(i = 0; i < sizeof(adi_sense_config_eeprom)/sizeof(uint16_t); i++, p++) { + //read struct back, break on error + if((EE_ReadVariable(VirtAddVarTab[1] + i, p)) != HAL_OK) + break; + } + + //if no error occurred and the config struct is complete + if(i == sizeof(adi_sense_config_eeprom)/sizeof(uint16_t)) { + //apply config + if(adi_sense_SetConfig(hDevice, &adi_sense_config_eeprom) != ADI_SENSE_SUCCESS) + return 1; + //if(adi_sense_SetDspData(hDevice, &adi_sense_dsp_lut) == ADI_SENSE_SUCCESS); + if(adi_sense_ApplyConfigUpdates(hDevice) != ADI_SENSE_SUCCESS) + return 1; + } + } + } + } + + //Lock the Flash Program Erase controller + HAL_FLASH_Lock(); + +#endif + + return 0; +} +
diff -r 76fed7dd9235 -r 25a2bf666957 src/ble_interface/bl652.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ble_interface/bl652.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,234 @@ +/* + * bl652.cpp - BLE driver for serial port service + * + * Author: Jake Greaves + */ + +#include "bl652.h" + +#include "mbed.h" +#include "myproswift_periph.h" +#include "communications.h" + + +//used by callback +static char *cbSerialBuffer; +volatile bool *bBleMessageReceived; +static uint32_t cbCount = 0; +static uint32_t cbMaxSize; + + +//reset pin of BLE module +extern DigitalOut ble_rst; +//flow control +extern DigitalOut ble_Cts; +extern DigitalIn ble_Rts; +//Serial for ble +extern Serial bleSerialDevice; +//SPI +extern SPI bleSpiDevice; +extern DigitalOut cs_Ble; + +extern DigitalOut bleMode0; +extern DigitalOut bleMode1; + + +//ble requires a minimum delay between packets +Timer timer; + + +/*************************************************************** +* Function Name: Bl652_AtTransaction +* Description : Perform an AT command transaction +***************************************************************/ +uint32_t Bl652_AtTransaction( char *command, char *resp ) +{ + //write command to device + Bl652_Write( command, strlen(command) ); + + //read response + int8_t i = -1; + do { + i++; + Bl652_Read( &resp[i], 1 ); + } while(resp[i] != AT_COMMAND_DELIMITER); + + if( !strncmp(resp, AT_COMMAND_ERROR, strlen(AT_COMMAND_ERROR)) ) { + return 1; + } + + else { + return 0; + } +} + +/*************************************************************** +* Function Name: Bl652_Boot +* Description : Main boot function +***************************************************************/ +uint32_t Bl652_Boot( void ) +{ + + //setup device as vSP mode + bleMode0 = 1; + bleMode1 = 1; + + //reset device + ble_rst = 0; + wait_ms( RESET_LENGTH ); + ble_rst = 1; + + //start sending timer for minimum packet delay + timer.start(); + + return 0; +} + +/*************************************************************** +* Function Name: Bl652_Callback +* Description : callback for uart communications +***************************************************************/ +static void Bl652_Callback( void ) +{ + while( bleSerialDevice.readable() ) { + //read next character + char c = bleSerialDevice.getc(); + + //store char in buffer + if( cbSerialBuffer != NULL ) { + cbSerialBuffer[cbCount] = c; + } + + //increment count + cbCount++; + + //check if buffer is filled + if( cbCount >= cbMaxSize ) { + + //set flag that data has been received + *bBleMessageReceived = 1; + break; + } + //else continue sending + else { + //indicate ble is clear to send + ble_Cts = 0; + } + } +} + +/*************************************************************** +* Function Name: Bl652_WaitUntilAvailable +* Description : wait until ble is awake +***************************************************************/ +static uint32_t Bl652_WaitUntilAvailable( void ) +{ + //wait until BLE is available + while( ble_Rts ); + + return 0; +} + +/*************************************************************** +* Function Name: Bl652_Write +* Description : write string to ble over uart +***************************************************************/ +uint32_t Bl652_Write( char *txBuffer, uint32_t byteCount ) +{ + uint8_t res = 0; + char padding[1] = {0x00}; + + //check packet is not too large + if( byteCount > BLE_PACKET_SIZE ) { + return 1; + } + + //wait the time limit for packets to be sent + while( timer.read_ms() < BLE_TX_PACKET_DELAY ); + timer.stop(); + + for( uint32_t i = 0; i < byteCount; i++ ) { + res = Bl652_WaitUntilAvailable(); + res = Uart_Write( bleSerialDevice, txBuffer + i, 1 ); + } + + //padding to 20 bytes + for( uint32_t i = 0; i < BLE_PACKET_SIZE - byteCount; i++ ) { + res = Bl652_WaitUntilAvailable(); + res = Uart_Write( bleSerialDevice, padding, 1 ); + } + + timer.reset(); + timer.start(); + + return res; +} + +/*************************************************************** +* Function Name: ble_read +* Description : blocking read over uart +***************************************************************/ +uint32_t Bl652_Read( char *rxBuffer, uint32_t byteCount ) +{ + ble_Cts = 0; + + for(uint32_t i = 0; i < byteCount; i++) { + rxBuffer[i] = bleSerialDevice.getc(); + } + + ble_Cts = 1; + + return 0; +} + +/*************************************************************** +* Function Name: ble_setup_read_cb +* Description : register callback and flag for receiving ble data +***************************************************************/ +uint32_t Bl652_SetupReadCb( void *rxBuffer, uint32_t maxSize, volatile bool *bMessageReadFlag ) +{ + uint32_t ret = 0; + + //setup global vars for handler funtions + cbCount = 0; + cbMaxSize = maxSize; + + //assign serial callback buffer + if( rxBuffer != NULL ) { + cbSerialBuffer = ( char* )rxBuffer; + } + else { + return 1; + } + + //register global flag + bBleMessageReceived = bMessageReadFlag; + + //assign callback buffer + cbSerialBuffer = ( char* )rxBuffer; + + //call UART function + ret = Uart_ReadCb( bleSerialDevice, Bl652_Callback ); + + //wait until BLE is awake + //ble_wait_until_available(); + + //indicate ble is clear to send + ble_Cts = 0; + + return ret; +} + +/*************************************************************** +* Function Name: ble_clear_cb +* Description : clear cb and top receiing ble data +***************************************************************/ +uint32_t Bl652_ClearCb( void ) +{ + //indicate ble to stop sending + ble_Cts = 1; + + //clear callback to uart handle + return Uart_ClearCb( bleSerialDevice ); +} +
diff -r 76fed7dd9235 -r 25a2bf666957 src/ble_interface/ble_interface.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/ble_interface/ble_interface.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,683 @@ +/* + * ble_interface.cpp - main interface to android application + * + * Author: Jake Greaves + */ +#include "ble_interface.h" + +//adisense1000 config as defined elsewhere +extern ADI_SENSE_CONFIG adi_sense_config; +extern ADI_SENSE_DEVICE_HANDLE hDevice; + +//ble uart device +extern Serial bleSerialDevice; +extern DigitalOut ble_Cts; + +//a work around for multiple requests received from app +char lastFieldNameID = 0xFF; + + +static char *fieldNames[ADI_SENSE_1000_MAX_CHANNELS] = { + "Cjc0", + "Cjc1", + "Sensor0", + "Sensor1", + "Sensor2", + "Sensor3", + "Voltage0", + "Current0", + "I2c0", + "I2c1", + "Spi0", + "Spi1", + "Spi2" +}; + +//send error response +static uint32_t Ble_HandleError( ErrorType error ); + + +//command ID to be handled +enum { + REQ_REG_PACKET_COUNT = 0x30, //'0' + REQ_REG_PACKETS = 0x31, //'1' + REQ_FIELD_NAMES = 0x32, //'2' + START_STREAM = 0x33, //'3' + STOP_STREAM = 0x34, //'4' +} MSG_TYPE; + +/* +enum { + REQ_REG_PACKET_COUNT = 0x10, + REQ_REG_PACKETS = 0x11, + REQ_FIELD_NAMES = 0x12, + START_STREAM = 0x20, + STOP_STREAM = 0x21, +} MSG_TYPE; +*/ +//possible measurement types +enum { + TEMPERATURE = 0x00, + PRESSURE, + HUMIDITY, + ACCELEROMETER, + UNDEFINED +} MEASUREMENT_TYPES; + +//data type. Might change to bytes per measurement in newer API versions +enum { + FLOAT_32 = 0x01 +} DATA_TYPE; + +//structs to store an active channels details for the BLE App +typedef struct { + uint8_t measurementId; + uint8_t measurementTypeId; + char *measurementName; + uint8_t numberOfFields; + uint8_t associatedChannel; + uint8_t dataType; +} MEASUREMENT_INFO; + + +//store all active channel information +static MEASUREMENT_INFO *measurementInfo = NULL; + +//counts amount of channels active +static uint8_t activeChannelCount = 0; + +//flag for streaming data +volatile static bool bStreamFlag = 0; + + +/*************************************************************** +* Function Name: Ble_HandleReqRegPacketCount +* Description : handle the REQ_REG_PACKET_COUNT command +****************************************************************/ +static uint32_t Ble_HandleReqRegPacketCount( void ) +{ + //buffer for sending BLE data + char bleTxBuffer[BLE_PACKET_SIZE] = {0x00}; + //stores position in bleTxBuffer + uint8_t buffPos = 0; + + //clear active channel count + activeChannelCount = 0; + + //clear global array for aactive channels, as we are recalculating this now + free( measurementInfo ); + measurementInfo = NULL; + + //check all channels + for( uint32_t i = 0; i < ADI_SENSE_1000_MAX_CHANNELS; i++ ) { + + //struct to contain data on measurement + MEASUREMENT_INFO channel_info; + + //current channel + ADI_SENSE_1000_CHANNEL_CONFIG channel = adi_sense_config.adisense1000.channels[i]; + + //include as independant channel if enabled and not a compensation channel + //for now, compensation cahnnels get their own graph if publishing is enabled + if( channel.enableChannel && !channel.disablePublishing ) { + + //add a measurement + channel_info.measurementId = activeChannelCount; + activeChannelCount++; + + //set name and units + //check channel type based on ranges and assign name and type + if( channel.adcChannelConfig.sensor <= ADI_SENSE_1000_ADC_SENSOR_THERMISTOR_4_ADV_L2 ) { + channel_info.measurementTypeId = TEMPERATURE; + channel_info.measurementName = "Temperature"; + } + + else if( channel.adcChannelConfig.sensor >= ADI_SENSE_1000_I2C_SENSOR_HUMIDITY_HONEYWELL_HUMIDICON && channel.adcChannelConfig.sensor <= ADI_SENSE_1000_I2C_SENSOR_HUMIDITY_SENSIRION_SHT3X ) { + channel_info.measurementTypeId = HUMIDITY; + channel_info.measurementName = "Humidity"; + } + + else if( channel.adcChannelConfig.sensor >= ADI_SENSE_1000_ADC_SENSOR_VOLTAGE || channel.adcChannelConfig.sensor == ADI_SENSE_1000_SPI_SENSOR_PRESSURE_HONEYWELL_TRUSTABILITY ) { + channel_info.measurementTypeId = PRESSURE; + channel_info.measurementName = "Pressure"; + } + + else { + channel_info.measurementTypeId = UNDEFINED; + channel_info.measurementName = "Undefined"; + } + + //default to 1 field + channel_info.numberOfFields = 1; + + //add current channel + channel_info.associatedChannel = i; + + //all values are floats for now + channel_info.dataType = FLOAT_32; + + //add to overall array + measurementInfo = ( MEASUREMENT_INFO * )realloc( measurementInfo, activeChannelCount * sizeof( MEASUREMENT_INFO ) ); + measurementInfo[activeChannelCount - 1] = channel_info; + } + } + + if( activeChannelCount == 0 ) { + return Ble_HandleError( ERROR_UNDEFINED ); + } + + //command ID + bleTxBuffer[buffPos] = REQ_REG_PACKET_COUNT; + buffPos++; + + //amount of data samples + bleTxBuffer[buffPos] = activeChannelCount; + buffPos++; + + //respond to app + Bl652_Write( bleTxBuffer, buffPos ); + + return 0; +} + +/*************************************************************** +* Function Name: Ble_HandleReqRegPackets +* Description : handle the REQ_REG_PACKETS command +****************************************************************/ +static uint32_t Ble_HandleReqRegPackets( void ) +{ + //buffer for sending BLE data + char bleTxBuffer[BLE_PACKET_SIZE] = {0x00}; + //stores position in bleTxBuffer + uint8_t buffPos = 0; + + //ReqRegPacketCount has not been called, or had an error + if( activeChannelCount == 0 ) { + return Ble_HandleError( ERROR_UNDEFINED ); + } + + //repeat for all measurements + for( uint32_t i = 0; i < activeChannelCount; i++ ) { + + //reset buffPos + buffPos = 0; + + //add command ID + bleTxBuffer[buffPos] = REQ_REG_PACKETS; + buffPos++; + + //add regPackets ID + bleTxBuffer[buffPos] = measurementInfo[i].measurementId; + buffPos++; + + //add type of measurement + bleTxBuffer[buffPos] = measurementInfo[i].measurementTypeId; + buffPos++; + + //adding measurements name to packet + char *measurementName = ( char* )measurementInfo[i].measurementName; + for( uint32_t j = 0; j < MEASUREMENT_NAME_MAX_LEN; j++ ) { + //populate measurement name for app + if( j < strlen( measurementName ) ) { + bleTxBuffer[buffPos] = measurementName[j]; + } + //pad unused chars with 0x00 + else { + bleTxBuffer[buffPos] = 0x00; + } + buffPos++; + } + + //add number of plots on graph. ( 1 for now ) + bleTxBuffer[buffPos] = measurementInfo[i].numberOfFields; + buffPos++; + //add data format ( always float32_t for now ) + bleTxBuffer[buffPos] = measurementInfo[i].dataType; + buffPos++; + + //transmit packet + Bl652_Write( bleTxBuffer, buffPos ); + } + + return 0; +} + +/*************************************************************** +* Function Name: Ble_HandleReqFieldNames +* Description : handle the REQ_FIELD_NAMES command +****************************************************************/ +static uint32_t Ble_HandleReqFieldNames( char *bleRxBuffer ) +{ + //buffer for sending BLE data + char bleTxBuffer[BLE_PACKET_SIZE] = {0x00}; + //stores position in bleTxBuffer + uint8_t buffPos = 0; + + //flag for reading from BLE + volatile bool bBleMessageReceived = 0; + uint8_t numberOfFields; + + //read a further byte + Bl652_Read( &bleRxBuffer[1], 1 ); + + //if ReqRegPacketCount has not been called, or had an error + if( activeChannelCount == 0 ) { + return Ble_HandleError( ERROR_UNDEFINED ); + } + + //dirtiest of hacks. Issue here is app seems to send same packet multiple times when sent once. + //Unsure why this is for now, ignore duplicates + if( bleRxBuffer[1] == lastFieldNameID ) { + return 0; + } + lastFieldNameID = bleRxBuffer[1]; + + //find units for channel + char unitDescriptor[UNIT_NAME_MAX_LEN]; + switch( measurementInfo[bleRxBuffer[1]].measurementTypeId ) { + + case TEMPERATURE: + strcpy( unitDescriptor, "�C" ); + break; + + case PRESSURE: + strcpy( unitDescriptor, "PSI" ); + break; + + case HUMIDITY: + strcpy( unitDescriptor, "%" ); + break; + + case ACCELEROMETER: + strcpy( unitDescriptor, "XYZ" ); + break; + + default: + strcpy( unitDescriptor, "NA" ); + break; + } + + //add command ID to BLE packet + bleTxBuffer[buffPos] = REQ_FIELD_NAMES; + buffPos++; + + //add unit name to ble packet, padding with 0x00 + for( uint32_t i = 0; i < UNIT_NAME_MAX_LEN; i++ ) { + //populate measurement name for app + if( i < strlen( unitDescriptor ) ) { + bleTxBuffer[buffPos] = unitDescriptor[i]; + } + //pad with 0x00 + else { + bleTxBuffer[buffPos] = 0x00; + } + buffPos++; + } + + //name of sensor fields + numberOfFields = measurementInfo[bleRxBuffer[1]].numberOfFields; + + //ReqRegPacketCount has not been called, or had an error + if( numberOfFields == 0 ) { + return Ble_HandleError( ERROR_UNDEFINED ); + } + + //calculate the available space for names of each plot. + //This is support for multiple channels associated together. + uint8_t eachFieldNameMaxSize = FIELD_NAMES_MAX_SIZE / numberOfFields; + + //add field names to packet + for( uint32_t i = 0; i < numberOfFields; i++ ) { + char *fieldName = fieldNames[measurementInfo[bleRxBuffer[1]].associatedChannel]; + + for( uint32_t j = 0; j < eachFieldNameMaxSize; j++ ) { + //populate measurement name for app + if( j < strlen( fieldName ) ) { + bleTxBuffer[buffPos] = fieldName[j]; + } + //pad with 0x00 + else { + bleTxBuffer[buffPos] = 0x00; + } + buffPos++; + } + } + + //return measurement count, field name + Bl652_Write( bleTxBuffer, buffPos ); + + return 0; +} + +/*************************************************************** +* Function Name: ble_data_ready_callback +* Description : callback for when data ready state changes +****************************************************************/ +static void ble_data_ready_callback( ADI_SENSE_GPIO_PIN ePinId, void *pArg ) +{ + volatile bool_t *pbDataready = ( volatile bool_t * ) pArg; + *pbDataready = true; +} + +/*************************************************************** +* Function Name: Ble_HandleStartStream +* Description : handle the START_STREAM command +****************************************************************/ +static uint32_t Ble_HandleStartStream( void ) +{ + //buffer for sending BLE data + char bleTxBuffer[BLE_PACKET_SIZE] = {0x00}; + //stores poition in bleTxBuffer + uint8_t buffPos = 0; + + //part of the adisense1000 sampling + ADI_SENSE_DATA_SAMPLE *pSampleBuffer; + ADI_SENSE_1000_OPERATING_MODE eOperatingMode; + ADI_SENSE_1000_DATAREADY_MODE eDataPublishMode; + ADI_SENSE_MEASUREMENT_MODE eMeasurementMode = ADI_SENSE_MEASUREMENT_MODE_NORMAL; + uint32_t nSamplesPerDataready, nSamplesPerCycle; + volatile bool_t bDataReady = false; + + //if ReqRegPacketCount has not been called, or had an error + if( activeChannelCount == 0 ) { + return Ble_HandleError( ERROR_UNDEFINED ); + } + + //upload new configuration and apply. + //This has been used to calculate all previous steps, so ensure that this is the active configuration + adi_sense_SetConfig( hDevice, &adi_sense_config ); + adi_sense_ApplyConfigUpdates( hDevice ); + + //get information about the adisense data ready mode + adi_sense_1000_GetDataReadyModeInfo(hDevice, + eMeasurementMode, + &eOperatingMode, + &eDataPublishMode, + &nSamplesPerDataready, + &nSamplesPerCycle ); + //allocate a buffer to store the samples retreived on each DATAREADY pulse + pSampleBuffer = new ADI_SENSE_DATA_SAMPLE[nSamplesPerDataready]; + if( pSampleBuffer == NULL ) { + return 1; + } + + //interrupt-triggered DATAREADY notifications in this mode + adi_sense_RegisterGpioCallback( hDevice, ADI_SENSE_GPIO_PIN_DATAREADY, + ble_data_ready_callback, + ( void * )&bDataReady ); + + //allow ble to send data for stream cancel command + ble_Cts = 0; + + //handle the single cycle device mode + if ( eOperatingMode == ADI_SENSE_1000_OPERATING_MODE_SINGLECYCLE ) { + + //loop single cycle until stream stop command is received + do { + //begin measurement cycles + adi_sense_StartMeasurement( hDevice, eMeasurementMode ); + + //read in each measurement cycle + for ( uint32_t i = 0; i < nSamplesPerCycle / nSamplesPerDataready; i++ ) { + uint32_t nReturned; + + //Interrupt method: wait for DATAREADY interrupt callback + while ( !bDataReady ); + + //reset bDataReady flag to detect the next callback + bDataReady = false; + + //read data into structure + adi_sense_GetData( hDevice, eMeasurementMode, pSampleBuffer, nSamplesPerDataready, &nReturned ); + + //for all returned samples + for( uint32_t i = 0; i < nReturned; i++ ) { + + //to store adisense1000 channel index + //and the channel number according to the BLE device + uint8_t channelIndex, activeChannelNumber; + + //obtain sample data in byte array form + uint8_t *sample = ( uint8_t* )&pSampleBuffer[i].processedValue; + + //match sample ID to active channel + for( uint32_t j = 0; j < activeChannelCount; j++ ) { + + //get the ID of the current active channel + channelIndex = measurementInfo[j].associatedChannel; + + //if the sample matches the current active channel + if( pSampleBuffer[i].channelId == channelIndex ) { + activeChannelNumber = j; + break; + } + } + + //clear buffPos + buffPos = 0; + + //tag samples with command value + bleTxBuffer[buffPos] = START_STREAM; + buffPos++; + + //Tag with ID of measurement + bleTxBuffer[buffPos] = measurementInfo[activeChannelNumber].measurementId; + buffPos++; + + //transmute sample data into bytes for transmission + for( uint32_t j = 0; j < sizeof( measurementInfo[activeChannelNumber].dataType ); j++ ) { + + //store bytes to buffer + bleTxBuffer[buffPos] = sample[j]; + buffPos++; + } + + //stream measurement + Bl652_Write( bleTxBuffer, buffPos ); + } + } + + if( bleSerialDevice.readable() ) { + ble_Cts = 1; + if( bleSerialDevice.getc() == STOP_STREAM ) { + //stop stream measurement + bleTxBuffer[0] = STOP_STREAM; + Bl652_Write( bleTxBuffer, 1 ); + break; + } + else { + return Ble_HandleError( ERROR_UNDEFINED ); + } + } + } while ( 1 ); + } + + //handle continuous measurement mode + else { + + //begin measurement cycles + adi_sense_StartMeasurement( hDevice, eMeasurementMode ); + + do { + uint32_t nReturned; + + //Interrupt method: wait for DATAREADY interrupt callback + while ( !bDataReady ); + + //reset bDataReady flag to detect the next callback + bDataReady = false; + + //read data into structure + adi_sense_GetData( hDevice, eMeasurementMode, pSampleBuffer, nSamplesPerDataready, &nReturned ); + + //for all returned samples //TODO: Might need modified. Test with App + for( uint32_t i = 0; i < nReturned; i++ ) { + + //to store adisense1000 channel index + //and the channel number according to the BLE device + uint8_t channelIndex, activeChannelNumber; + + //obtain sample data in byte array form + uint8_t *sample = ( uint8_t* )&pSampleBuffer[i].processedValue; + + //match sample ID to active channel + for( uint32_t j = 0; j < activeChannelCount; j++ ) { + + //get the ID of the current active channel + channelIndex = measurementInfo[j].associatedChannel; + + //if the sample matches the current active channel + if( pSampleBuffer[i].channelId == channelIndex ) { + activeChannelNumber = j; + break; + } + } + + //clear buffPos + buffPos = 0; + + //tag samples with command value + bleTxBuffer[buffPos] = START_STREAM; + buffPos++; + + //Tag with ID of measurement + bleTxBuffer[buffPos] = measurementInfo[activeChannelNumber].measurementId; + buffPos++; + + //transmute sample data into bytes for transmission + for( uint32_t j = 0; j < sizeof( measurementInfo[activeChannelNumber].dataType ); j++ ) { + + //store bytes to buffer + bleTxBuffer[buffPos] = sample[j]; + buffPos++; + } + + //stream measurement + Bl652_Write( bleTxBuffer, buffPos ); + } + + if( bleSerialDevice.readable() ) { + + //signal ble to stop sending bytes + ble_Cts = 1; + + //read byte buffer and determine if + //the STOP_STREAM byte has been received + if( bleSerialDevice.getc() == STOP_STREAM ) { + //stop stream measurement + bleTxBuffer[0] = STOP_STREAM; + Bl652_Write( bleTxBuffer, 1 ); + break; + } + else { + return Ble_HandleError( ERROR_UNDEFINED ); + } + } + } while ( 1 ); + + //stop measurement + adi_sense_StopMeasurement( hDevice ); + } + + //free buffer + delete [] pSampleBuffer; + + return 0; +} + +/*************************************************************** +* Function Name: Ble_HandleStopStream +* Description : handle the STOP_STREAM command +****************************************************************/ +static uint32_t Ble_HandleStopStream( void ) +{ + //buffer for sending BLE data + char bleTxBuffer[BLE_PACKET_SIZE] = {0x00}; + //stores poition in bleTxBuffer + uint8_t buffPos = 0; + + //stop stream measurement. Already stopped but let app know + bleTxBuffer[buffPos] = STOP_STREAM; + buffPos++; + + //transmit buffer + Bl652_Write( bleTxBuffer, 1 ); + + return 0; +} + +/*************************************************************** +* Function Name: handle_error +* Description : handle an error +****************************************************************/ +static uint32_t Ble_HandleError( ErrorType error ) +{ + char status[1] = {error}; + + //send response error + Bl652_Write( status, sizeof( status ) ); + + return 1; +} + +/*************************************************************** +* Function Name: ble_parse_command +* Description : parse the ble command +****************************************************************/ +uint32_t Ble_ParseCommand( char *bleRxBuffer ) +{ + uint32_t ret = 0; + //here we read the next byte and use a case to decide the handler function + //within the handler, the remaining bytes may be read and acted on appropriately with a response + + //confirm type of command ( 1st complete byte ) + switch( bleRxBuffer[0] ) { + + case REQ_REG_PACKET_COUNT: {//app is requesting the amount of reg packets required + //call handler function, passing buffer for further use + ret = Ble_HandleReqRegPacketCount(); + char bleSend1[] = "PacketCount\r\n"; + Bl652_Write(bleSend1 , 15); + break; + } + case REQ_REG_PACKETS: {//app is requesting for all reg packets + //call handler function, passing buffer for further use + ret = Ble_HandleReqRegPackets(); + char bleSend2[] = "ReqRegister\r\n"; + Bl652_Write(bleSend2 , 15); + break; + } + case REQ_FIELD_NAMES: {//app is requesting field names + //call handler function, passing buffer for further use + ret = Ble_HandleReqFieldNames( bleRxBuffer ); + char bleSend3[] = "FieldNames\r\n"; + Bl652_Write(bleSend3 , 15); + break; + } + case START_STREAM: {//app is requesting the start of the data stream + //call handler function + ret = Ble_HandleStartStream(); + char bleSend4[] = "StartStream\r\n"; + Bl652_Write(bleSend4 , 15); + break; + } + case STOP_STREAM: {//app is requesting to stop the data stream + //call handler function + ret = Ble_HandleStopStream(); + break; + } + //Template + //case COMMAND: return parse_COMMAND(); + //parse_COMMAND handles the action required + //COMMAND must be defined within the header file + + //handle an unrecognised command/error + default: {//command not recognised + ret = Ble_HandleError( ERROR_UNDEFINED ); + break; + } + } + + return ret; +} +
diff -r 76fed7dd9235 -r 25a2bf666957 src/bootloader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/bootloader.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,46 @@ +/* + ****************************************************************************** + * file: bootloader.c + *----------------------------------------------------------------------------- + */ + +#include "bootloader.h" +#include "rcc_backup_registers.h" + + +void (*SysMemBootJump)(void); + + +// Jump through software to the system bootloader +// This should only be called after a reset to ensure correct operation +void Bootloader_Init( void ) { + + // Base bootloader address, found within software manual + volatile uint32_t bootLoaderAddr = 0x1FFF0000; + + // Clear backup register flag + Rcc_WriteBackupReg(BOOTLOADER_FLAG_BACKUP_REG, 0); + + // Disable RCC clock + HAL_RCC_DeInit(); + + //disable systick timer and interrupts + SysTick -> CTRL = 0; + SysTick -> LOAD = 0; + SysTick -> VAL = 0; + + //disable all configurable interrupts + __disable_irq(); + + //remap sys mem to 0x0000 0000 in address space. Different for each device + __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); + + //map jump function + SysMemBootJump = (void (*)(void)) (*((uint32_t *)(bootLoaderAddr + 0x04))); + + //set main stack pointer + __set_MSP(*(uint32_t *)bootLoaderAddr); + + //jump + SysMemBootJump(); +}
diff -r 76fed7dd9235 -r 25a2bf666957 src/communications.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/communications.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,64 @@ +/* + * communications.cpp - low level communications wrapper for mbed + * + * Author: Jake Greaves + */ + +#include "communications.h" + +//spi callback flags +static volatile int intType; +static volatile bool spiCallbackFlag; +static event_callback_t callbck; + + +/*************************************************************** +* Function Name: uart_Init +* Description : init for serialHandle +****************************************************************/ +int Uart_Init( Serial &serialHandle, uint32_t baudrate ) +{ + //set baudrate + serialHandle.baud( baudrate ); + + return 0; +} + +/*************************************************************** +* Function Name: uart_Write +* Description : write a string to a serial device +****************************************************************/ +int Uart_Write( Serial &serialHandle, const char* txBuffer, unsigned int length ) +{ + + for(unsigned int i = 0; i < length; i++) { + //print to serial device + serialHandle.putc( txBuffer[i] ); + } + + return 0; +} + +/*************************************************************** +* Function Name: uart_read_cb +* Description : Read from a serial device using a callback +****************************************************************/ +int Uart_ReadCb( Serial &serialHandle, void ( *callback )( void ) ) +{ + //attach callback + serialHandle.attach( callback ); + + return 0; +} + +/*************************************************************** +* Function Name: uart_clear_cb +* Description : clear callback +****************************************************************/ +int Uart_ClearCb( Serial &serialHandle ) +{ + //attach callback + serialHandle.attach( NULL ); + + return 0; +}
diff -r 76fed7dd9235 -r 25a2bf666957 src/eeprom_virtual/eeprom.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/eeprom_virtual/eeprom.c Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,769 @@ +/** + ****************************************************************************** + * @file EEPROM/EEPROM_Emulation/src/eeprom.c + * @author MCD Application Team + * @brief This file provides all the EEPROM emulation firmware functions. + ****************************************************************************** + * @attention + * + * <h2><center>© Copyright © 2017 STMicroelectronics International N.V. + * All rights reserved.</center></h2> + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted, provided that the following conditions are met: + * + * 1. Redistribution of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of STMicroelectronics nor the names of other + * contributors to this software may be used to endorse or promote products + * derived from this software without specific written permission. + * 4. This software, including modifications and/or derivative works of this + * software, must execute solely and exclusively on microcontroller or + * microprocessor devices manufactured by or for STMicroelectronics. + * 5. Redistribution and use of this software other than as permitted under + * this license is void and will automatically terminate your rights under + * this license. + * + * THIS SOFTWARE IS PROVIDED BY STMICROELECTRONICS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS, IMPLIED OR STATUTORY WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE AND NON-INFRINGEMENT OF THIRD PARTY INTELLECTUAL PROPERTY + * RIGHTS ARE DISCLAIMED TO THE FULLEST EXTENT PERMITTED BY LAW. IN NO EVENT + * SHALL STMICROELECTRONICS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************** + */ +/** @addtogroup EEPROM_Emulation + * @{ + */ + +/* Includes ------------------------------------------------------------------*/ +#include "eeprom_virtual/eeprom.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ + +/* Global variable used to store variable value in read sequence */ +uint16_t DataVar = 0; + +/* Virtual address defined by the user: 0xFFFF value is prohibited */ +extern uint16_t VirtAddVarTab[NB_OF_VAR]; + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +static HAL_StatusTypeDef EE_Format(void); +static uint16_t EE_FindValidPage(uint8_t Operation); +static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data); +static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data); +static uint16_t EE_VerifyPageFullyErased(uint32_t Address); + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Restore the pages to a known good state in case of page's status + * corruption after a power loss. + * @param None. + * @retval - Flash error code: on write Flash error + * - FLASH_COMPLETE: on success + */ +uint16_t EE_Init(void) +{ + uint16_t PageStatus0 = 6, PageStatus1 = 6; + uint16_t VarIdx = 0; + uint16_t EepromStatus = 0, ReadStatus = 0; + int16_t x = -1; + HAL_StatusTypeDef FlashStatus; + uint32_t SectorError = 0; + FLASH_EraseInitTypeDef pEraseInit; + + + /* Get Page0 status */ + PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS); + /* Get Page1 status */ + PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS); + + pEraseInit.TypeErase = TYPEERASE_SECTORS; + pEraseInit.Sector = PAGE0_ID; + pEraseInit.NbSectors = 1; + pEraseInit.VoltageRange = VOLTAGE_RANGE; + + /* Check for invalid header states and repair if necessary */ + switch (PageStatus0) + { + case ERASED: + if (PageStatus1 == VALID_PAGE) /* Page0 erased, Page1 valid */ + { + /* Erase Page0 */ + if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS)) + { + FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError); + /* If erase operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + } + else if (PageStatus1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */ + { + /* Erase Page0 */ + if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS)) + { + FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError); + /* If erase operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + /* Mark Page1 as valid */ + FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE1_BASE_ADDRESS, VALID_PAGE); + /* If program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + else /* First EEPROM access (Page0&1 are erased) or invalid state -> format EEPROM */ + { + /* Erase both Page0 and Page1 and set Page0 as valid page */ + FlashStatus = EE_Format(); + /* If erase/program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + break; + + case RECEIVE_DATA: + if (PageStatus1 == VALID_PAGE) /* Page0 receive, Page1 valid */ + { + /* Transfer data from Page1 to Page0 */ + for (VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++) + { + if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx]) + { + x = VarIdx; + } + if (VarIdx != x) + { + /* Read the last variables' updates */ + ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar); + /* In case variable corresponding to the virtual address was found */ + if (ReadStatus != 0x1) + { + /* Transfer the variable to the Page0 */ + EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar); + /* If program operation was failed, a Flash error code is returned */ + if (EepromStatus != HAL_OK) + { + return EepromStatus; + } + } + } + } + /* Mark Page0 as valid */ + FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE); + /* If program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + pEraseInit.Sector = PAGE1_ID; + pEraseInit.NbSectors = 1; + pEraseInit.VoltageRange = VOLTAGE_RANGE; + /* Erase Page1 */ + if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS)) + { + FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError); + /* If erase operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + } + else if (PageStatus1 == ERASED) /* Page0 receive, Page1 erased */ + { + pEraseInit.Sector = PAGE1_ID; + pEraseInit.NbSectors = 1; + pEraseInit.VoltageRange = VOLTAGE_RANGE; + /* Erase Page1 */ + if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS)) + { + FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError); + /* If erase operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + /* Mark Page0 as valid */ + FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE); + /* If program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + else /* Invalid state -> format eeprom */ + { + /* Erase both Page0 and Page1 and set Page0 as valid page */ + FlashStatus = EE_Format(); + /* If erase/program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + break; + + case VALID_PAGE: + if (PageStatus1 == VALID_PAGE) /* Invalid state -> format eeprom */ + { + /* Erase both Page0 and Page1 and set Page0 as valid page */ + FlashStatus = EE_Format(); + /* If erase/program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + else if (PageStatus1 == ERASED) /* Page0 valid, Page1 erased */ + { + pEraseInit.Sector = PAGE1_ID; + pEraseInit.NbSectors = 1; + pEraseInit.VoltageRange = VOLTAGE_RANGE; + /* Erase Page1 */ + if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS)) + { + FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError); + /* If erase operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + } + else /* Page0 valid, Page1 receive */ + { + /* Transfer data from Page0 to Page1 */ + for (VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++) + { + if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx]) + { + x = VarIdx; + } + if (VarIdx != x) + { + /* Read the last variables' updates */ + ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar); + /* In case variable corresponding to the virtual address was found */ + if (ReadStatus != 0x1) + { + /* Transfer the variable to the Page1 */ + EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar); + /* If program operation was failed, a Flash error code is returned */ + if (EepromStatus != HAL_OK) + { + return EepromStatus; + } + } + } + } + /* Mark Page1 as valid */ + FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE1_BASE_ADDRESS, VALID_PAGE); + /* If program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + pEraseInit.Sector = PAGE0_ID; + pEraseInit.NbSectors = 1; + pEraseInit.VoltageRange = VOLTAGE_RANGE; + /* Erase Page0 */ + if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS)) + { + FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError); + /* If erase operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + } + break; + + default: /* Any other state -> format eeprom */ + /* Erase both Page0 and Page1 and set Page0 as valid page */ + FlashStatus = EE_Format(); + /* If erase/program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + break; + } + + return HAL_OK; +} + +/** + * @brief Verify if specified page is fully erased. + * @param Address: page address + * This parameter can be one of the following values: + * @arg PAGE0_BASE_ADDRESS: Page0 base address + * @arg PAGE1_BASE_ADDRESS: Page1 base address + * @retval page fully erased status: + * - 0: if Page not erased + * - 1: if Page erased + */ +uint16_t EE_VerifyPageFullyErased(uint32_t Address) +{ + uint32_t ReadStatus = 1; + uint16_t AddressValue = 0x5555; + + //handle page 0 check + if(Address < PAGE0_END_ADDRESS) { + /* Check each active page address starting from end */ + while (Address <= PAGE0_END_ADDRESS) + { + /* Get the current location content to be compared with virtual address */ + AddressValue = (*(__IO uint16_t*)Address); + + /* Compare the read address with the virtual address */ + if (AddressValue != ERASED) + { + + /* In case variable value is read, reset ReadStatus flag */ + ReadStatus = 0; + + break; + } + /* Next address location */ + Address = Address + 4; + } + } + //handle page 0 check + else { + /* Check each active page address starting from end */ + while (Address <= PAGE1_END_ADDRESS) + { + /* Get the current location content to be compared with virtual address */ + AddressValue = (*(__IO uint16_t*)Address); + + /* Compare the read address with the virtual address */ + if (AddressValue != ERASED) + { + + /* In case variable value is read, reset ReadStatus flag */ + ReadStatus = 0; + + break; + } + /* Next address location */ + Address = Address + 4; + } + } + /* Return ReadStatus value: (0: Page not erased, 1: Sector erased) */ + return ReadStatus; +} + +/** + * @brief Returns the last stored variable data, if found, which correspond to + * the passed virtual address + * @param VirtAddress: Variable virtual address + * @param Data: Global variable contains the read variable value + * @retval Success or error status: + * - 0: if variable was found + * - 1: if the variable was not found + * - NO_VALID_PAGE: if no valid page was found. + */ +uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data) +{ + uint16_t ValidPage = PAGE0; + uint16_t AddressValue = 0x5555, ReadStatus = 1; + uint32_t Address = EEPROM_START_ADDRESS, PageStartAddress = EEPROM_START_ADDRESS; + + /* Get active Page for read operation */ + ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE); + + /* Check if there is no valid page */ + if (ValidPage == NO_VALID_PAGE) + { + return NO_VALID_PAGE; + } + + /* Get the valid Page start Address */ + PageStartAddress = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(ValidPage * PAGE_SIZE)); + + /* Get the valid Page end Address */ + Address = (uint32_t)((EEPROM_START_ADDRESS - 2) + (uint32_t)((1 + ValidPage) * PAGE_SIZE)); + + /* Check each active page address starting from end */ + while (Address > (PageStartAddress + 2)) + { + /* Get the current location content to be compared with virtual address */ + AddressValue = (*(__IO uint16_t*)Address); + + /* Compare the read address with the virtual address */ + if (AddressValue == VirtAddress) + { + /* Get content of Address-2 which is variable value */ + *Data = (*(__IO uint16_t*)(Address - 2)); + + /* In case variable value is read, reset ReadStatus flag */ + ReadStatus = 0; + + break; + } + else + { + /* Next address location */ + Address = Address - 4; + } + } + + /* Return ReadStatus value: (0: variable exist, 1: variable doesn't exist) */ + return ReadStatus; +} + +/** + * @brief Writes/upadtes variable data in EEPROM. + * @param VirtAddress: Variable virtual address + * @param Data: 16 bit data to be written + * @retval Success or error status: + * - FLASH_COMPLETE: on success + * - PAGE_FULL: if valid page is full + * - NO_VALID_PAGE: if no valid page was found + * - Flash error code: on write Flash error + */ +uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data) +{ + uint16_t Status = 0; + + /* Write the variable virtual address and value in the EEPROM */ + Status = EE_VerifyPageFullWriteVariable(VirtAddress, Data); + + /* In case the EEPROM active page is full */ + if (Status == PAGE_FULL) + { + /* Perform Page transfer */ + Status = EE_PageTransfer(VirtAddress, Data); + } + + /* Return last operation status */ + return Status; +} + +/** + * @brief Erases PAGE and PAGE1 and writes VALID_PAGE header to PAGE + * @param None + * @retval Status of the last operation (Flash write or erase) done during + * EEPROM formating + */ +static HAL_StatusTypeDef EE_Format(void) +{ + HAL_StatusTypeDef FlashStatus = HAL_OK; + uint32_t SectorError = 0; + FLASH_EraseInitTypeDef pEraseInit; + + pEraseInit.TypeErase = FLASH_TYPEERASE_SECTORS; + pEraseInit.Sector = PAGE0_ID; + pEraseInit.NbSectors = 1; + pEraseInit.VoltageRange = VOLTAGE_RANGE; + /* Erase Page0 */ + if(!EE_VerifyPageFullyErased(PAGE0_BASE_ADDRESS)) + { + FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError); + /* If erase operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + /* Set Page0 as valid page: Write VALID_PAGE at Page0 base address */ + FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, PAGE0_BASE_ADDRESS, VALID_PAGE); + /* If program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + + pEraseInit.Sector = PAGE1_ID; + /* Erase Page1 */ + if(!EE_VerifyPageFullyErased(PAGE1_BASE_ADDRESS)) + { + FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError); + /* If erase operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + } + + return HAL_OK; +} + +/** + * @brief Find valid Page for write or read operation + * @param Operation: operation to achieve on the valid page. + * This parameter can be one of the following values: + * @arg READ_FROM_VALID_PAGE: read operation from valid page + * @arg WRITE_IN_VALID_PAGE: write operation from valid page + * @retval Valid page number (PAGE or PAGE1) or NO_VALID_PAGE in case + * of no valid page was found + */ +static uint16_t EE_FindValidPage(uint8_t Operation) +{ + uint16_t PageStatus0 = 6, PageStatus1 = 6; + + /* Get Page0 actual status */ + PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS); + + /* Get Page1 actual status */ + PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS); + + /* Write or read operation */ + switch (Operation) + { + case WRITE_IN_VALID_PAGE: /* ---- Write operation ---- */ + if (PageStatus1 == VALID_PAGE) + { + /* Page0 receiving data */ + if (PageStatus0 == RECEIVE_DATA) + { + return PAGE0; /* Page0 valid */ + } + else + { + return PAGE1; /* Page1 valid */ + } + } + else if (PageStatus0 == VALID_PAGE) + { + /* Page1 receiving data */ + if (PageStatus1 == RECEIVE_DATA) + { + return PAGE1; /* Page1 valid */ + } + else + { + return PAGE0; /* Page0 valid */ + } + } + else + { + return NO_VALID_PAGE; /* No valid Page */ + } + + case READ_FROM_VALID_PAGE: /* ---- Read operation ---- */ + if (PageStatus0 == VALID_PAGE) + { + return PAGE0; /* Page0 valid */ + } + else if (PageStatus1 == VALID_PAGE) + { + return PAGE1; /* Page1 valid */ + } + else + { + return NO_VALID_PAGE ; /* No valid Page */ + } + + default: + return PAGE0; /* Page0 valid */ + } +} + +/** + * @brief Verify if active page is full and Writes variable in EEPROM. + * @param VirtAddress: 16 bit virtual address of the variable + * @param Data: 16 bit data to be written as variable value + * @retval Success or error status: + * - FLASH_COMPLETE: on success + * - PAGE_FULL: if valid page is full + * - NO_VALID_PAGE: if no valid page was found + * - Flash error code: on write Flash error + */ +static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data) +{ + HAL_StatusTypeDef FlashStatus = HAL_OK; + uint16_t ValidPage = PAGE0; + uint32_t Address = EEPROM_START_ADDRESS, PageEndAddress = EEPROM_START_ADDRESS+PAGE_SIZE; + + /* Get valid Page for write operation */ + ValidPage = EE_FindValidPage(WRITE_IN_VALID_PAGE); + + /* Check if there is no valid page */ + if (ValidPage == NO_VALID_PAGE) + { + return NO_VALID_PAGE; + } + + /* Get the valid Page start Address */ + Address = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(ValidPage * PAGE_SIZE)); + + /* Get the valid Page end Address */ + PageEndAddress = (uint32_t)((EEPROM_START_ADDRESS - 1) + (uint32_t)((ValidPage + 1) * PAGE_SIZE)); + + /* Check each active page address starting from begining */ + while (Address < PageEndAddress) + { + /* Verify if Address and Address+2 contents are 0xFFFFFFFF */ + if ((*(__IO uint32_t*)Address) == 0xFFFFFFFF) + { + /* Set variable data */ + FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, Address, Data); + /* If program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + /* Set variable virtual address */ + FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, Address + 2, VirtAddress); + /* Return program operation status */ + return FlashStatus; + } + else + { + /* Next address location */ + Address = Address + 4; + } + } + + /* Return PAGE_FULL in case the valid page is full */ + return PAGE_FULL; +} + +/** + * @brief Transfers last updated variables data from the full Page to + * an empty one. + * @param VirtAddress: 16 bit virtual address of the variable + * @param Data: 16 bit data to be written as variable value + * @retval Success or error status: + * - FLASH_COMPLETE: on success + * - PAGE_FULL: if valid page is full + * - NO_VALID_PAGE: if no valid page was found + * - Flash error code: on write Flash error + */ +static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data) +{ + HAL_StatusTypeDef FlashStatus = HAL_OK; + uint32_t NewPageAddress = EEPROM_START_ADDRESS; + uint16_t OldPageId=0; + uint16_t ValidPage = PAGE0, VarIdx = 0; + uint16_t EepromStatus = 0, ReadStatus = 0; + uint32_t SectorError = 0; + FLASH_EraseInitTypeDef pEraseInit; + + /* Get active Page for read operation */ + ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE); + + if (ValidPage == PAGE1) /* Page1 valid */ + { + /* New page address where variable will be moved to */ + NewPageAddress = PAGE0_BASE_ADDRESS; + + /* Old page ID where variable will be taken from */ + OldPageId = PAGE1_ID; + } + else if (ValidPage == PAGE0) /* Page0 valid */ + { + /* New page address where variable will be moved to */ + NewPageAddress = PAGE1_BASE_ADDRESS; + + /* Old page ID where variable will be taken from */ + OldPageId = PAGE0_ID; + } + else + { + return NO_VALID_PAGE; /* No valid Page */ + } + + /* Set the new Page status to RECEIVE_DATA status */ + FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, NewPageAddress, RECEIVE_DATA); + /* If program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + + /* Write the variable passed as parameter in the new active page */ + EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddress, Data); + /* If program operation was failed, a Flash error code is returned */ + if (EepromStatus != HAL_OK) + { + return EepromStatus; + } + + /* Transfer process: transfer variables from old to the new active page */ + for (VarIdx = 0; VarIdx < NB_OF_VAR; VarIdx++) + { + if (VirtAddVarTab[VarIdx] != VirtAddress) /* Check each variable except the one passed as parameter */ + { + /* Read the other last variable updates */ + ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar); + /* In case variable corresponding to the virtual address was found */ + if (ReadStatus != 0x1) + { + /* Transfer the variable to the new active page */ + EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar); + /* If program operation was failed, a Flash error code is returned */ + if (EepromStatus != HAL_OK) + { + return EepromStatus; + } + } + } + } + + pEraseInit.TypeErase = TYPEERASE_SECTORS; + pEraseInit.Sector = OldPageId; + pEraseInit.NbSectors = 1; + pEraseInit.VoltageRange = VOLTAGE_RANGE; + + /* Erase the old Page: Set old Page status to ERASED status */ + FlashStatus = HAL_FLASHEx_Erase(&pEraseInit, &SectorError); + /* If erase operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + + /* Set new Page status to VALID_PAGE status */ + FlashStatus = HAL_FLASH_Program(TYPEPROGRAM_HALFWORD, NewPageAddress, VALID_PAGE); + /* If program operation was failed, a Flash error code is returned */ + if (FlashStatus != HAL_OK) + { + return FlashStatus; + } + + /* Return last operation flash status */ + return FlashStatus; +} + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +/******************* (C) COPYRIGHT 2017 STMicroelectronics *****END OF FILE****/ +
diff -r 76fed7dd9235 -r 25a2bf666957 src/led.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/led.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,36 @@ +/* + * led.c - control functions for led indicator + * + * Author: Jake Greaves + */ + +#include "led.h" + +extern DigitalOut status_led; + +Ticker led_ticker; + +void Led_Blink( void ) { + + Led_On(!status_led); +} + +void Led_Boot( void ) { + + // Attach interrupt to blink led + led_ticker.attach(Led_Blink, LED_BLINK_PERIOD); +} + +void Led_Idle( void ) { + + // Set led to constantly on + led_ticker.detach(); + Led_On(true); +} + +void Led_On( bool_t state ) { + + // Set led state + status_led = state; +} +
diff -r 76fed7dd9235 -r 25a2bf666957 src/myproswift_eval.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myproswift_eval.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,81 @@ + +#include "myproswift_eval.h" + + +#include "mbed.h" +#include "pc_interface.h" +#include "ble_interface.h" +#include "myproswift_periph.h" + + +/*************************************************************** +* Function Name: MyProSwift_Command +* Description : read a command from either PC or BLE interfaces +* and handle accordingly +****************************************************************/ +int32_t MyProSwift_Command( bool bleActive ) +{ + uint32_t ret = 0; + //init buffers to 0x00 + char msgBuffer[MSG_BUFFER_MAX_SIZE] = {0x00}; + char bleBuffer[BLE_BUFFER_MAX_SIZE] = {0x00}; + + //setup callback routine for pc + volatile bool bPcMessageFlag = 0; + ret = Pc_SetupReadLineCb( msgBuffer, MSG_BUFFER_MAX_SIZE, &bPcMessageFlag ); + if( ret != 0 ) { + return ret; + } + + //setup callback routine for ble + volatile bool bBleMessageReceived = 0; + if( bleActive ) { + //read first byte + ret = Bl652_SetupReadCb( bleBuffer, 1, &bBleMessageReceived ); + if( ret != 0 ) { + ADI_SENSE_LOG_INFO("Ble Message Read Unsuccesful!"); + return ret; + } + } + + //poll ble and pc flag + while( !bBleMessageReceived /*&& !bPcMessageFlag */ ) + ;//add mbed abstracted sleep function + + //clear ble callbacks if needed + if( bleActive ) { + ret = Bl652_ClearCb(); + if( ret != 0 ) { + return ret; + } + } + + //clear pc callbacks always + ret = Pc_ClearReadLineCb(); + if( ret != 0 ) { + return ret; + } + + //handle message based on which interface it was received from + if( bBleMessageReceived ) { + //parse and handle command + ADI_SENSE_LOG_INFO("Ble Message Received!"); + ret = Ble_ParseCommand( bleBuffer ); + ADI_SENSE_LOG_INFO("Command Parsed!"); + if(ret != 0) { + //all ble side error handled within function as responses + return ret; + } + } + + else if(bPcMessageFlag) { + //parse and handle command + ret = Pc_ParseCommand( msgBuffer ); + if( ret != 0 ) { + //all pc side error handled within function as responses + return ret; + } + } + + return 0; +} \ No newline at end of file
diff -r 76fed7dd9235 -r 25a2bf666957 src/myproswift_periph.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/myproswift_periph.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,81 @@ +/* + ****************************************************************************** + * file: myswift_periph.cpp + *----------------------------------------------------------------------------- + */ + +#include "myproswift_periph.h" + +/* + ****************************************************************************** + * ADISense1000 + *----------------------------------------------------------------------------- + */ +//connection information for initialising ADISense1000 +ADI_SENSE_CONNECTION connectionInfo = { + .type = ADI_SENSE_CONNECTION_TYPE_SPI, + .spi = { + .mosiPin = SENSE_SPI_MOSI, + .misoPin = SENSE_SPI_MISO, + .sckPin = SENSE_SPI_SCK, + .csPin = SENSE_SPI_CS, + .maxSpeedHz = SENSE_SPI_FREQUENCY, + }, + .gpio = { + .resetPin = SENSE_RST_PIN, + .errorPin = SENSE_ERROR_PIN, + .alertPin = SENSE_ALERT_PIN, + .datareadyPin = SENSE_DREADY_PIN, + }, +}; + +/* + ****************************************************************************** + * Bluetooth Low Energy + *----------------------------------------------------------------------------- + */ +//reset pin of BLE module +DigitalOut ble_rst(BLE_RST_PIN, 0); +//flow control +DigitalOut ble_Cts(BLE_CTS_PIN, 1); +DigitalIn ble_Rts(BLE_RTS_PIN); + +Serial bleSerialDevice(BLE_SERIAL_TX, BLE_SERIAL_RX, BLE_BAUD_RATE); + +#ifdef BL652 +DigitalOut bleMode0(BLE_MODE_0_PIN, 0); +DigitalOut bleMode1(BLE_MODE_1_PIN, 0); +#endif + + +/* + ****************************************************************************** + * PC Serial + *----------------------------------------------------------------------------- + */ + +//pointer initialised in adi_sense_Log.cpp using pins defined in this header +Serial *gpUartDevice = new Serial(PC_UART_TX_PIN, PC_UART_RX_PIN, PC_UART_BAUDRATE); + +/* + ****************************************************************************** + * Battery + *----------------------------------------------------------------------------- + */ + +//pin for reading the current voltage of the battery +//need solution to this. Battery ranges from 4.2V to 2V where the adc can only +//read to 3.3V (VDD) +//AnalogIn batteryV(BATTERY_V_PIN); + +/* + ****************************************************************************** + * Status LED + *----------------------------------------------------------------------------- + */ + +//flash when flash led is called, also iluminated when device boots successfully +DigitalOut status_led(STATUS_LED_PIN, 0); +//DigitalOut status_led1(PC_6, 0); + +
diff -r 76fed7dd9235 -r 25a2bf666957 src/pc_interface/pc_interface.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pc_interface/pc_interface.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,1458 @@ +/* + * pc_interface.cpp - main interface to pc application + * + * Author: Jake Greaves + */ + +#include "pc_interface/pc_interface.h" + +#include "bootloader.h" + +extern DigitalOut status_led; + +extern ADI_SENSE_CONFIG adi_sense_config; +extern ADI_SENSE_DEVICE_HANDLE hDevice; +extern bool_t bDeviceReady; +extern ADI_SENSE_PRODUCT_ID productId; + +char respBuffer[RESPONSE_BUFFER_SIZE]; +char seperatorBuf[] = {PC_SEPERATOR}; +char delimBuf[1] = {PC_DELIMITER}; + + +/*************************************************************** +* Function Name: pc_reset_success +* Description : notify that device is ready +****************************************************************/ +int Pc_ResetSuccess(bool_t bBootLoader) +{ + char status[3]; + //char hello_pc[] = "hello pc!\r\n"; + + if(bBootLoader) { + //format error code into chars + //return error code indicating that we are entering bootloader mode + snprintf(status, sizeof(status), "%02X", NO_ERROR_BOOTLOADER); + } + + else { + //format error code into chars + snprintf(status, sizeof(status), "%02X", NO_ERROR); + } + + //print to serial + Pc_Write(status, strlen(status)); + Pc_Write(delimBuf, sizeof(delimBuf)); + //Pc_Write(hello_pc, 11); + //Pc_Write(hello_pc, strlen(hello_pc)); + + return 0; +} + +/*************************************************************** +* Function Name: pc_read_next_arg +* Description : read next arg, setting a flag if the delimiter is reached +****************************************************************/ +static int pc_read_next_arg(char *command, char *arg, int size, bool *flag) +{ + int readPos = 0; + char c; + + //clear flag + *flag = 0; + + //read until break or buffer is used + for(int i = 0; i < size + 1; i++) { + + //read single char from pc + c = command[0]; + //remove c from command + memmove(command, command + 1, strlen(command + 1)); + + //if seperator is found, argument is in buffer, return + if(c == PC_SEPERATOR) { + arg[readPos] = '\0'; + return 0; + } + + //if delimiter is found, set flag and return + else if(c == PC_DELIMITER) { + arg[readPos] = '\0'; + *flag = 1; + return 0; + } + + //else fill buffer with char + else { + if(i < size) + arg[readPos] = c; + readPos++; + } + } + + //buffer filled, return error + return 1; +} + +/*************************************************************** +* Function Name: pc_parse_device_info +* Description : get device info and return to pc +****************************************************************/ +static int pc_parse_device_info(void) +{ + //need to actually monitor this + char status[3]; + char batteryVoltage[] = "3.3"; + + //need to adjust hardware for this + //batteryV.read() * VCC; + + //format error code into chars + snprintf(status, sizeof(status), "%02X", NO_ERROR); + + //just a test, need to implement proper battery monitoring and firmware version control + Pc_Write(status, strlen(status)); + Pc_Write(seperatorBuf, 1); + Pc_Write(DEVICE_NAME, strlen(DEVICE_NAME)); + Pc_Write(seperatorBuf, 1); + Pc_Write(batteryVoltage, strlen(batteryVoltage)); + Pc_Write(seperatorBuf, 1); + Pc_Write(FIRMWARE_VERSION, strlen(FIRMWARE_VERSION)); + Pc_Write(delimBuf, 1); + + return 0; +} + +/*************************************************************** +* Function Name: pc_parse_flash_led +* Description : flash led to identify device +****************************************************************/ +static int pc_parse_flash_led(void) +{ + char status[3]; + //format error code into chars + snprintf(status, sizeof(status), "%02X", NO_ERROR); + + //flash led + for(int i = 0; i < 10; i++) { + status_led = !status_led; + wait(0.05); + } + + //return status ok + Pc_Write(status, strlen(status)); + Pc_Write(delimBuf, sizeof(delimBuf)); + + return 0; +} + +/*************************************************************** +* Function Name: parse_reset +* Description : perform a soft reset of the device +****************************************************************/ +static int pc_parse_reset(void) +{ + //call CMSIS reset function + NVIC_SystemReset(); + + //will never return as reset is called + return 0; +} + +/*************************************************************** +* Function Name: pc_parse_configure +* Description : parse the configure json command +****************************************************************/ +static int pc_parse_configure(char *commandString) +{ + int ret = 0; + bool delimiterFlag = 0; + char channel[32]; + int channelIndex = (ADI_SENSE_1000_CHANNEL_ID)-2; + char keyword[64]; + int keywordIndex = -1; + + //read in channel + pc_read_next_arg(commandString, channel, sizeof(channel), &delimiterFlag); + if(delimiterFlag) //if delimiter, action is complete + return pc_handle_error(ERROR_EXPECTED_CHANNEL); + + //read in first keyword + pc_read_next_arg(commandString, keyword, sizeof(keyword), &delimiterFlag); + if(delimiterFlag) + return pc_handle_error(ERROR_EXPECTED_KEYWORD); + + //find index of channel to configure + for(int i = -1; i < ADI_SENSE_1000_MAX_CHANNELS; i++) { + //cycle through conversion array, strncmp until found + if(!strncmp(channel, channelIdVals[i+1].stringVal, strlen(channelIdVals[i+1].stringVal))) { + channelIndex = i; + break; + } + } + + //handle error, channel not found + if(channelIndex < -1) + return pc_handle_error(ERROR_EXPECTED_CHANNEL); + + for(int i = 0; i < ENUM_ATTRIBUTE_SIZE; i++) { + //cycle through conversion array, strncmp until found + if(!strncmp(keyword, keywordConvert[i].stringEquiv, strlen(keywordConvert[i].stringEquiv))) { + keywordIndex = i; + break; + } + } + + //handle error, channel not found + if(keywordIndex < 0) + return pc_handle_error(ERROR_EXPECTED_KEYWORD); + + //pass channel and keyword index to configure command which parses the value and applies it to the struct + if(channelIndex > ADI_SENSE_1000_CHANNEL_ID_NONE) + ret = pc_parse_configure_channel((ADI_SENSE_1000_CHANNEL_ID)channelIndex, (CONFIG_ATTRIBUTE)keywordIndex, commandString); + else + ret = pc_parse_configure_device((CONFIG_ATTRIBUTE)keywordIndex, commandString); + + + if(ret != 0) + return pc_handle_error((ErrorType)ret); + + char status[3]; + //format error code into chars + snprintf(status, sizeof(status), "%02X", NO_ERROR); + Pc_Write(status, strlen(status)); + + //send response + Pc_Write(delimBuf, sizeof(delimBuf)); + + return ret; +} + +/*************************************************************** +* Function Name: parse_configure_device +* Description : parse the configure_device json command +****************************************************************/ +static int pc_parse_configure_device(CONFIG_ATTRIBUTE attribute, char *commandString) +{ + int valueIndex = -1; + char value[64]; + bool delimiterFlag = 0; + char *p; + float32_t newRegValFloat32; + + //read in first value + pc_read_next_arg(commandString, value, sizeof(value), &delimiterFlag); + + for(int i = 0; i < keywordConvert[attribute].valCount; i++) { + if(!strncmp(value, keywordConvert[attribute].valsConvert[i].stringVal, + strlen(keywordConvert[attribute].valsConvert[i].stringVal))) { + //value matched, store index and break + valueIndex = i; + break; + } + } + + switch(attribute) { + //configure global struct to reflect new configuration + //this struct can then be commited to write the ADISense1000 registers + case PRODUCT_ID: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + adi_sense_config.productId = (ADI_SENSE_PRODUCT_ID)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case POWER_MODE: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + adi_sense_config.adisense1000.power.powerMode = (ADI_SENSE_1000_POWER_MODE)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case OPERATIONAL_MODE: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + adi_sense_config.adisense1000.measurement.operatingMode = (ADI_SENSE_1000_OPERATING_MODE)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case DATA_READY_MODE: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + adi_sense_config.adisense1000.measurement.dataReadyMode = (ADI_SENSE_1000_DATAREADY_MODE)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case CYCLE_TIME: + if(valueIndex == -1) { + newRegValFloat32 = strtof(value, &p); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + } + else { + newRegValFloat32 = (float32_t) keywordConvert[attribute].valsConvert[valueIndex].structVal; + } + adi_sense_config.adisense1000.measurement.cycleInterval = newRegValFloat32; + break; + case GLOBAL_DIAGNOSTICS: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + adi_sense_config.adisense1000.diagnostics.disableGlobalDiag = (bool_t)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case MEASUREMENT_SPECIFIC_DIAGNOSTICS: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + adi_sense_config.adisense1000.diagnostics.disableMeasurementDiag = (bool_t)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case DIAGNOSTIC_MEASUREMENT_FREQUENCY: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + adi_sense_config.adisense1000.diagnostics.osdFrequency = (ADI_SENSE_1000_OPEN_SENSOR_DIAGNOSTICS)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + + default: + return (ERROR_CONVERSION_FAILED); + } + + //expect command string to be fully used + if(delimiterFlag) + return 0; + + else + return (ERROR_EXPECTED_DELIMITER); +} + +/*************************************************************** +* Function Name: parse_configure_channel +* Description : parse the configure_channel command +****************************************************************/ +static int pc_parse_configure_channel(ADI_SENSE_1000_CHANNEL_ID channelIndex, CONFIG_ATTRIBUTE attribute, char *commandString) +{ + int valueIndex = -1; + char value[64]; + bool delimiterFlag = 0; + char *p; + uint32_t newRegValUint32; + float32_t newRegValFloat32; + uint32_t sensorTimeNewVal; + uint32_t frontEndTimeNewVal; + uint32_t extraSettlingTime; + + //read in first value + pc_read_next_arg(commandString, value, sizeof(value), &delimiterFlag); + + //find index of value, where possible + for(int i = 0; i < keywordConvert[attribute].valCount; i++) { + if(!strncmp(value, keywordConvert[attribute].valsConvert[i].stringVal, + strlen(keywordConvert[attribute].valsConvert[i].stringVal))) { + //value matched, store index and break + valueIndex = i; + break; + } + } + + ADI_SENSE_1000_CHANNEL_CONFIG *channel = &adi_sense_config.adisense1000.channels[channelIndex]; + + //check for only analog attributes on analog channels + if(channelIndex < ADI_SENSE_1000_CHANNEL_ID_I2C_0) { + + switch(attribute) { + //configure global struct to reflect new configuration + //this struct can then be commited to write the ADISense1000 registers + case MEASUREMENT_ENABLE: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> enableChannel = (bool_t)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case PUBLISH_MEASUREMENT: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> disablePublishing = (bool_t)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case ASSIGNED_COMPENSATION_MEASUREMENT_CHANNEL: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> compensationChannel = (ADI_SENSE_1000_CHANNEL_ID)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case DISPLAY_UNIT: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> measurementUnit = (ADI_SENSE_1000_MEASUREMENT_UNIT)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case MEASUREMENT_MIN_VALUE: + if(valueIndex == -1) { + newRegValFloat32 = strtof(value, &p); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + } + else { + newRegValFloat32 = (float32_t) keywordConvert[attribute].valsConvert[valueIndex].structVal; + } + channel -> lowThreshold = newRegValFloat32; + break; + case MEASUREMENT_MAX_VALUE: + if(valueIndex == -1) { + newRegValFloat32 = strtof(value, &p); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + } + else { + newRegValFloat32 = (float32_t) keywordConvert[attribute].valsConvert[valueIndex].structVal; + } + channel -> highThreshold = newRegValFloat32; + break; + case MEASUREMENTS_PER_CYCLE: + if(valueIndex == -1) { + newRegValUint32 = strtol(value, &p, 10); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + } + else { + newRegValFloat32 = (uint32_t) keywordConvert[attribute].valsConvert[valueIndex].structVal; + } + channel -> measurementsPerCycle = newRegValUint32; + break; + case SETTLING_TIME: + if(valueIndex == -1) { + //check command string hasn't ended as we expect more parameters + if(delimiterFlag) + return (ERROR_EXPECTED_VALUE); + //parse last parameter expected to calculate extra settling time + char frontEndSettling[32]; + pc_read_next_arg(commandString, frontEndSettling, sizeof(frontEndSettling), &delimiterFlag); + //extra settling time is equal to sensor settling - frontend. This is a check value for the ADISense1000 + sensorTimeNewVal = strtol(value, &p, 10); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + frontEndTimeNewVal = strtol(frontEndSettling, &p, 10); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + + extraSettlingTime = sensorTimeNewVal - frontEndTimeNewVal; + } + else { + extraSettlingTime = (uint32_t) keywordConvert[attribute].valsConvert[valueIndex].structVal; + } + channel -> extraSettlingTime = extraSettlingTime; + break; + case SENSOR_TYPE: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> adcChannelConfig.sensor = (ADI_SENSE_1000_ADC_SENSOR_TYPE)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case GAIN: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> adcChannelConfig.gain = (ADI_SENSE_1000_ADC_GAIN)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case EXCITATION_CURRENT: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> adcChannelConfig.current.outputLevel = (ADI_SENSE_1000_ADC_EXC_CURRENT)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case FILTER_TYPE: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> adcChannelConfig.filter.type = (ADI_SENSE_1000_ADC_FILTER_TYPE)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case FILTER_FS: + if(valueIndex == -1) { + newRegValUint32 = strtol(value, &p, 10); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + } + else { + newRegValUint32 = (uint32_t)keywordConvert[attribute].valsConvert[valueIndex].structVal; + } + channel -> adcChannelConfig.filter.fs = newRegValUint32; + break; + case REFERENCE: + //check command string hasn't ended as we expected more parameters + if(delimiterFlag) + return (ERROR_EXPECTED_VALUE); + + //need to read in 4 args to parse this. ReferenceSelect (Value), ReferenceResistor, ReferenceResistorSelect, ReferenceVoltage. + char referenceResistor[32]; + pc_read_next_arg(commandString, referenceResistor, sizeof(referenceResistor), &delimiterFlag); + if(delimiterFlag) + return (ERROR_EXPECTED_VALUE); + + char referenceResistorSelect[32]; + pc_read_next_arg(commandString, referenceResistorSelect, sizeof(referenceResistorSelect), &delimiterFlag); + if(delimiterFlag) + return (ERROR_EXPECTED_VALUE); + + char referenceVoltage[32]; + pc_read_next_arg(commandString, referenceVoltage, sizeof(referenceVoltage), &delimiterFlag); + + if(!strncmp(referenceResistorSelect, REF_RES_SELECT_INTERNAL, strlen(REF_RES_SELECT_INTERNAL))) { + if(!strncmp(value, REF_SELECT_REFIN1, strlen(REF_SELECT_REFIN1))) { + channel -> adcChannelConfig.reference.type = ADI_SENSE_1000_ADC_REFERENCE_RESISTOR_INTERNAL_1; + } + else if(!strncmp(value, REF_SELECT_REFIN2, strlen(REF_SELECT_REFIN2))) { + channel -> adcChannelConfig.reference.type = ADI_SENSE_1000_ADC_REFERENCE_RESISTOR_INTERNAL_2; + } + else + return (ERROR_CONVERSION_FAILED); + } + else if(!strncmp(referenceResistorSelect, REF_RES_SELECT_EXTERNAL, strlen(REF_RES_SELECT_EXTERNAL))) { + if(!strncmp(value, REF_SELECT_REFIN1, strlen(REF_SELECT_REFIN1))) { + channel -> adcChannelConfig.reference.type = ADI_SENSE_1000_ADC_REFERENCE_RESISTOR_EXTERNAL_1; + //strtol reference resistor to config. Not currently available + } + else if(!strncmp(value, REF_SELECT_REFIN2, strlen(REF_SELECT_REFIN2))) { + channel -> adcChannelConfig.reference.type = ADI_SENSE_1000_ADC_REFERENCE_RESISTOR_EXTERNAL_2; + //strtol reference resistor to config. Not currently available + } + else + return (ERROR_CONVERSION_FAILED); + } + else if(!strncmp(referenceResistorSelect, REF_RES_SELECT_NA, strlen(REF_RES_SELECT_NA))) { + if(!strncmp(value, REF_SELECT_REFIN1, strlen(REF_SELECT_REFIN1))) { + channel -> adcChannelConfig.reference.type = ADI_SENSE_1000_ADC_REFERENCE_VOLTAGE_EXTERNAL_1; + //strtol reference voltage to config. Not currently available + } + else if(!strncmp(value, REF_SELECT_REFIN2, strlen(REF_SELECT_REFIN2))) { + channel -> adcChannelConfig.reference.type = ADI_SENSE_1000_ADC_REFERENCE_VOLTAGE_EXTERNAL_2; + //strtol reference volatge to config. Not currently available + } + else if(!strncmp(value, REF_SELECT_INTERNAL, strlen(REF_SELECT_INTERNAL))) { + channel -> adcChannelConfig.reference.type = ADI_SENSE_1000_ADC_REFERENCE_VOLTAGE_INTERNAL; + } + else + channel -> adcChannelConfig.reference.type = ADI_SENSE_1000_ADC_REFERENCE_NONE; + } + else + return (ERROR_CONVERSION_FAILED); + + break; + case VBIAS_ENABLE: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> adcChannelConfig.enableVbias = (bool_t)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + + default: + return (ERROR_ATTR_NOT_SUPPORTED_ON_CHANNEL); + } + } + + //check for only digital attributes on digital channels + else if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0) { + + switch(attribute) { + //configure global struct to reflect new configuration + //this struct can then be commited to write the ADISense1000 registers + case MEASUREMENT_ENABLE: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> enableChannel = (bool_t)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case PUBLISH_MEASUREMENT: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> disablePublishing = (bool_t)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case ASSIGNED_COMPENSATION_MEASUREMENT_CHANNEL: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> compensationChannel = (ADI_SENSE_1000_CHANNEL_ID)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case DISPLAY_UNIT: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + channel -> measurementUnit = (ADI_SENSE_1000_MEASUREMENT_UNIT)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + case MEASUREMENT_MIN_VALUE: + if(valueIndex == -1) { + newRegValFloat32 = strtof(value, &p); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + } + else { + newRegValFloat32 = (float32_t) keywordConvert[attribute].valsConvert[valueIndex].structVal; + } + channel -> lowThreshold = newRegValFloat32; + break; + case MEASUREMENT_MAX_VALUE: + if(valueIndex == -1) { + newRegValFloat32 = strtof(value, &p); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + } + else { + newRegValFloat32 = (float32_t) keywordConvert[attribute].valsConvert[valueIndex].structVal; + } + channel -> highThreshold = newRegValFloat32; + break; + case MEASUREMENTS_PER_CYCLE: + if(valueIndex == -1) { + newRegValUint32 = strtol(value, &p, 10); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + } + else { + newRegValFloat32 = (uint32_t) keywordConvert[attribute].valsConvert[valueIndex].structVal; + } + channel -> measurementsPerCycle = newRegValUint32; + break; + case SETTLING_TIME: + if(valueIndex == -1) { + //check command string hasn't ended as we expect more parameters + if(delimiterFlag) + return (ERROR_EXPECTED_VALUE); + //parse last parameter expected to calculate extra settling time + char frontEndSettling[32]; + pc_read_next_arg(commandString, frontEndSettling, sizeof(frontEndSettling), &delimiterFlag); + //extra settling time is equal to sensor settling - frontend. This is a check value for the ADISense1000 + sensorTimeNewVal = strtol(value, &p, 10); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + frontEndTimeNewVal = strtol(frontEndSettling, &p, 10); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + + extraSettlingTime = sensorTimeNewVal - frontEndTimeNewVal; + } + else { + extraSettlingTime = (uint32_t) keywordConvert[attribute].valsConvert[valueIndex].structVal; + } + channel -> extraSettlingTime = extraSettlingTime; + break; + case SENSOR_TYPE: + if(valueIndex == -1) + return (ERROR_CONVERSION_FAILED); + + if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0 && channelIndex < ADI_SENSE_1000_CHANNEL_ID_SPI_0) + channel -> i2cChannelConfig.sensor = (ADI_SENSE_1000_I2C_SENSOR_TYPE)keywordConvert[attribute].valsConvert[valueIndex].structVal; + else if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_SPI_0 && channelIndex < ADI_SENSE_1000_MAX_CHANNELS) + channel -> spiChannelConfig.sensor = (ADI_SENSE_1000_SPI_SENSOR_TYPE)keywordConvert[attribute].valsConvert[valueIndex].structVal; + break; + + case DEVICE_ADDRESS: + if(valueIndex == -1) { + if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0 && channelIndex < ADI_SENSE_1000_CHANNEL_ID_SPI_0) { + newRegValUint32 = strtol(value, &p, 0); + if(*p != '\0') + return (ERROR_EXPECTED_VALUE); + channel -> i2cChannelConfig.deviceAddress = newRegValUint32; + } + else + return (ERROR_CONVERSION_FAILED); + } + else { + channel -> i2cChannelConfig.deviceAddress = (uint32_t) keywordConvert[attribute].valsConvert[valueIndex].structVal; + } + break; + + //NOT NEEDED FOR FIRST SAMPLING + /*case READ_COMMAND: + if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0 && channelIndex < ADI_SENSE_1000_CHANNEL_ID_SPI_0) { + commandBuf = strtol(value, NULL, 10); + memcpy(, channel -> i2cChannelConfig.dataRequestCommand.command); + channel -> i2cChannelConfig.dataRequestCommand.commandLength = ; + } + break; + case CONFIG_COMMAND: + if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0 && channelIndex < ADI_SENSE_1000_CHANNEL_ID_SPI_0) { + channel -> i2cChannelConfig.configurationCommand.command = ; + channel -> i2cChannelConfig.configurationCommand.commandLength = ; + } + break; + case NUMBER_OF_BITS: + if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0 && channelIndex < ADI_SENSE_1000_CHANNEL_ID_SPI_0) { + channel -> i2cChannelConfig.dataFormat.numDataBits = ; + } + break; + case FRAME_WIDTH: + if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0 && channelIndex < ADI_SENSE_1000_CHANNEL_ID_SPI_0) { + channel -> i2cChannelConfig.dataFormat.frameLength = ; + } + break; + case LEFT_ALIGNMENT: + if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0 && channelIndex < ADI_SENSE_1000_CHANNEL_ID_SPI_0) { + channel -> i2cChannelConfig.dataFormat.leftJustified = ; + } + break; + case DATA_ENDIANNESS: + if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0 && channelIndex < ADI_SENSE_1000_CHANNEL_ID_SPI_0) { + channel -> i2cChannelConfig.dataFormat.littleEndian = ; + } + break; + case OFFSET: + if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0 && channelIndex < ADI_SENSE_1000_CHANNEL_ID_SPI_0) { + channel -> i2cChannelConfig.dataFormat.bitOffset = ; + } + break; + case CODING: + if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0 && channelIndex < ADI_SENSE_1000_CHANNEL_ID_SPI_0) { + channel -> i2cChannelConfig.dataFormat.coding = ; + } + break; + case CPOL_CPHA: + if(channelIndex >= ADI_SENSE_1000_CHANNEL_ID_I2C_0 && channelIndex < ADI_SENSE_1000_CHANNEL_ID_SPI_0) { + channel -> i2cChannelConfig.dataFormat = ; + } + break; + */ + default: + return (ERROR_ATTR_NOT_SUPPORTED_ON_CHANNEL); + } + } + + //expect that the whole command string has been used + if(delimiterFlag) + return 0; + + else + return (ERROR_EXPECTED_DELIMITER); +} + +/*************************************************************** +* Function Name: pc_parse_apply +* Description : apply the config to the device +****************************************************************/ +static int pc_parse_apply(void) +{ + //upload new configuration and apply + if(adi_sense_SetConfig(hDevice, &adi_sense_config) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_SET_CONFIG); + if(adi_sense_ApplyConfigUpdates(hDevice) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_UPDATE_CONFIG); + +#ifdef VIRT_EEPROM + //Unlock the Flash Program Erase controller + HAL_FLASH_Unlock(); + + //write adi_sense_config to eeprom + uint16_t *p = (uint16_t*)&adi_sense_config; + uint16_t temp; + + for(int i = 0; i < sizeof(adi_sense_config)/sizeof(uint16_t); i++, p++) { + + if((EE_WriteVariable(VirtAddVarTab[1] + i, *p)) != HAL_OK) + { + exit(1); + } + if((EE_WriteVariable(VirtAddVarTab[1] + i, *p)) != HAL_OK) + { + exit(1); + } + if((EE_ReadVariable(VirtAddVarTab[1] + i, &temp)) != HAL_OK) + { + exit(1); + } + if (temp != *p) + { + exit(1); + } + } + + //flag for valid configuration + uint16_t eepromConfigValid = 0xAF; + + //write configuration valid flag + if((EE_WriteVariable(VirtAddVarTab[0], eepromConfigValid)) != HAL_OK) + { + exit(1); + } + + //Lock the Flash Program Erase controller + HAL_FLASH_Lock(); +#endif + + char status[3]; + //format error code into chars + snprintf(status, sizeof(status), "%02X", NO_ERROR); + Pc_Write(status, strlen(status)); + + //send response + Pc_Write(delimBuf, sizeof(delimBuf)); + + return 0; +} + +/*************************************************************** +* Function Name: data_ready_callback +* Description : callback for when data ready state changes +****************************************************************/ +static void pc_data_ready_callback( + ADI_SENSE_GPIO_PIN ePinId, + void *pArg) +{ + volatile bool_t *pbFlag = (volatile bool_t *) pArg; + + *pbFlag = true; +} + +/*************************************************************** +* Function Name: pc_register_callbacks +* Description : callback for when data ready state changes +****************************************************************/ +static int pc_register_callbacks(ADI_SENSE_DEVICE_HANDLE hDevice, + volatile bool_t *pbDataReady, + volatile bool_t *pbError, + volatile bool_t *pbAlert) +{ + int res; + + res = adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_DATAREADY, + pc_data_ready_callback, (void *)pbDataReady); + if (res != ADI_SENSE_SUCCESS) + { + return res; + } + + res = adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_ERROR, + pc_data_ready_callback, (void *)pbError); + if (res != ADI_SENSE_SUCCESS) + { + return res; + } + + res = adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_ALERT, + pc_data_ready_callback, (void *)pbAlert); + if (res != ADI_SENSE_SUCCESS) + { + return res; + } + + return ADI_SENSE_SUCCESS; +} + +/*************************************************************** +* Function Name: pc_deregister_callbacks +* Description : callback for when data ready state changes +****************************************************************/ +ADI_SENSE_RESULT pc_deregister_callbacks( + 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) + { + return res; + } + + res = adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_ERROR, + NULL, NULL); + if (res != ADI_SENSE_SUCCESS) + { + return res; + } + + res = adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_ALERT, + NULL, NULL); + if (res != ADI_SENSE_SUCCESS) + { + return res; + } + + return ADI_SENSE_SUCCESS; +} + +/*************************************************************** +* Function Name: pc_parse_sample +* Description : parse the sample command +****************************************************************/ +static int pc_parse_sample(char *commandString) +{ + ADI_SENSE_STATUS status; + ADI_SENSE_DATA_SAMPLE *pSampleBuffer; + ADI_SENSE_1000_OPERATING_MODE eOperatingMode; + ADI_SENSE_1000_DATAREADY_MODE eDataPublishMode; + uint32_t nSamplesPerDataready; + uint32_t nSamplesPerCycle; + uint32_t maxMeasurementCycles; + ADI_SENSE_MEASUREMENT_MODE eMeasurementMode = ADI_SENSE_MEASUREMENT_MODE_NORMAL; + bool firstSample = true; //flag for if this is the first round of sampling, include status code + volatile bool_t bDataReady = false; + volatile bool_t bError = false; + volatile bool_t bAlert = false; + + char *p; //check strtol has parsed correctly + + char maxMeasurementCyclesString[20] = ""; + bool delimiterFlag = 0; + + //register callbacks for status pins + if (pc_register_callbacks(hDevice, &bDataReady, &bError, &bAlert) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_GPIO_CALLBACK_REG); + + pc_read_next_arg(commandString, maxMeasurementCyclesString, sizeof(maxMeasurementCyclesString), &delimiterFlag); + if(!strcmp(maxMeasurementCyclesString, "") || !strncmp(maxMeasurementCyclesString, "0", strlen("0"))) + return pc_handle_error(ERROR_EXPECTED_VALUE); + if(!delimiterFlag) + return pc_handle_error(ERROR_EXPECTED_DELIMITER); + + //convert string to integer + maxMeasurementCycles = strtol(maxMeasurementCyclesString, &p, 10); + if(*p != '\0') + return pc_handle_error(ERROR_EXPECTED_VALUE); + + if(maxMeasurementCycles < 1) + return pc_handle_error(ERROR_EXPECTED_VALUE); + + //Allocate a buffer to store the samples retreived on each DATAREADY pulse + if(adi_sense_1000_GetDataReadyModeInfo(hDevice, + eMeasurementMode, + &eOperatingMode, + &eDataPublishMode, + &nSamplesPerDataready, + &nSamplesPerCycle) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_GET_DRDY_INFO); + + //allocate a buffer for samples using the ADISense1000 API + pSampleBuffer = new ADI_SENSE_DATA_SAMPLE[nSamplesPerDataready]; + if(pSampleBuffer == NULL) + return pc_handle_error(ERROR_ALLOCATE_BUFFER); + + char seperatorBuf[] = {PC_SEPERATOR}; + + //handle the single cycle device mode + if (eOperatingMode == ADI_SENSE_1000_OPERATING_MODE_SINGLECYCLE) { + uint32_t nTotalCycles = 0; + + do { + //begin measurement cycles + if(adi_sense_StartMeasurement(hDevice, eMeasurementMode) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_START_MEASUREMENT); + + //read in each measurement cycle + for (unsigned i = 0; i < nSamplesPerCycle / nSamplesPerDataready; i++) { + uint32_t nReturned; + + //Interrupt method: wait for DATAREADY interrupt callback + while(!(bDataReady || bError)); + + if(!bError) { + //reset bDataReady flag to detect the next callback + bDataReady = false; + + //read data into structure + if(adi_sense_GetData(hDevice, eMeasurementMode, pSampleBuffer, nSamplesPerDataready, &nReturned) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_GET_DATA); + if(nReturned != nSamplesPerDataready) + return pc_handle_error(ERROR_SAMPLE_COUNT_MISMATCH); + + if(firstSample) { + firstSample = false; + //begin with status byte + char status[3]; + //format error code into chars + snprintf(status, sizeof(status), "%02X", NO_ERROR); + //send response + Pc_Write(status, sizeof(status) - 1); + } + + //build a response string + for(int i = 0; i < nReturned; i++) { + float32_t *sample = &pSampleBuffer[i].processedValue; + memcpy(respBuffer, (uint8_t*)sample, sizeof(float32_t)); + Pc_Write(seperatorBuf, 1); + + for(int j = 0; j < sizeof(float32_t); j++) { + char buf[3]; + snprintf(buf, sizeof(buf), "%02X", respBuffer[j]); + Pc_Write(buf, 2); + } + } + } + + else { + break; + } + + } + nTotalCycles++; + + } while (!bError && (nTotalCycles < maxMeasurementCycles)); + } + + //handle continuous measurement mode + else { + uint32_t nTotalSamples = 0; + + //begin measurement cycles + if(adi_sense_StartMeasurement(hDevice, eMeasurementMode) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_START_MEASUREMENT); + + do { + uint32_t nReturned; + + //Interrupt method: wait for DATAREADY interrupt callback + while(!(bDataReady || bError)); + + if(!bError) { + //reset bDataReady flag to detect the next callback + bDataReady = false; + + //read data into structure + if(adi_sense_GetData(hDevice, eMeasurementMode, pSampleBuffer, nSamplesPerDataready, &nReturned) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_GET_DATA); + if(nReturned != nSamplesPerDataready) + return pc_handle_error(ERROR_SAMPLE_COUNT_MISMATCH); + + if(firstSample) { + firstSample = false; + //begin with status byte + char status[3]; + //format error code into chars + snprintf(status, sizeof(status), "%02X", NO_ERROR); + //send response + Pc_Write(status, sizeof(status) - 1); + } + + //build a response string + for(int i = 0; i < nReturned; i++) { + float32_t *sample = &pSampleBuffer[i].processedValue; + memcpy(respBuffer, (uint8_t*)sample, sizeof(float32_t)); + Pc_Write(seperatorBuf, 1); + for(int j = 0; j < sizeof(float32_t); j++) { + char buf[3]; + snprintf(buf, sizeof(buf), "%02X", respBuffer[j]); + Pc_Write(buf, 2); + } + } + + //count samples + nTotalSamples += nReturned; + } + + } while (!bError && ((nTotalSamples / nSamplesPerCycle) < maxMeasurementCycles)); + + if(adi_sense_StopMeasurement(hDevice) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_STOP_MEASUREMENT); + } + + //currently only error case is handled + if (bError || bAlert) + { + if(adi_sense_GetStatus(hDevice, &status) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_GET_DATA); + + if (status.deviceStatus & + (ADI_SENSE_DEVICE_STATUS_ERROR | ADI_SENSE_DEVICE_STATUS_ALERT)) + { + if (bError) + return pc_handle_error(ERROR_GET_DATA); + } + } + + delete [] pSampleBuffer; + + if(pc_deregister_callbacks(hDevice) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_GPIO_CALLBACK_REG); + + Pc_Write(delimBuf, sizeof(delimBuf)); + + return 0; + + /*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;*/ +} + +/*************************************************************** +* Function Name: pc_parse_start_stream +* Description : parse the stream command +****************************************************************/ +static int pc_parse_start_stream(void) +{ + ADI_SENSE_DATA_SAMPLE *pSampleBuffer; + ADI_SENSE_1000_OPERATING_MODE eOperatingMode; + ADI_SENSE_1000_DATAREADY_MODE eDataPublishMode; + uint32_t nSamplesPerDataready; + uint32_t nSamplesPerCycle; + ADI_SENSE_MEASUREMENT_MODE eMeasurementMode = ADI_SENSE_MEASUREMENT_MODE_NORMAL; + + char status[3]; + + volatile bool_t bDataReady = false; + + //upload new configuration and apply + if(adi_sense_SetConfig(hDevice, &adi_sense_config) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_SET_CONFIG); + + if(adi_sense_ApplyConfigUpdates(hDevice) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_UPDATE_CONFIG); + + //Allocate a buffer to store the samples retreived on each DATAREADY pulse + if(adi_sense_1000_GetDataReadyModeInfo(hDevice, + eMeasurementMode, + &eOperatingMode, + &eDataPublishMode, + &nSamplesPerDataready, + &nSamplesPerCycle) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_GET_DRDY_INFO); + + //allocate a buffer for samples using the ADISense1000 API + pSampleBuffer = new ADI_SENSE_DATA_SAMPLE[nSamplesPerDataready]; + if(pSampleBuffer == NULL) + return pc_handle_error(ERROR_ALLOCATE_BUFFER); + + //begin with status byte + //format error code into chars + snprintf(status, sizeof(status), "%02X", NO_ERROR); + //send response + Pc_Write(status, sizeof(status) - 1); + + //setup callback routine for pc + bool bPcMessageFlag = 0; + char msgBuffer[1]; + Pc_SetupReadLineCb(msgBuffer, 1, &bPcMessageFlag); + + //handle the single cycle device mode + if (eOperatingMode == ADI_SENSE_1000_OPERATING_MODE_SINGLECYCLE) { + uint32_t nTotalCycles = 0; + + //interrupt-triggered DATAREADY notifications in this mode + if(adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_DATAREADY, + pc_data_ready_callback, + (void *)&bDataReady) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_GPIO_CALLBACK_REG); + + do { + //begin measurement cycles + if(adi_sense_StartMeasurement(hDevice, eMeasurementMode) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_START_MEASUREMENT); + + //read in each measurement cycle + for (unsigned i = 0; i < nSamplesPerCycle / nSamplesPerDataready; i++) { + uint32_t nReturned; + + //Interrupt method: wait for DATAREADY interrupt callback + while (!bDataReady); + + //reset bDataReady flag to detect the next callback + bDataReady = false; + + //read data into structure + if(adi_sense_GetData(hDevice, eMeasurementMode, pSampleBuffer, nSamplesPerDataready, &nReturned) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_GET_DATA); + if(nReturned != nSamplesPerDataready) + return pc_handle_error(ERROR_SAMPLE_COUNT_MISMATCH); + + //build a response string + for(int i = 0; i < nReturned; i++) { + float32_t *sample = &pSampleBuffer[i].processedValue; + memcpy(respBuffer, (uint8_t*)sample, sizeof(float32_t)); + Pc_Write(seperatorBuf, 1); + for(int j = 0; j < sizeof(float32_t); j++) { + char buf[3]; + snprintf(buf, sizeof(buf), "%02X", respBuffer[j]); + Pc_Write(buf, 2); + } + } + + } + nTotalCycles++; + + //check read byte to see if streaming should be stopped + if(bPcMessageFlag) { + if(msgBuffer[0] == COMMAND_STOP_STREAM) { + Pc_Write(delimBuf, sizeof(delimBuf)); + break; + } + else + Pc_SetupReadLineCb(msgBuffer, 1, &bPcMessageFlag); + } + } while (1); + } + + //handle continuous measurement mode + else { + uint32_t nTotalSamples = 0; + + //interrupt-triggered DATAREADY notifications in this mode + if(adi_sense_RegisterGpioCallback(hDevice, ADI_SENSE_GPIO_PIN_DATAREADY, + pc_data_ready_callback, + (void *)&bDataReady) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_GPIO_CALLBACK_REG); + + //begin measurement cycles + if(adi_sense_StartMeasurement(hDevice, eMeasurementMode) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_START_MEASUREMENT); + + do { + uint32_t nReturned; + + //Interrupt method: wait for DATAREADY interrupt callback + while (!bDataReady); + + //reset bDataReady flag to detect the next callback + bDataReady = false; + + //read data into structure + if(adi_sense_GetData(hDevice, eMeasurementMode, pSampleBuffer, nSamplesPerDataready, &nReturned) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_GET_DATA); + if(nReturned != nSamplesPerDataready) + return pc_handle_error(ERROR_SAMPLE_COUNT_MISMATCH); + + //build a response string + for(int i = 0; i < nReturned; i++) { + float32_t *sample = &pSampleBuffer[i].processedValue; + memcpy(respBuffer, (uint8_t*)sample, sizeof(float32_t)); + Pc_Write(seperatorBuf, 1); + for(int j = 0; j < sizeof(float32_t); j++) { + char buf[3]; + snprintf(buf, sizeof(buf), "%02X", respBuffer[j]); + Pc_Write(buf, 2); + } + } + + //count samples + nTotalSamples += nReturned; + + //check read byte to see if streaming should be stopped + if(bPcMessageFlag) { + if(msgBuffer[0] == COMMAND_STOP_STREAM) { + Pc_Write(delimBuf, sizeof(delimBuf)); + break; + } + else + Pc_SetupReadLineCb(msgBuffer, 1, &bPcMessageFlag); + } + } while (1); + + if(adi_sense_StopMeasurement(hDevice) != ADI_SENSE_SUCCESS) + return pc_handle_error(ERROR_STOP_MEASUREMENT); + } + + Pc_ClearReadLineCb(); + + delete [] pSampleBuffer; + + //begin with status byte + //format error code into chars + snprintf(status, sizeof(status), "%02X", NO_ERROR); + //send response + Pc_Write(status, sizeof(status) - 1); + + Pc_Write(delimBuf, sizeof(delimBuf)); + + return 0; +} + +/*************************************************************** +* Function Name: pc_parse_update_fw_version +* Description : set bootloader flag and reset device into +* mode expecting programming over serial. +****************************************************************/ +int pc_parse_update_fw_version() +{ + //set backup register flag to enter bootloader + Rcc_WriteBackupReg(BOOTLOADER_FLAG_BACKUP_REG, 1); + + //perform soft reset + return pc_parse_reset(); +} + +/*************************************************************** +* Function Name: handle_error +* Description : handle an error +****************************************************************/ +int pc_handle_error(ErrorType error) +{ + char status[3]; + //begin with status byte + //format error code into chars + snprintf(status, sizeof(status), "%02X", error); + //send response + Pc_Write(status, sizeof(status) - 1); + + Pc_Write(delimBuf, sizeof(delimBuf)); + + return 1; +} + +/*************************************************************** +* Function Name: Pc_ParseCommand +* Description : parse the configure json command +****************************************************************/ +int Pc_ParseCommand( char *commandString ) +{ + char c; + bool flag; + + pc_read_next_arg(commandString, &c, 1, &flag); + + //if no command was found, enumIndex will equal -1 and therefore execute the default case. This handles the error + switch(c) { + + //pc is requesting the information packet about this device + case COMMAND_DEVICE_INFO: + return pc_parse_device_info(); + + //pc is requesting this device to flash it's led to identify itself + case COMMAND_FLASH_LED: + return pc_parse_flash_led(); + + //soft reset the system + case COMMAND_RESET: + return pc_parse_reset(); + + //configure the local reg map + case COMMAND_CONFIGURE: + return pc_parse_configure(commandString); + + //apply configuration to device + case COMMAND_APPLY: + return pc_parse_apply(); + + //return a single instance of sampling to the pc + case COMMAND_SAMPLE: + return pc_parse_sample(commandString); + + //begin streaming data to the pc, this locks out until the stopstream command is received + case COMMAND_START_STREAM: + return pc_parse_start_stream(); + + case COMMAND_STOP_STREAM: + return pc_handle_error(ERROR_STREAM_NOT_STARTED); + + case COMMAND_UPDATE_FW_VERSION: + return pc_parse_update_fw_version(); + + //Template + //case COMMAND: return parse_COMMAND(); + //parse_COMMAND handles the action required + //COMMAND must be defined within the header file + + //handle an unrecognised command/error + + default: + return pc_handle_error(ERROR_NO_COMMAND_MATCHED); + } +} +
diff -r 76fed7dd9235 -r 25a2bf666957 src/pc_interface/pc_json_conversions.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pc_interface/pc_json_conversions.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,1 @@ +
diff -r 76fed7dd9235 -r 25a2bf666957 src/pc_interface/pc_serial.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/pc_interface/pc_serial.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,167 @@ +/* + * pc_serial.cpp - serial communcations to pc as debug + * future use for eval software + * + * Author: Jake Greaves + */ + +#include "pc_interface/pc_serial.h" + +//init for pc comms +extern Serial *gpUartDevice; + +//used by callback handler +static char *cbSerialBuffer; +volatile static bool *bPcMessageReceived; +static uint32_t cbCount = 0; +static uint32_t cbMaxSize; + +/*************************************************************** +* Function Name: pc_uart_callback +* Description : Callback for pc communications +****************************************************************/ +static void Pc_Callback(void) +{ + while(gpUartDevice -> readable()) { + //read char and effecively clear this callback flag + char c = gpUartDevice -> getc(); + + //check buffer is allocated + if(cbSerialBuffer != NULL) { + //store char to return buffer + cbSerialBuffer[cbCount] = c; + + if(c == '\n') { + //set flag that data has been received + *bPcMessageReceived = 1; + break; + } + else { + //increment count, pos in buffer + cbCount++; + } + } + } +} + +/*************************************************************** +* Function Name: pc_setup_read_line_cb +* Description : setup callback to handle pc comms +* cb sets flag when full message is received +****************************************************************/ +uint32_t Pc_SetupReadLineCb( char *rxBuffer, uint32_t maxSize, volatile bool *bMessageReadFlag ) +{ + uint32_t ret = 0; + + //setup global vars for handler funtions + cbCount = 0; + cbMaxSize = maxSize; + + //assign serial callback buffer + if( rxBuffer != NULL ) { + cbSerialBuffer = rxBuffer; + } + else { + return 1; + } + + //clear global flag + bPcMessageReceived = bMessageReadFlag; + + //setup callback to uart handle + ret = Uart_ReadCb( *gpUartDevice, Pc_Callback ); + + return ret; +} + +/*************************************************************** +* Function Name: pc_setup_read_line_cb +* Description : setup callback to handle pc comms +* cb sets flag when full message is received +****************************************************************/ +uint32_t Pc_ClearReadLineCb( void ) +{ + //clear callback to uart handle + return Uart_ClearCb( *gpUartDevice ); +} + +/*************************************************************** +* Function Name: pc_uart_callback +* Description : Callback for pc communications +****************************************************************/ +uint32_t Pc_Read( char *rxBuffer, uint32_t maxSize ) +{ + for(uint32_t i = 0; i < maxSize; i++) + rxBuffer[i] = gpUartDevice -> getc(); + + return 0; +} + +/*************************************************************** +* Function Name: pc_write +* Description : write formatted string to pc terminal +****************************************************************/ +uint32_t Pc_Write( const char* txBuffer, uint32_t size ) +{ + //call uart functions + Uart_Write( *gpUartDevice, txBuffer, size ); + + return 0; +} + +/*************************************************************** +* Function Name: pc_write_error +* Description : write formatted string to pc terminal +* preceded by Error: +****************************************************************/ +uint32_t Pc_WriteError( const char* txBuffer, ... ) +{ + char buff[PC_BUFFER_SIZE]; + + //precede string with error tag + gpUartDevice -> printf( "Error: " ); + + //format string to send + va_list args; + va_start( args, txBuffer ); + vsprintf( buff, txBuffer, args ); + + //call uart functions + Uart_Write( *gpUartDevice, buff, strlen( buff ) ); + + //cleanup args + va_end( args ); + + return 0; +} + +/*************************************************************** +* Function Name: pc_write_debug +* Description : write formatted string to pc terminal + preceded by Debug: +****************************************************************/ +uint32_t Pc_WriteDebug(const char* txBuffer, ...) +{ + char buff[PC_BUFFER_SIZE]; + + //precede string with debug tag + gpUartDevice -> printf( "Debug: " ); + + //format string to send + va_list args; + va_start( args, txBuffer ); + vsprintf( buff, txBuffer, args ); + + //call uart functions + Uart_Write( *gpUartDevice, buff, strlen( buff ) ); + gpUartDevice -> printf( "\n\r" ); + + //cleanup args + va_end(args); + + return 0; +} + +//EOF + +
diff -r 76fed7dd9235 -r 25a2bf666957 src/rcc_backup_registers/rcc_backup_registers.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/rcc_backup_registers/rcc_backup_registers.cpp Fri Aug 24 08:58:48 2018 +0000 @@ -0,0 +1,34 @@ +/* + * rcc_backup_registers.cpp - Interface functions for writing to back-up registers + * + * Author: Jake Greaves + */ + + +#include "rcc_backup_registers/rcc_backup_registers.h" + + +/*************************************************************** +* Function Name: Rcc_ReadBackupReg +* Description : read from BackupRegister and return its value +****************************************************************/ +uint32_t Rcc_ReadBackupReg( uint32_t BackupRegister ) +{ + RTC_HandleTypeDef RtcHandle; + RtcHandle.Instance = RTC; + return HAL_RTCEx_BKUPRead(&RtcHandle, BackupRegister); +} + +/*************************************************************** +* Function Name: Rcc_WriteBackupReg +* Description : write data to BackupRegister +****************************************************************/ +void Rcc_WriteBackupReg( uint32_t BackupRegister, uint32_t data ) +{ + RTC_HandleTypeDef RtcHandle; + RtcHandle.Instance = RTC; + HAL_PWR_EnableBkUpAccess(); + HAL_RTCEx_BKUPWrite(&RtcHandle, BackupRegister, data); + HAL_PWR_DisableBkUpAccess(); +} +