From 4da435376d968df98d27d1cde1c953aab532d807 Mon Sep 17 00:00:00 2001 From: Glenn Ruben Bakke Date: Wed, 11 Jan 2017 22:12:41 +0100 Subject: [PATCH] nrf5/hal: Updating hal_adc* with more api functions. --- nrf5/hal/hal_adc.c | 109 ++++++++++++++++++++++++++++++++++++++++++++ nrf5/hal/hal_adc.h | 24 +++++++++- nrf5/hal/hal_adce.c | 14 ++++++ 3 files changed, 145 insertions(+), 2 deletions(-) diff --git a/nrf5/hal/hal_adc.c b/nrf5/hal/hal_adc.c index 413a3f1bb3..fb46961404 100644 --- a/nrf5/hal/hal_adc.c +++ b/nrf5/hal/hal_adc.c @@ -24,12 +24,121 @@ * THE SOFTWARE. */ +#include #include "mphalport.h" #include "hal_adc.h" #ifdef HAL_ADC_MODULE_ENABLED +#define ADC_REF_VOLTAGE_IN_MILLIVOLTS (1200) // Reference voltage (in milli volts) used by ADC while doing conversion. +#define ADC_PRE_SCALING_COMPENSATION (3) // The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage. +#define DIODE_FWD_VOLT_DROP_MILLIVOLTS (270) // Typical forward voltage drop of the diode (Part no: SD103ATW-7-F) that is connected in series with the voltage supply. This is the voltage drop when the forward current is 1mA. Source: Data sheet of 'SURFACE MOUNT SCHOTTKY BARRIER DIODE ARRAY' available at www.diodes.com. + +#define ADC_RESULT_IN_MILLI_VOLTS(ADC_VALUE)\ + ((((ADC_VALUE) * ADC_REF_VOLTAGE_IN_MILLIVOLTS) / 255) * ADC_PRE_SCALING_COMPENSATION) + +static const uint32_t hal_adc_input_lookup[] = { + ADC_CONFIG_PSEL_AnalogInput0 << ADC_CONFIG_PSEL_Pos, + ADC_CONFIG_PSEL_AnalogInput1 << ADC_CONFIG_PSEL_Pos, + ADC_CONFIG_PSEL_AnalogInput2 << ADC_CONFIG_PSEL_Pos, + ADC_CONFIG_PSEL_AnalogInput3 << ADC_CONFIG_PSEL_Pos, + ADC_CONFIG_PSEL_AnalogInput4 << ADC_CONFIG_PSEL_Pos, + ADC_CONFIG_PSEL_AnalogInput5 << ADC_CONFIG_PSEL_Pos, + ADC_CONFIG_PSEL_AnalogInput6 << ADC_CONFIG_PSEL_Pos, + ADC_CONFIG_PSEL_AnalogInput7 << ADC_CONFIG_PSEL_Pos +}; + + +static uint8_t battery_level_in_percent(const uint16_t mvolts) +{ + uint8_t battery_level; + + if (mvolts >= 3000) { + battery_level = 100; + } else if (mvolts > 2900) { + battery_level = 100 - ((3000 - mvolts) * 58) / 100; + } else if (mvolts > 2740) { + battery_level = 42 - ((2900 - mvolts) * 24) / 160; + } else if (mvolts > 2440) { + battery_level = 18 - ((2740 - mvolts) * 12) / 300; + } else if (mvolts > 2100) { + battery_level = 6 - ((2440 - mvolts) * 6) / 340; + } else { + battery_level = 0; + } + + return battery_level; +} + + void hal_adc_init(HAL_ADC_Type * p_instance, hal_adc_init_t const * p_adc_init) { + + while (p_instance->ENABLE && p_instance->BUSY) + { + // spin loop if another user is in progress of sampling + } + + p_instance->INTENSET = ADC_INTENSET_END_Msk; + p_instance->CONFIG = (ADC_CONFIG_RES_8bit << ADC_CONFIG_RES_Pos) + | (ADC_CONFIG_INPSEL_AnalogInputTwoThirdsPrescaling << ADC_CONFIG_INPSEL_Pos) + | (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) + | (hal_adc_input_lookup[p_adc_init->channel]) + | (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos); +} + +void hal_adc_start(HAL_ADC_Type * p_instance) { + p_instance->ENABLE = ADC_ENABLE_ENABLE_Enabled; +} + +void hal_adc_stop(HAL_ADC_Type * p_instance) { + p_instance->ENABLE = ADC_ENABLE_ENABLE_Disabled; +} + +uint8_t hal_adc_value(HAL_ADC_Type * p_instance) { + + p_instance->EVENTS_END = 0; + p_instance->TASKS_START = 1; + + while (!p_instance->EVENTS_END) { + ; + } + + uint8_t adc_result = p_instance->RESULT; + + p_instance->EVENTS_END = 0; + p_instance->TASKS_STOP = 1; + + return adc_result; +} + +uint8_t hal_adc_battery_level(HAL_ADC_Type * p_instance) { + p_instance->INTENSET = ADC_INTENSET_END_Msk; + p_instance->CONFIG = (ADC_CONFIG_RES_8bit << ADC_CONFIG_RES_Pos) + | (ADC_CONFIG_INPSEL_SupplyOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) + | (ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos) + | (ADC_CONFIG_PSEL_Disabled << ADC_CONFIG_PSEL_Pos) + | (ADC_CONFIG_EXTREFSEL_None << ADC_CONFIG_EXTREFSEL_Pos); + + p_instance->EVENTS_END = 0; + p_instance->ENABLE = ADC_ENABLE_ENABLE_Enabled; + + p_instance->EVENTS_END = 0; + p_instance->TASKS_START = 1; + + while (!p_instance->EVENTS_END) { + ; + } + + uint8_t adc_result; + uint16_t batt_lvl_in_milli_volts; + + p_instance->EVENTS_END = 0; + adc_result = p_instance->RESULT; + p_instance->TASKS_STOP = 1; + + batt_lvl_in_milli_volts = ADC_RESULT_IN_MILLI_VOLTS(adc_result) + DIODE_FWD_VOLT_DROP_MILLIVOLTS; + return battery_level_in_percent(batt_lvl_in_milli_volts); + } #endif // HAL_ADC_MODULE_ENABLED diff --git a/nrf5/hal/hal_adc.h b/nrf5/hal/hal_adc.h index 1dbea697b9..8fd19d14b7 100644 --- a/nrf5/hal/hal_adc.h +++ b/nrf5/hal/hal_adc.h @@ -27,26 +27,38 @@ #ifndef HAL_ADC_H__ #define HAL_ADC_H__ +#include + #include "nrf.h" #if NRF51 #define ADC_IRQ_NUM ADC_IRQn -#define ADC_BASE(x) ((NRF_ADC_Type *)NRF_ADC_BASE) +#define ADC_BASE ((NRF_ADC_Type *)NRF_ADC_BASE) #define HAL_ADC_Type NRF_ADC_Type #else #define ADC_IRQ_NUM SAADC_IRQn -#define ADC_BASE(x) ((NRF_SAADC_Type *)NRF_SAADC_BASE) +#define ADC_BASE ((NRF_SAADC_Type *)NRF_SAADC_BASE) #define HAL_ADC_Type NRF_SAADC_Type #endif +typedef enum { + HAL_ADC_CHANNEL_2 = 2, + HAL_ADC_CHANNEL_3, + HAL_ADC_CHANNEL_4, + HAL_ADC_CHANNEL_5, + HAL_ADC_CHANNEL_6, + HAL_ADC_CHANNEL_7, +} hal_adc_channel_t; + /** * @brief ADC Configuration Structure definition */ typedef struct { + hal_adc_channel_t channel; } hal_adc_init_t; /** @@ -60,4 +72,12 @@ typedef struct __ADC_HandleTypeDef void hal_adc_init(HAL_ADC_Type * p_instance, hal_adc_init_t const * p_adc_init); +void hal_adc_start(HAL_ADC_Type * p_instance); + +void hal_adc_stop(HAL_ADC_Type * p_instance); + +uint8_t hal_adc_value(HAL_ADC_Type * p_instance); + +uint8_t hal_adc_battery_level(HAL_ADC_Type * p_instance); + #endif // HAL_ADC_H__ diff --git a/nrf5/hal/hal_adce.c b/nrf5/hal/hal_adce.c index b78afddbe8..21f1a7e8ee 100644 --- a/nrf5/hal/hal_adce.c +++ b/nrf5/hal/hal_adce.c @@ -32,4 +32,18 @@ void hal_adc_init(HAL_ADC_Type * p_instance, hal_adc_init_t const * p_adc_init) { } +void hal_adc_start(HAL_ADC_Type * p_instance) { +} + +void hal_adc_stop(HAL_ADC_Type * p_instance) { +} + +uint8_t hal_adc_value(HAL_ADC_Type * p_instance) { + return 0; +} + +uint8_t hal_adc_battery_level(HAL_ADC_Type * p_instance) { + return 0; +} + #endif // HAL_ADCE_MODULE_ENABLED