HEXIWEAR Battery driver and example.
Dependencies: Hexi_OLED_SSD1351
Diff: Hexi_Battery/hexi_battery.cpp
- Revision:
- 0:579e15da3834
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Hexi_Battery/hexi_battery.cpp Sat Oct 29 17:13:31 2016 +0000 @@ -0,0 +1,525 @@ + +#include "hexi_battery.h" +#include "mbed.h" + +#define BITBAND_ACCESS32(Reg,Bit) (*((uint32_t volatile*)(0x42000000u + (32u*((uintptr_t)(Reg) - (uintptr_t)0x40000000u)) + (4u*((uintptr_t)(Bit)))))) +#define ADC_SC1_REG(base,index) ((base)->SC1[index]) +#define ADC_WR_SC1(base, index, value) (ADC_SC1_REG(base, index) = (value)) +#define ADC_BRD_SC1_COCO(base, index) (BITBAND_ACCESS32(&ADC_SC1_REG(base, index), ADC_SC1_COCO_SHIFT)) +#define ADC_RD_R_D(base, index) ((ADC_R_REG(base, index) & ADC_R_D_MASK) >> ADC_R_D_SHIFT) +#define ADC_BRD_R_D(base, index) (ADC_RD_R_D(base, index)) +#define ADC_R_REG(base,index) ((base)->R[index]) +#define SIM_BWR_SCGC_BIT(base, index, value) (BITBAND_ACCESS32(&SIM_SCGC_BIT_REG((base), (index)), SIM_SCGC_BIT_SHIFT(index)) = (uint32_t)(value)) +#define SIM_SCGC_BIT_SHIFT(index) ((uint32_t)(index) & ((1U << 5) - 1U)) +#define SIM_SCGC_BIT_REG(base, index) (*((volatile uint32_t *)&SIM_SCGC1_REG(base) + (((uint32_t)(index) >> 5) - 0U))) +#define SIM_SCGC1_REG(base) ((base)->SCGC1) + +#define ADC_RD_CFG1(base) (ADC_CFG1_REG(base)) +#define ADC_WR_CFG1(base, value) (ADC_CFG1_REG(base) = (value)) + +#define ADC_CFG1_REG(base) ((base)->CFG1) +#define ADC_WR_CFG2(base, value) (ADC_CFG2_REG(base) = (value)) +#define ADC_CFG2_REG(base) ((base)->CFG2) + +#define ADC_WR_CV1(base, value) (ADC_CV1_REG(base) = (value)) +#define ADC_CV1_REG(base) ((base)->CV1) +#define ADC_WR_CV2(base, value) (ADC_CV2_REG(base) = (value)) +#define ADC_CV2_REG(base) ((base)->CV2) + +#define ADC_WR_SC2(base, value) (ADC_SC2_REG(base) = (value)) +#define ADC_SC2_REG(base) ((base)->SC2) + +#define ADC_WR_SC3(base, value) (ADC_SC3_REG(base) = (value)) +#define ADC_SC3_REG(base) ((base)->SC3) + +#define ADC_RD_SC2(base) (ADC_SC2_REG(base)) +#define ADC_RD_CFG2(base) (ADC_CFG2_REG(base)) +#define ADC_CFG2_REG(base) ((base)->CFG2) + +#define ADC_RD_SC3(base) (ADC_SC3_REG(base)) +#define ADC_SC3_REG(base) ((base)->SC3) + +#define ADC_INSTANCE_COUNT (2U) /*!< Number of instances of the ADC module. */ +const IRQn_Type g_adcIrqId[ADC_INSTANCE_COUNT] = ADC_IRQS; + +typedef enum _adc16_chn { + kAdc16Chn0 = 0U, /*!< AD0. */ + kAdc16Chn1 = 1U, /*!< AD1. */ + kAdc16Chn2 = 2U, /*!< AD2. */ + kAdc16Chn3 = 3U, /*!< AD3. */ + kAdc16Chn4 = 4U, /*!< AD4. */ + kAdc16Chn5 = 5U, /*!< AD5. */ + kAdc16Chn6 = 6U, /*!< AD6. */ + kAdc16Chn7 = 7U, /*!< AD6. */ + kAdc16Chn8 = 8U, /*!< AD8. */ + kAdc16Chn9 = 9U, /*!< AD9. */ + kAdc16Chn10 = 10U, /*!< AD10. */ + kAdc16Chn11 = 11U, /*!< AD11. */ + kAdc16Chn12 = 12U, /*!< AD12. */ + kAdc16Chn13 = 13U, /*!< AD13. */ + kAdc16Chn14 = 14U, /*!< AD14. */ + kAdc16Chn15 = 15U, /*!< AD15. */ + kAdc16Chn16 = 16U, /*!< AD16. */ + kAdc16Chn17 = 17U, /*!< AD17. */ + kAdc16Chn18 = 18U, /*!< AD18. */ + kAdc16Chn19 = 19U, /*!< AD19. */ + kAdc16Chn20 = 20U, /*!< AD20. */ + kAdc16Chn21 = 21U, /*!< AD21. */ + kAdc16Chn22 = 22U, /*!< AD22. */ + kAdc16Chn23 = 23U, /*!< AD23. */ + kAdc16Chn24 = 24U, /*!< AD24. */ + kAdc16Chn25 = 25U, /*!< AD25. */ + kAdc16Chn26 = 26U, /*!< AD26. */ + kAdc16Chn27 = 27U, /*!< AD27. */ + kAdc16Chn28 = 28U, /*!< AD28. */ + kAdc16Chn29 = 29U, /*!< AD29. */ + kAdc16Chn30 = 30U, /*!< AD30. */ + kAdc16Chn31 = 31U, /*!< AD31. */ + + kAdc16Chn0d = kAdc16Chn0, /*!< DAD0. */ + kAdc16Chn1d = kAdc16Chn1, /*!< DAD1. */ + kAdc16Chn2d = kAdc16Chn2, /*!< DAD2. */ + kAdc16Chn3d = kAdc16Chn3, /*!< DAD3. */ + kAdc16Chn4a = kAdc16Chn4, /*!< AD4a. */ + kAdc16Chn5a = kAdc16Chn5, /*!< AD5a. */ + kAdc16Chn6a = kAdc16Chn6, /*!< AD6a. */ + kAdc16Chn7a = kAdc16Chn7, /*!< AD7a. */ + kAdc16Chn4b = kAdc16Chn4, /*!< AD4b. */ + kAdc16Chn5b = kAdc16Chn5, /*!< AD5b. */ + kAdc16Chn6b = kAdc16Chn6, /*!< AD6b. */ + kAdc16Chn7b = kAdc16Chn7 /*!< AD7b. */ + +} adc16_chn_t; + +typedef enum _adc16_status { + kStatus_ADC16_Success = 0U, /*!< Success. */ + kStatus_ADC16_InvalidArgument = 1U, /*!< Invalid argument existed. */ + kStatus_ADC16_Failed = 2U /*!< Execution failed. */ +} adc16_status_t; + +typedef struct Adc16ChnConfig { + adc16_chn_t chnIdx; /*!< Select the sample channel index. */ + bool convCompletedIntEnable; /*!< Enable the conversion complete interrupt. */ +#if FSL_FEATURE_ADC16_HAS_DIFF_MODE + bool diffConvEnable; /*!< Enable the differential conversion. */ +#endif /** FSL_FEATURE_ADC16_HAS_DIFF_MODE */ +} adc16_chn_config_t; + +extern const adc16_chn_config_t BATTERY_ADC_ChnConfig; + +const adc16_chn_config_t BATTERY_ADC_ChnConfig = { + .chnIdx = kAdc16Chn16, + .convCompletedIntEnable = false, + .diffConvEnable = false +}; + +ADC_Type * const g_adcBase[] = ADC_BASE_PTRS; + + +void ADC16_HAL_ConfigChn(ADC_Type * base, uint32_t chnGroup, const adc16_chn_config_t *configPtr) +{ + uint16_t tmp = 0U; + + /** Interrupt enable. */ + if (configPtr->convCompletedIntEnable) { + tmp |= ADC_SC1_AIEN_MASK; + } + + /** Differential mode enable. */ +#if FSL_FEATURE_ADC16_HAS_DIFF_MODE + if (configPtr->diffConvEnable) { + tmp |= ADC_SC1_DIFF_MASK; + } +#endif /** FSL_FEATURE_ADC16_HAS_DIFF_MODE */ + + /** Input channel select. */ + tmp |= ADC_SC1_ADCH((uint32_t)(configPtr->chnIdx)); + + ADC_WR_SC1(base, chnGroup, tmp); +} + +adc16_status_t ADC16_DRV_ConfigConvChn(uint32_t instance, + uint32_t chnGroup, const adc16_chn_config_t *configPtr) +{ + ADC_Type * base = g_adcBase[instance]; + + if (!configPtr) { + return kStatus_ADC16_InvalidArgument; + } + + ADC16_HAL_ConfigChn(base, chnGroup, configPtr); + + return kStatus_ADC16_Success; +} + +static inline bool ADC16_HAL_GetChnConvCompletedFlag(ADC_Type * base, uint32_t chnGroup) +{ + return (1U == ADC_BRD_SC1_COCO(base, chnGroup) ); +} + +void ADC16_DRV_WaitConvDone(uint32_t instance, uint32_t chnGroup) +{ + ADC_Type * base = g_adcBase[instance]; + + while ( !ADC16_HAL_GetChnConvCompletedFlag(base, chnGroup) ) + {} +} + +static inline uint16_t ADC16_HAL_GetChnConvValue(ADC_Type * base, uint32_t chnGroup ) +{ + return (uint16_t)(ADC_BRD_R_D(base, chnGroup) ); +} + +uint16_t ADC16_DRV_GetConvValueRAW(uint32_t instance, uint32_t chnGroup) +{ + + ADC_Type * base = g_adcBase[instance]; + + return ADC16_HAL_GetChnConvValue(base, chnGroup); +} + +int16_t ADC16_DRV_GetConvValueSigned(uint32_t instance, uint32_t chnGroup) +{ + return (int16_t)ADC16_DRV_GetConvValueRAW(instance, chnGroup); +} + +void ADC16_DRV_PauseConv(uint32_t instance, uint32_t chnGroup) +{ + adc16_chn_config_t configStruct; + + configStruct.chnIdx = kAdc16Chn31; + configStruct.convCompletedIntEnable = false; +#if FSL_FEATURE_ADC16_HAS_DIFF_MODE + configStruct.diffConvEnable = false; +#endif + ADC16_DRV_ConfigConvChn(instance, chnGroup, &configStruct); +} + +typedef enum _adc16_clk_divider { + kAdc16ClkDividerOf1 = 0U, /*!< For divider 1 from the input clock to ADC16. @internal gui name="1" */ + kAdc16ClkDividerOf2 = 1U, /*!< For divider 2 from the input clock to ADC16. @internal gui name="2" */ + kAdc16ClkDividerOf4 = 2U, /*!< For divider 4 from the input clock to ADC16. @internal gui name="4" */ + kAdc16ClkDividerOf8 = 3U /*!< For divider 8 from the input clock to ADC16. @internal gui name="8" */ +} adc16_clk_divider_t; + +typedef enum _adc16_resolution { + kAdc16ResolutionBitOf8or9 = 0U, + /*!< 8-bit for single end sample, or 9-bit for differential sample. @internal gui name="" */ + kAdc16ResolutionBitOfSingleEndAs8 = kAdc16ResolutionBitOf8or9, /*!< 8-bit for single end sample. @internal gui name="8 bit in single mode" */ + kAdc16ResolutionBitOfDiffModeAs9 = kAdc16ResolutionBitOf8or9, /*!< 9-bit for differential sample. @internal gui name="9 bit in differential mode" */ + + kAdc16ResolutionBitOf12or13 = 1U, + /*!< 12-bit for single end sample, or 13-bit for differential sample. @internal gui name="" */ + kAdc16ResolutionBitOfSingleEndAs12 = kAdc16ResolutionBitOf12or13, /*!< 12-bit for single end sample. @internal gui name="12 bit in single mode" */ + kAdc16ResolutionBitOfDiffModeAs13 = kAdc16ResolutionBitOf12or13, /*!< 13-bit for differential sample. @internal gui name="13 bit in differential mode" */ + + kAdc16ResolutionBitOf10or11 = 2U, + /*!< 10-bit for single end sample, or 11-bit for differential sample. @internal gui name="" */ + kAdc16ResolutionBitOfSingleEndAs10 = kAdc16ResolutionBitOf10or11, /*!< 10-bit for single end sample. @internal gui name="10 bit in single mode" */ + kAdc16ResolutionBitOfDiffModeAs11 = kAdc16ResolutionBitOf10or11 /*!< 11-bit for differential sample. @internal gui name="11 bit in differential mode" */ +#if (FSL_FEATURE_ADC16_MAX_RESOLUTION >= 16U) + , kAdc16ResolutionBitOf16 = 3U, + /*!< 16-bit for both single end sample and differential sample. @internal gui name="16-bit" */ + kAdc16ResolutionBitOfSingleEndAs16 = kAdc16ResolutionBitOf16, /*!< 16-bit for single end sample. @internal gui name="" */ + kAdc16ResolutionBitOfDiffModeAs16 = kAdc16ResolutionBitOf16 /*!< 16-bit for differential sample. @internal gui name="" */ + +#endif /** FSL_FEATURE_ADC16_MAX_RESOLUTION */ +} adc16_resolution_t; + +typedef enum _adc16_long_sample_cycle { + kAdc16LongSampleCycleOf24 = 0U, /*!< 20 extra ADCK cycles, 24 ADCK cycles total. */ + kAdc16LongSampleCycleOf16 = 1U, /*!< 12 extra ADCK cycles, 16 ADCK cycles total. */ + kAdc16LongSampleCycleOf10 = 2U, /*!< 6 extra ADCK cycles, 10 ADCK cycles total. */ + kAdc16LongSampleCycleOf4 = 3U /*!< 2 extra ADCK cycles, 6 ADCK cycles total. */ +} adc16_long_sample_cycle_t; + +typedef enum _adc16_clk_src_mode { + kAdc16ClkSrcOfBusClk = 0U, /*!< For input as bus clock. @internal gui name="Bus clock" */ + kAdc16ClkSrcOfAltClk2 = 1U, /*!< For input as alternate clock 2 (AltClk2). @internal gui name="Alternate clock 2" */ + kAdc16ClkSrcOfAltClk = 2U, /*!< For input as alternate clock (ALTCLK). @internal gui name="Alternate clock 1" */ + kAdc16ClkSrcOfAsynClk = 3U /*!< For input as asynchronous clock (ADACK). @internal gui name="Asynchronous clock" */ +} adc16_clk_src_mode_t; + +typedef enum _adc16_ref_volt_src { + kAdc16RefVoltSrcOfVref = 0U, /*!< For external pins pair of VrefH and VrefL. @internal gui name="Vref pair" */ + kAdc16RefVoltSrcOfValt = 1U /*!< For alternate reference pair of ValtH and ValtL. @internal gui name="Valt pair" */ +} adc16_ref_volt_src_t; + +typedef struct Adc16ConverterConfig { + bool lowPowerEnable; /*!< Enable low power. @internal gui name="Low power mode" id="LowPowerMode" */ + adc16_clk_divider_t clkDividerMode; /*!< Select the divider of input clock source. @internal gui name="Clock divider" id="ClockDivider" */ + bool longSampleTimeEnable; /*!< Enable the long sample time. @internal gui name="Long sample time" id="LongSampleTime" */ + adc16_resolution_t resolution; /*!< Select the sample resolution mode. @internal gui name="Resolution" id="Resolution" */ + adc16_clk_src_mode_t clkSrc; /*!< Select the input clock source to converter. @internal gui name="Clock source" id="ClockSource" */ + bool asyncClkEnable; /*!< Enable the asynchronous clock inside the ADC. @internal gui name="Internal async. clock" id="InternalAsyncClock" */ + bool highSpeedEnable; /*!< Enable the high speed mode. @internal gui name="High speed mode" id="HighSpeed" */ + adc16_long_sample_cycle_t longSampleCycleMode; /*!< Select the long sample mode. @internal gui name="Long sample mode" id="LongSampleMode" */ + bool hwTriggerEnable; /*!< Enable hardware trigger function. @internal gui name="Hardware trigger" id="HwTrigger" */ + adc16_ref_volt_src_t refVoltSrc; /*!< Select the reference voltage source. @internal gui name="Voltage reference" id="ReferenceVoltage" */ + bool continuousConvEnable; /*!< Enable continuous conversion mode. @internal gui name="Continuous mode" id="ContinuousMode" */ +#if FSL_FEATURE_ADC16_HAS_DMA + bool dmaEnable; /*!< Enable the DMA for ADC converter. @internal gui name="DMA mode" id="DMASupport" */ +#endif /** FSL_FEATURE_ADC16_HAS_DMA */ +} adc16_converter_config_t; + +const adc16_converter_config_t BATTERY_ADC_InitConfig = { + .lowPowerEnable = false, + .clkDividerMode = kAdc16ClkDividerOf1, + .longSampleTimeEnable = false, + .resolution = kAdc16ResolutionBitOf16, + .clkSrc = kAdc16ClkSrcOfBusClk, + .asyncClkEnable = false, + .highSpeedEnable = true, + .longSampleCycleMode = kAdc16LongSampleCycleOf4, + .hwTriggerEnable = false, + .refVoltSrc = kAdc16RefVoltSrcOfVref, + .continuousConvEnable = false, + .dmaEnable = false, +}; + +#define FSL_SIM_SCGC_BIT(SCGCx, n) (((SCGCx-1U)<<5U) + n) + +typedef enum _sim_clock_gate_name { + kSimClockGateI2c2 = FSL_SIM_SCGC_BIT(1U, 6U), + kSimClockGateUart4 = FSL_SIM_SCGC_BIT(1U, 10U), + kSimClockGateUart5 = FSL_SIM_SCGC_BIT(1U, 11U), + kSimClockGateEnet0 = FSL_SIM_SCGC_BIT(2U, 0U), + kSimClockGateDac0 = FSL_SIM_SCGC_BIT(2U, 12U), + kSimClockGateDac1 = FSL_SIM_SCGC_BIT(2U, 13U), + kSimClockGateSpi2 = FSL_SIM_SCGC_BIT(3U, 12U), + kSimClockGateSdhc0 = FSL_SIM_SCGC_BIT(3U, 17U), + kSimClockGateFtm3 = FSL_SIM_SCGC_BIT(3U, 25U), + kSimClockGateAdc1 = FSL_SIM_SCGC_BIT(3U, 27U), + kSimClockGateEwm0 = FSL_SIM_SCGC_BIT(4U, 1U), + kSimClockGateCmt0 = FSL_SIM_SCGC_BIT(4U, 2U), + kSimClockGateI2c0 = FSL_SIM_SCGC_BIT(4U, 6U), + kSimClockGateI2c1 = FSL_SIM_SCGC_BIT(4U, 7U), + kSimClockGateUart0 = FSL_SIM_SCGC_BIT(4U, 10U), + kSimClockGateUart1 = FSL_SIM_SCGC_BIT(4U, 11U), + kSimClockGateUart2 = FSL_SIM_SCGC_BIT(4U, 12U), + kSimClockGateUart3 = FSL_SIM_SCGC_BIT(4U, 13U), + kSimClockGateUsbfs0 = FSL_SIM_SCGC_BIT(4U, 18U), + kSimClockGateCmp = FSL_SIM_SCGC_BIT(4U, 19U), + kSimClockGateVref0 = FSL_SIM_SCGC_BIT(4U, 20U), + kSimClockGateLptmr0 = FSL_SIM_SCGC_BIT(5U, 0U), + kSimClockGatePortA = FSL_SIM_SCGC_BIT(5U, 9U), + kSimClockGatePortB = FSL_SIM_SCGC_BIT(5U, 10U), + kSimClockGatePortC = FSL_SIM_SCGC_BIT(5U, 11U), + kSimClockGatePortD = FSL_SIM_SCGC_BIT(5U, 12U), + kSimClockGatePortE = FSL_SIM_SCGC_BIT(5U, 13U), + kSimClockGateFtf0 = FSL_SIM_SCGC_BIT(6U, 0U), + kSimClockGateDmamux0 = FSL_SIM_SCGC_BIT(6U, 1U), + kSimClockGateFlexcan0 = FSL_SIM_SCGC_BIT(6U, 4U), + kSimClockGateRnga0 = FSL_SIM_SCGC_BIT(6U, 9U), + kSimClockGateSpi0 = FSL_SIM_SCGC_BIT(6U, 12U), + kSimClockGateSpi1 = FSL_SIM_SCGC_BIT(6U, 13U), + kSimClockGateSai0 = FSL_SIM_SCGC_BIT(6U, 15U), + kSimClockGateCrc0 = FSL_SIM_SCGC_BIT(6U, 18U), + kSimClockGateUsbdcd0 = FSL_SIM_SCGC_BIT(6U, 21U), + kSimClockGatePdb0 = FSL_SIM_SCGC_BIT(6U, 22U), + kSimClockGatePit0 = FSL_SIM_SCGC_BIT(6U, 23U), + kSimClockGateFtm0 = FSL_SIM_SCGC_BIT(6U, 24U), + kSimClockGateFtm1 = FSL_SIM_SCGC_BIT(6U, 25U), + kSimClockGateFtm2 = FSL_SIM_SCGC_BIT(6U, 26U), + kSimClockGateAdc0 = FSL_SIM_SCGC_BIT(6U, 27U), + kSimClockGateRtc0 = FSL_SIM_SCGC_BIT(6U, 29U), + kSimClockGateFlexbus0 = FSL_SIM_SCGC_BIT(7U, 0U), + kSimClockGateDma0 = FSL_SIM_SCGC_BIT(7U, 1U), + kSimClockGateMpu0 = FSL_SIM_SCGC_BIT(7U, 2U), +#if (defined(DOXYGEN_OUTPUT) && (DOXYGEN_OUTPUT)) +} sim_clock_gate_name_k64f12_t; +#else +} sim_clock_gate_name_t; +#endif + +static const sim_clock_gate_name_t adcGateTable[] = { + kSimClockGateAdc0, + kSimClockGateAdc1 +}; + +static inline void SIM_HAL_EnableClock(SIM_Type * base, sim_clock_gate_name_t name) +{ + SIM_BWR_SCGC_BIT(base, name, 1U); +} + +void CLOCK_SYS_EnableAdcClock(uint32_t instance) +{ + SIM_HAL_EnableClock(SIM, adcGateTable[instance]); +} + +void ADC16_HAL_Init(ADC_Type * base) +{ + ADC_WR_CFG1(base, 0U); + ADC_WR_CFG2(base, 0U); + ADC_WR_CV1(base, 0U); + ADC_WR_CV2(base, 0U); + ADC_WR_SC2(base, 0U); + ADC_WR_SC3(base, 0U); +#if FSL_FEATURE_ADC16_HAS_PGA + ADC_WR_PGA(base, 0U); +#endif /** FSL_FEATURE_ADC16_HAS_PGA */ +} + +void ADC16_HAL_ConfigConverter(ADC_Type * base, const adc16_converter_config_t *configPtr) +{ + uint16_t cfg1, cfg2, sc2, sc3; + + cfg1 = ADC_RD_CFG1(base); + cfg1 &= ~( ADC_CFG1_ADLPC_MASK + | ADC_CFG1_ADIV_MASK + | ADC_CFG1_ADLSMP_MASK + | ADC_CFG1_MODE_MASK + | ADC_CFG1_ADICLK_MASK ); + + /** Low power mode. */ + if (configPtr->lowPowerEnable) { + cfg1 |= ADC_CFG1_ADLPC_MASK; + } + /** Clock divider. */ + cfg1 |= ADC_CFG1_ADIV(configPtr->clkDividerMode); + /** Long sample time. */ + if (configPtr->longSampleTimeEnable) { + cfg1 |= ADC_CFG1_ADLSMP_MASK; + } + /** Sample resolution mode. */ + cfg1 |= ADC_CFG1_MODE(configPtr->resolution); + /** Clock source input. */ + cfg1 |= ADC_CFG1_ADICLK(configPtr->clkSrc); + + cfg2 = ADC_RD_CFG2(base); + cfg2 &= ~( ADC_CFG2_ADACKEN_MASK + | ADC_CFG2_ADHSC_MASK + | ADC_CFG2_ADLSTS_MASK ); + /** Asynchronous clock output enable. */ + if (configPtr->asyncClkEnable) { + cfg2 |= ADC_CFG2_ADACKEN_MASK; + } + /** High speed configuration. */ + if (configPtr->highSpeedEnable) { + cfg2 |= ADC_CFG2_ADHSC_MASK; + } + /** Long sample time select. */ + cfg2 |= ADC_CFG2_ADLSTS(configPtr->longSampleCycleMode); + + sc2 = ADC_RD_SC2(base); + sc2 &= ~( ADC_SC2_ADTRG_MASK + | ADC_SC2_REFSEL_MASK +#if FSL_FEATURE_ADC16_HAS_DMA + | ADC_SC2_DMAEN_MASK +#endif /** FSL_FEATURE_ADC16_HAS_DMA */ + ); + /** Conversion trigger select. */ + if (configPtr->hwTriggerEnable) { + sc2 |= ADC_SC2_ADTRG_MASK; + } + /** Voltage reference selection. */ + sc2 |= ADC_SC2_REFSEL(configPtr->refVoltSrc); +#if FSL_FEATURE_ADC16_HAS_DMA + /** DMA. */ + if (configPtr->dmaEnable) { + sc2 |= ADC_SC2_DMAEN_MASK; + } +#endif /** FSL_FEATURE_ADC16_HAS_DMA */ + + sc3 = ADC_RD_SC3(base); + sc3 &= ~( ADC_SC3_ADCO_MASK + | ADC_SC3_CALF_MASK ); + /** Continuous conversion enable. */ + if (configPtr->continuousConvEnable) { + sc3 |= ADC_SC3_ADCO_MASK; + } + + ADC_WR_CFG1(base, cfg1); + ADC_WR_CFG2(base, cfg2); + ADC_WR_SC2(base, sc2); + ADC_WR_SC3(base, sc3); +} + +static inline void INT_SYS_EnableIRQ(IRQn_Type irqNumber) +{ + /** call core API to enable the IRQ*/ + NVIC_EnableIRQ(irqNumber); +} + +adc16_status_t ADC16_DRV_Init(uint32_t instance, const adc16_converter_config_t *userConfigPtr) +{ + ADC_Type * base = g_adcBase[instance]; + + if (!userConfigPtr) { + return kStatus_ADC16_InvalidArgument; + } + /** Enable clock for ADC. */ + CLOCK_SYS_EnableAdcClock(instance); + + /** Reset all the register to a known state. */ + ADC16_HAL_Init(base); + ADC16_HAL_ConfigConverter(base, userConfigPtr); + + /** Enable ADC interrupt in NVIC level.*/ + INT_SYS_EnableIRQ(g_adcIrqId[instance] ); + + return kStatus_ADC16_Success; +} + +static uint8_t bat_convert_data(uint16_t input) +{ + uint8_t output = 0; + + uint16_t bat_mvolts = (uint16_t)( ( (float)input * ( 3.3 / 65535.0 ) ) * 1000 ); + + if ( bat_mvolts > 2670 ) { + output = 100; + } + + else if ( bat_mvolts > 2500 ) { + output = (uint8_t)( 50 + 50.0 * ( ( bat_mvolts - 2500 ) / 170.0 ) ); + } else if ( bat_mvolts > 2430 ) { + output = (uint8_t)( 30 + 20.0 * ( ( bat_mvolts - 2430 ) / 70.0 ) ); + } else if ( bat_mvolts > 2370 ) { + output = (uint8_t)( 10 + 20.0 * ( ( bat_mvolts - 2370 ) / 60.0 ) ); + } else { + output = 0; + } + return output; + +} + +HexiwearBattery::HexiwearBattery() +{ + batCharging = new DigitalIn(PTC12); + batSensSwitch = new DigitalOut(PTC14); + ADC16_DRV_Init(0, &BATTERY_ADC_InitConfig); + ADC16_DRV_ConfigConvChn(0, 0U, &BATTERY_ADC_ChnConfig); +} + +HexiwearBattery::~HexiwearBattery() +{ + delete batSensSwitch; + delete batCharging; +} + +void HexiwearBattery::sensorOn() +{ + *batSensSwitch = 0; +}; + + +void HexiwearBattery::sensorOff() +{ + *batSensSwitch = 1; +}; + +bool HexiwearBattery::isBatteryCharging() +{ + return *batCharging == 0; +} + +uint8_t HexiwearBattery::readLevelPercent() +{ + ADC16_DRV_ConfigConvChn( 0, 0, &BATTERY_ADC_ChnConfig); + ADC16_DRV_WaitConvDone ( 0, 0 ); + int16_t result = ADC16_DRV_GetConvValueSigned( 0, 0 ); + ADC16_DRV_PauseConv(0, 0 ); + return bat_convert_data(result); +} +