diff --git a/Makefile b/Makefile index 7e4b902..e81e396 100644 --- a/Makefile +++ b/Makefile @@ -64,6 +64,7 @@ src/leddrv.c \ src/button.c \ src/bmlist.c \ src/ble/profile/legacy.c \ +src/ble/profile/batt.c \ src/ble/profile/devinfo.c \ src/ble/setup.c \ src/ble/peripheral.c \ @@ -79,6 +80,7 @@ src/xbm.c \ src/resource.c \ src/animation.c \ src/font.c \ +src/power.c \ # ASM sources diff --git a/src/ble/profile.h b/src/ble/profile.h index bec1fa1..1472a3d 100644 --- a/src/ble/profile.h +++ b/src/ble/profile.h @@ -3,5 +3,6 @@ int legacy_registerService(); int devInfo_registerService(); +int batt_registerService(); #endif /* __BLE_UART_SERVICE_H__ */ diff --git a/src/ble/profile/batt.c b/src/ble/profile/batt.c new file mode 100644 index 0000000..09b1a1e --- /dev/null +++ b/src/ble/profile/batt.c @@ -0,0 +1,52 @@ +#include "utils.h" + +#include "../../power.h" + +static const uint16_t ServiceUUID = 0x180F; +static const gattAttrType_t service = {2, (uint8_t *)&ServiceUUID}; + +static const uint16_t battLv_CharUUID = 0x2A19; +static uint8 battLv_CharProps = GATT_PROP_READ; +static uint8 battLv_Val[1]; + +static gattAttribute_t attr_table[] = { + ATTR_DECLAR(primaryServiceUUID, 2, GATT_PERMIT_READ, &service), + + CHAR_DECLAR(&battLv_CharProps), + CHAR_VAL_DECLAR(&battLv_CharUUID, 2, GATT_PERMIT_READ, battLv_Val), +}; + +static bStatus_t read_handler(uint16_t connHandle, gattAttribute_t *pAttr, + uint8_t *p_value, uint16_t *pLen, uint16_t offset, + uint16_t maxLen, uint8_t method) +{ + uint16_t uuid = BUILD_UINT16(pAttr->type.uuid[0], pAttr->type.uuid[1]); + + if (uuid != battLv_CharUUID) { + *pLen = 0; + return ATT_ERR_ATTR_NOT_FOUND; + } + + *pLen = 1; + battLv_Val[0] = batt_raw2percent(batt_raw()); + tmos_memcpy(p_value, battLv_Val, *pLen); + + return SUCCESS; +} + +static gattServiceCBs_t service_handlers = { + read_handler, + NULL, + NULL +}; + +int batt_registerService() +{ + uint8 status = SUCCESS; + + status = GATTServApp_RegisterService(attr_table, + GATT_NUM_ATTRS(attr_table), + GATT_MAX_ENCRYPT_KEY_SIZE, + &service_handlers); + return (status); +} \ No newline at end of file diff --git a/src/ble/profile/legacy.c b/src/ble/profile/legacy.c index 2957aa5..92ac3f4 100644 --- a/src/ble/profile/legacy.c +++ b/src/ble/profile/legacy.c @@ -65,7 +65,7 @@ static bStatus_t write_handler(uint16 connHandle, gattAttribute_t *pAttr, return ATT_ERR_ATTR_NOT_FOUND; } -gattServiceCBs_t service_handlers = { +static gattServiceCBs_t service_handlers = { NULL, write_handler, NULL diff --git a/src/main.c b/src/main.c index ab82307..e22b5a3 100644 --- a/src/main.c +++ b/src/main.c @@ -49,8 +49,6 @@ enum MODES { #define SCAN_BOOTLD_BTN (1 << 3) #define BLE_NEXT_STEP (1 << 4) -#define CHARGE_STT_PIN GPIO_Pin_0 // PA0 - static tmosTaskID common_taskid = INVALID_TASK_ID ; volatile uint16_t fb[LED_COLS] = {0}; @@ -108,24 +106,6 @@ void load_bmlist() bmlist_drop(curr_bm); } -void poweroff() -{ - // Stop wasting energy - GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_Floating); - GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_Floating); - - // Configure wake-up - GPIOA_ModeCfg(KEY1_PIN, GPIO_ModeIN_PD); - GPIOA_ITModeCfg(KEY1_PIN, GPIO_ITMode_RiseEdge); - GPIOA_ModeCfg(CHARGE_STT_PIN, GPIO_ModeIN_PU); - GPIOA_ITModeCfg(CHARGE_STT_PIN, GPIO_ITMode_FallEdge); - PFIC_EnableIRQ(GPIO_A_IRQn); - PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Long_Delay); - - /* Good bye */ - LowPower_Shutdown(0); -} - static uint16_t common_tasks(tmosTaskID task_id, uint16_t events) { static int marque_step, flash_step; @@ -229,6 +209,7 @@ void ble_setup() devInfo_registerService(); legacy_registerService(); + batt_registerService(); } static void usb_receive(uint8_t *buf, uint16_t len) @@ -328,37 +309,6 @@ static void debug_init() UART1_BaudRateCfg(921600); } -uint16_t adcBuff[40]; -static int read_batt_raw() -{ - int ret = 0; - /* adc 1 - pa5 */ - PRINT("\n2.Single channel sampling...\n"); - GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_Floating); - ADC_ExtSingleChSampInit(SampleFreq_3_2, ADC_PGA_0); - - int16_t RoughCalib_Value = ADC_DataCalib_Rough(); - PRINT("RoughCalib_Value =%d \n", RoughCalib_Value); - - ADC_ChannelCfg(1); - - for(int i = 0; i < 20; i++) { - adcBuff[i] = ADC_ExcutSingleConver() + RoughCalib_Value; - ret += adcBuff[i]; - } - for(int i = 0; i < 20; i++) { - PRINT("%d \n", adcBuff[i]); - } - - return ret / 20; -} - -static int is_charging() -{ - GPIOA_ModeCfg(CHARGE_STT_PIN, GPIO_ModeIN_PU); - return GPIOA_ReadPortPin(CHARGE_STT_PIN) == 0; -} - static void disp_bat_stt(int bat_percent, int col, int row) { if (bat_percent < 0) { @@ -373,30 +323,6 @@ static void disp_bat_stt(int bat_percent, int col, int row) } } -#define ZERO_PERCENT_THRES (3.3) -#define _100_PERCENT_THRES (4.2) -#define ADC_MAX_VAL (4096.0) // 12 bit -#define ADC_MAX_VOLT (2.1) // Volt -#define R1 (182.0) // kOhm -#define R2 (100.0) // kOhm -#define PERCENT_RANGE (_100_PERCENT_THRES - ZERO_PERCENT_THRES) -#define VOLT_DIV(v) ((v) / (R1 + R2) * R2) // Voltage divider -#define VOLT_DIV_INV(v) ((v) / R2 * (R1 + R2)) // .. Inverse -#define ADC2VOLT(raw) ((raw) / ADC_MAX_VAL * ADC_MAX_VOLT) -#define VOLT2ADC(volt) ((volt) / ADC_MAX_VOLT * ADC_MAX_VAL) - -static int bat_raw2percent(int r) -{ - float vadc = ADC2VOLT(r); - float vbat = VOLT_DIV_INV(vadc); - float strip = vbat - ZERO_PERCENT_THRES; - if (strip < PERCENT_RANGE) { - // Negative values meaning the battery is not connected or died - return (int)(strip / PERCENT_RANGE * 100.0); - } - return 100; -} - static void fb_putchar(char c, int col, int row) { for (int i=0; i < 6; i++) { @@ -419,9 +345,9 @@ static void disp_charging() { int blink = 0; while (mode == BOOT) { - int percent = bat_raw2percent(read_batt_raw()); + int percent = batt_raw2percent(batt_raw()); - if (is_charging()) { + if (charging_status()) { disp_bat_stt(blink ? percent : 0, 2, 2); if (ani_xbm_next_frame(&fabm_xbm, fb, 16, 0) == 0) { fb_puts(VERSION_ABBR, sizeof(VERSION_ABBR), 16, 2); diff --git a/src/power.c b/src/power.c new file mode 100644 index 0000000..0192f8a --- /dev/null +++ b/src/power.c @@ -0,0 +1,74 @@ +#include + +#include "power.h" +#include "button.h" + +void poweroff() +{ + // Stop wasting energy + GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_Floating); + GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_Floating); + + // Configure wake-up + GPIOA_ModeCfg(KEY1_PIN, GPIO_ModeIN_PD); + GPIOA_ITModeCfg(KEY1_PIN, GPIO_ITMode_RiseEdge); + GPIOA_ModeCfg(CHARGE_STT_PIN, GPIO_ModeIN_PU); + GPIOA_ITModeCfg(CHARGE_STT_PIN, GPIO_ITMode_FallEdge); + PFIC_EnableIRQ(GPIO_A_IRQn); + PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Long_Delay); + + /* Good bye */ + LowPower_Shutdown(0); +} + +int batt_raw() +{ + int ret = 0; + GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_Floating); + ADC_ExtSingleChSampInit(SampleFreq_3_2, ADC_PGA_0); + + int16_t adc_calib = ADC_DataCalib_Rough(); + PRINT("RoughCalib_Value = %d \n", adc_calib); + + ADC_ChannelCfg(1); + + PRINT("ADC reading: \n"); + uint16_t buf[20]; + for(int i = 0; i < 20; i++) { + uint16_t adc = ADC_ExcutSingleConver() + adc_calib; + ret += adc; + PRINT("%d \n", adc); + } + + return ret / 20; +} + +int charging_status() +{ + GPIOA_ModeCfg(CHARGE_STT_PIN, GPIO_ModeIN_PU); + return GPIOA_ReadPortPin(CHARGE_STT_PIN) == 0; +} + +#define ZERO_PERCENT_THRES (3.3) +#define _100_PERCENT_THRES (4.2) +#define ADC_MAX_VAL (4096.0) // 12 bit +#define ADC_MAX_VOLT (2.1) // Volt +#define R1 (182.0) // kOhm +#define R2 (100.0) // kOhm +#define PERCENT_RANGE (_100_PERCENT_THRES - ZERO_PERCENT_THRES) +#define VOLT_DIV(v) ((v) / (R1 + R2) * R2) // Voltage divider +#define VOLT_DIV_INV(v) ((v) / R2 * (R1 + R2)) // .. Inverse +#define ADC2VOLT(raw) ((raw) / ADC_MAX_VAL * ADC_MAX_VOLT) +#define VOLT2ADC(volt) ((volt) / ADC_MAX_VOLT * ADC_MAX_VAL) + +int batt_raw2percent(int r) +{ + float vadc = ADC2VOLT(r); + float vbat = VOLT_DIV_INV(vadc); + float strip = vbat - ZERO_PERCENT_THRES; + if (strip < PERCENT_RANGE) { + // Negative values meaning the battery is not connected or died + return (int)(strip / PERCENT_RANGE * 100.0); + } + return 100; +} diff --git a/src/power.h b/src/power.h index 4d418a0..985fd42 100644 --- a/src/power.h +++ b/src/power.h @@ -1,11 +1,16 @@ #ifndef __RESET_H__ #define __RESET_H__ +#define CHARGE_STT_PIN GPIO_Pin_0 // PA0 + static inline void reset_jump() { asm volatile("j 0x00"); } void poweroff(); +int batt_raw(); +int charging_status(); +int batt_raw2percent(int r); #endif /* __RESET_H__ */