Compare commits
6 Commits
8a9b805b95
...
beb7a86af1
Author | SHA1 | Date | |
---|---|---|---|
|
beb7a86af1 | ||
|
721db527ce | ||
|
85e5fec2cd | ||
|
622681128c | ||
|
214e174ffc | ||
|
9f574f0486 |
@ -34,6 +34,7 @@ COMPONENTS_$(TARGET) = \
|
|||||||
$(TOP_DIR)/app/app_drivers/libappdrivers$(LIB_EXT) \
|
$(TOP_DIR)/app/app_drivers/libappdrivers$(LIB_EXT) \
|
||||||
$(TOP_DIR)/app/persistency/libpersistency$(LIB_EXT) \
|
$(TOP_DIR)/app/persistency/libpersistency$(LIB_EXT) \
|
||||||
$(TOP_DIR)/app/translation/libtranslation$(LIB_EXT) \
|
$(TOP_DIR)/app/translation/libtranslation$(LIB_EXT) \
|
||||||
|
$(TOP_DIR)/app/translation/libble$(LIB_EXT) \
|
||||||
$(TOP_DIR)/lvgl/liblvgl$(LIB_EXT)
|
$(TOP_DIR)/lvgl/liblvgl$(LIB_EXT)
|
||||||
|
|
||||||
ifeq ($(USE_LIB), 0)
|
ifeq ($(USE_LIB), 0)
|
||||||
|
@ -6,19 +6,107 @@
|
|||||||
#include "wm_timer.h"
|
#include "wm_timer.h"
|
||||||
#include "wm_pwm.h"
|
#include "wm_pwm.h"
|
||||||
|
|
||||||
|
#define INTERRUPT_POLICY (0)
|
||||||
|
#define POLL_POLICY (1)
|
||||||
|
|
||||||
|
#define BATTERY_CONTROLLER_STATUS_DETECTION_POLICY INTERRUPT_POLICY
|
||||||
|
|
||||||
|
/* Battery voltage and ADC */
|
||||||
static int8_t _adc_offset = 0;
|
static int8_t _adc_offset = 0;
|
||||||
|
|
||||||
|
/* Vibration motor timer */
|
||||||
static uint8_t _vibration_motor_timer_id = WM_TIMER_ID_INVALID;
|
static uint8_t _vibration_motor_timer_id = WM_TIMER_ID_INVALID;
|
||||||
|
|
||||||
|
/* Battery charge controller status */
|
||||||
|
static battery_controller_status_e _battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
|
||||||
|
static BatteryControllerStatusChangeCb_t _BatteryControllerStatusChangeCb = NULL;
|
||||||
|
|
||||||
static void vibration_motor_timer_irq_cb(void *p)
|
static void vibration_motor_timer_irq_cb(void *p)
|
||||||
{
|
{
|
||||||
(void)p;
|
(void)p;
|
||||||
tls_pwm_stop(VIBRATION_MOTOR_PWM_CHANNEL);
|
tls_pwm_stop(VIBRATION_MOTOR_PWM_CHANNEL);
|
||||||
tls_gpio_cfg(VIBRATION_MOTOR_ENABLE, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
|
tls_gpio_cfg(VIBRATION_MOTOR_ENABLE, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING);
|
||||||
tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0);
|
tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0);
|
||||||
APP_LOG_DEBUG("Vibration stopped");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == POLL_POLICY
|
||||||
|
static uint8_t _battery_status_timer_id = WM_TIMER_ID_INVALID;
|
||||||
|
|
||||||
|
static void battery_status_timer_irq_cb(void *p)
|
||||||
|
{
|
||||||
|
bool charging = tls_gpio_read(BATTERY_CONTROLLER_CHARGING_STATUS) == 0;
|
||||||
|
bool charged = tls_gpio_read(BATTERY_CONTROLLER_CHARGED_STATUS) == 0;
|
||||||
|
|
||||||
|
battery_controller_status_e old_battery_status = _battery_fsm;
|
||||||
|
|
||||||
|
if(charging && !charged)
|
||||||
|
_battery_fsm = BATTERY_CONTROLLER_STATUS_CHARGING;
|
||||||
|
else if(!charging && charged)
|
||||||
|
_battery_fsm = BATTERY_CONTROLLER_STATUS_CHARGED;
|
||||||
|
else if (!charging && !charged)
|
||||||
|
_battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
|
||||||
|
else
|
||||||
|
_battery_fsm = BATTERY_CONTROLLER_STATUS_ERROR;
|
||||||
|
|
||||||
|
if(old_battery_status != _battery_fsm)
|
||||||
|
{
|
||||||
|
// Let's call a user registered callback here
|
||||||
|
APP_LOG_INFO("Battery status changed from %s to %s",
|
||||||
|
battery_controller_status_2_str(old_battery_status),
|
||||||
|
battery_controller_status_2_str(_battery_fsm));
|
||||||
|
|
||||||
|
if(_BatteryControllerStatusChangeCb) _BatteryControllerStatusChangeCb(old_battery_status, _battery_fsm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == INTERRUPT_POLICY
|
||||||
|
static void battery_controller_irq_cb(void *p)
|
||||||
|
{
|
||||||
|
enum tls_io_name gpio_pin = (enum tls_io_name)p;
|
||||||
|
|
||||||
|
if(BATTERY_CONTROLLER_CHARGING_STATUS == gpio_pin)
|
||||||
|
{
|
||||||
|
tls_clr_gpio_irq_status(BATTERY_CONTROLLER_CHARGING_STATUS);
|
||||||
|
}
|
||||||
|
if(BATTERY_CONTROLLER_CHARGED_STATUS == gpio_pin)
|
||||||
|
{
|
||||||
|
tls_clr_gpio_irq_status(BATTERY_CONTROLLER_CHARGED_STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool charging = tls_gpio_read(BATTERY_CONTROLLER_CHARGING_STATUS) == 0;
|
||||||
|
bool charged = tls_gpio_read(BATTERY_CONTROLLER_CHARGED_STATUS) == 0;
|
||||||
|
|
||||||
|
battery_controller_status_e old_battery_status = _battery_fsm;
|
||||||
|
|
||||||
|
switch(old_battery_status)
|
||||||
|
{
|
||||||
|
case BATTERY_CONTROLLER_STATUS_CHARGING:
|
||||||
|
if(charged) _battery_fsm = BATTERY_CONTROLLER_STATUS_CHARGED;
|
||||||
|
else if(!charged && !charging) _battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
|
||||||
|
break;
|
||||||
|
case BATTERY_CONTROLLER_STATUS_CHARGED:
|
||||||
|
if(!charged && !charging) _battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
|
||||||
|
break;
|
||||||
|
case BATTERY_CONTROLLER_STATUS_DISCHARGING:
|
||||||
|
if(charging) _battery_fsm = BATTERY_CONTROLLER_STATUS_CHARGING;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(old_battery_status != _battery_fsm)
|
||||||
|
{
|
||||||
|
// Let's call a user registered callback here
|
||||||
|
APP_LOG_INFO("Battery status changed from %s to : %s, IRQ : %u",
|
||||||
|
battery_controller_status_2_str(old_battery_status),
|
||||||
|
battery_controller_status_2_str(_battery_fsm),
|
||||||
|
gpio_pin);
|
||||||
|
|
||||||
|
if(_BatteryControllerStatusChangeCb) _BatteryControllerStatusChangeCb(old_battery_status, _battery_fsm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void watch_peripherals_io_init(void)
|
static void watch_peripherals_io_init(void)
|
||||||
{
|
{
|
||||||
/* We initialize the ADC input as well as the gpio used to enabled the voltage divider bridge */
|
/* We initialize the ADC input as well as the gpio used to enabled the voltage divider bridge */
|
||||||
@ -31,8 +119,34 @@ static void watch_peripherals_io_init(void)
|
|||||||
tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0);
|
tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0);
|
||||||
|
|
||||||
/* We initialize the pins used to read the battery controller IC charging and charged statuses */
|
/* We initialize the pins used to read the battery controller IC charging and charged statuses */
|
||||||
tls_gpio_cfg(BATTERY_CONTROLLER_CHARGING_STATUS, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
|
|
||||||
tls_gpio_cfg(BATTERY_CONTROLLER_CHARGED_STATUS, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
|
tls_gpio_cfg(BATTERY_CONTROLLER_CHARGED_STATUS, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
|
||||||
|
tls_gpio_cfg(BATTERY_CONTROLLER_CHARGING_STATUS, WM_GPIO_DIR_INPUT, WM_GPIO_ATTR_FLOATING);
|
||||||
|
|
||||||
|
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == INTERRUPT_POLICY
|
||||||
|
tls_gpio_isr_register(BATTERY_CONTROLLER_CHARGED_STATUS, &(battery_controller_irq_cb), (int*) BATTERY_CONTROLLER_CHARGED_STATUS);
|
||||||
|
tls_gpio_irq_enable(BATTERY_CONTROLLER_CHARGED_STATUS, WM_GPIO_IRQ_TRIG_DOUBLE_EDGE); // Enabled when level is changing edge
|
||||||
|
|
||||||
|
tls_gpio_isr_register(BATTERY_CONTROLLER_CHARGING_STATUS, &(battery_controller_irq_cb), (int*) BATTERY_CONTROLLER_CHARGING_STATUS);
|
||||||
|
tls_gpio_irq_enable(BATTERY_CONTROLLER_CHARGING_STATUS, WM_GPIO_IRQ_TRIG_DOUBLE_EDGE); // Enabled when level is changing edge
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CASE_RETURN_STR
|
||||||
|
#define CASE_RETURN_STR(const) case const: return #const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const char *battery_controller_status_2_str(battery_controller_status_e status)
|
||||||
|
{
|
||||||
|
switch(status)
|
||||||
|
{
|
||||||
|
CASE_RETURN_STR(BATTERY_CONTROLLER_STATUS_CHARGING)
|
||||||
|
CASE_RETURN_STR(BATTERY_CONTROLLER_STATUS_DISCHARGING)
|
||||||
|
CASE_RETURN_STR(BATTERY_CONTROLLER_STATUS_CHARGED)
|
||||||
|
CASE_RETURN_STR(BATTERY_CONTROLLER_STATUS_ERROR)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "Unknown Battery Status";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_peripherals_init(int8_t adcOffset)
|
void watch_peripherals_init(int8_t adcOffset)
|
||||||
@ -43,7 +157,7 @@ void watch_peripherals_init(int8_t adcOffset)
|
|||||||
/* Prevent multiple init call !*/
|
/* Prevent multiple init call !*/
|
||||||
if(WM_TIMER_ID_INVALID == _vibration_motor_timer_id)
|
if(WM_TIMER_ID_INVALID == _vibration_motor_timer_id)
|
||||||
{
|
{
|
||||||
/* Let's initialize the timer w'll use to stop the vibration motor */
|
/* Let's initialize the timer we'll use to stop the vibration motor */
|
||||||
struct tls_timer_cfg vibration_motor_timer_cfg =
|
struct tls_timer_cfg vibration_motor_timer_cfg =
|
||||||
{
|
{
|
||||||
.arg = NULL,
|
.arg = NULL,
|
||||||
@ -55,8 +169,32 @@ void watch_peripherals_init(int8_t adcOffset)
|
|||||||
_vibration_motor_timer_id = tls_timer_create(&vibration_motor_timer_cfg);
|
_vibration_motor_timer_id = tls_timer_create(&vibration_motor_timer_cfg);
|
||||||
|
|
||||||
if(WM_TIMER_ID_INVALID == _vibration_motor_timer_id)
|
if(WM_TIMER_ID_INVALID == _vibration_motor_timer_id)
|
||||||
APP_LOG_ERROR("Failed to create timer");
|
APP_LOG_ERROR("Failed to create vibration motor timer");
|
||||||
}
|
}
|
||||||
|
#if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == POLL_POLICY
|
||||||
|
if(WM_TIMER_ID_INVALID == _battery_status_timer_id)
|
||||||
|
{
|
||||||
|
struct tls_timer_cfg battery_status_timer_cfg =
|
||||||
|
{
|
||||||
|
.arg = NULL,
|
||||||
|
.callback = &(battery_status_timer_irq_cb),
|
||||||
|
.unit = TLS_TIMER_UNIT_MS,
|
||||||
|
.is_repeat = true,
|
||||||
|
.timeout = 200
|
||||||
|
};
|
||||||
|
_battery_status_timer_id = tls_timer_create(&battery_status_timer_cfg);
|
||||||
|
|
||||||
|
if(WM_TIMER_ID_INVALID == _battery_status_timer_id)
|
||||||
|
APP_LOG_ERROR("Failed to create battery status timer");
|
||||||
|
else
|
||||||
|
tls_timer_start(_battery_status_timer_id);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void watch_peripherals_register_battery_controller_status_change_cb(BatteryControllerStatusChangeCb_t BatteryControllerStatusChangeCb)
|
||||||
|
{
|
||||||
|
_BatteryControllerStatusChangeCb = BatteryControllerStatusChangeCb;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t watch_peripherals_get_battery_voltage(battery_unit_e unit)
|
uint16_t watch_peripherals_get_battery_voltage(battery_unit_e unit)
|
||||||
@ -100,22 +238,11 @@ uint8_t battery_voltage_to_percentage(uint16_t voltage_in_mV)
|
|||||||
|
|
||||||
battery_controller_status_e watch_peripherals_get_battery_controller_status(void)
|
battery_controller_status_e watch_peripherals_get_battery_controller_status(void)
|
||||||
{
|
{
|
||||||
bool charging = tls_gpio_read(BATTERY_CONTROLLER_CHARGING_STATUS) == 0;
|
return _battery_fsm;
|
||||||
bool charged = tls_gpio_read(BATTERY_CONTROLLER_CHARGED_STATUS) == 0;
|
|
||||||
|
|
||||||
if(charging && !charged)
|
|
||||||
return BATTERY_CHARGING;
|
|
||||||
else if(!charging && charged)
|
|
||||||
return BATTERY_CHARGED;
|
|
||||||
else if (!charging && !charged)
|
|
||||||
return BATTERY_DISCHARGING;
|
|
||||||
else
|
|
||||||
return BATTERY_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs)
|
void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs)
|
||||||
{
|
{
|
||||||
APP_LOG_DEBUG("Vibration started");
|
|
||||||
/* No need to do anything if the duration is 0 or if the strength is 0 */
|
/* No need to do anything if the duration is 0 or if the strength is 0 */
|
||||||
if(!strength || !durationMs) return;
|
if(!strength || !durationMs) return;
|
||||||
/* We start the timer which will stop the vibration after durationMs time */
|
/* We start the timer which will stop the vibration after durationMs time */
|
||||||
|
@ -15,12 +15,22 @@ typedef enum battery_unit
|
|||||||
|
|
||||||
typedef enum battery_controller_status
|
typedef enum battery_controller_status
|
||||||
{
|
{
|
||||||
BATTERY_CHARGING = 0,
|
BATTERY_CONTROLLER_STATUS_DISCHARGING = 0,
|
||||||
BATTERY_CHARGED,
|
BATTERY_CONTROLLER_STATUS_CHARGING,
|
||||||
BATTERY_DISCHARGING,
|
BATTERY_CONTROLLER_STATUS_CHARGED,
|
||||||
BATTERY_ERROR
|
BATTERY_CONTROLLER_STATUS_ERROR
|
||||||
} battery_controller_status_e;
|
} battery_controller_status_e;
|
||||||
|
|
||||||
|
typedef void (*BatteryControllerStatusChangeCb_t)(battery_controller_status_e old, battery_controller_status_e new);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Helper function to easily print the battery status enumeration name
|
||||||
|
*
|
||||||
|
* @param status the enumeration value for which to get the name
|
||||||
|
* @return const char* a string representing the enumeration value
|
||||||
|
*/
|
||||||
|
const char *battery_controller_status_2_str(battery_controller_status_e status);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Inits the watch peripherals driver.
|
* @brief Inits the watch peripherals driver.
|
||||||
* This must be called before using the API.
|
* This must be called before using the API.
|
||||||
@ -29,6 +39,14 @@ typedef enum battery_controller_status
|
|||||||
*/
|
*/
|
||||||
void watch_peripherals_init(int8_t adcOffset);
|
void watch_peripherals_init(int8_t adcOffset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers the user provided callback function to notify the battery controller status change event
|
||||||
|
* @note This function should be as short as possible, do not call LVGL functions in it.
|
||||||
|
*
|
||||||
|
* @param BatteryStatusChangeCb a pointer to the function having the right definition.
|
||||||
|
*/
|
||||||
|
void watch_peripherals_register_battery_controller_status_change_cb(BatteryControllerStatusChangeCb_t BatteryStatusChangeCb);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reads and returns the current battery voltage in mV or it's corresponding capacity in percentage.
|
* @brief Reads and returns the current battery voltage in mV or it's corresponding capacity in percentage.
|
||||||
* This function takes into account the adcOffset parameter provided in the @ref watch_peripherals_init
|
* This function takes into account the adcOffset parameter provided in the @ref watch_peripherals_init
|
||||||
@ -50,9 +68,9 @@ uint8_t battery_voltage_to_percentage(uint16_t voltage_in_mV);
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the current battery controller IC status.
|
* @brief Returns the current battery controller IC status.
|
||||||
* It can be one of the following
|
* It can be one of the following :
|
||||||
*
|
*
|
||||||
* @return battery_controller_status_e
|
* @return battery_controller_status_e BATTERY_CHARGING, BATTERY_CHARGED, BATTERY_DISCHARGING and BATTERY_ERROR.
|
||||||
*/
|
*/
|
||||||
battery_controller_status_e watch_peripherals_get_battery_controller_status(void);
|
battery_controller_status_e watch_peripherals_get_battery_controller_status(void);
|
||||||
|
|
||||||
|
15
src/W800_SDK_v1.00.10/app/ble/Makefile
Normal file
15
src/W800_SDK_v1.00.10/app/ble/Makefile
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
TOP_DIR = ../..
|
||||||
|
sinclude $(TOP_DIR)/tools/w800/conf.mk
|
||||||
|
|
||||||
|
ifndef PDIR
|
||||||
|
GEN_LIBS = libble$(LIB_EXT)
|
||||||
|
endif
|
||||||
|
|
||||||
|
#DEFINES +=
|
||||||
|
|
||||||
|
sinclude $(TOP_DIR)/tools/w800/rules.mk
|
||||||
|
|
||||||
|
INCLUDES := $(INCLUDES) -I $(PDIR)include
|
||||||
|
|
||||||
|
PDIR := ../$(PDIR)
|
||||||
|
sinclude $(PDIR)Makefile
|
91
src/W800_SDK_v1.00.10/app/ble/ble_modem.c
Normal file
91
src/W800_SDK_v1.00.10/app/ble/ble_modem.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include "ble_modem.h"
|
||||||
|
#include "app_common.h"
|
||||||
|
#include "host/ble_hs.h"
|
||||||
|
#include "FreeRTOS.h"
|
||||||
|
#include "wm_bt_def.h"
|
||||||
|
#include "wm_bt_app.h"
|
||||||
|
#include "wm_bt_util.h"
|
||||||
|
#include "ble_service.h"
|
||||||
|
|
||||||
|
//Is needed for the BT off workaround
|
||||||
|
#include "wm_wifi.h"
|
||||||
|
|
||||||
|
bool ble_modem_on(bool startService)
|
||||||
|
{
|
||||||
|
int status = BLE_HS_ENOERR;
|
||||||
|
bool serviceStartSuccess = true;
|
||||||
|
uint8_t uart_no = 0xFF;
|
||||||
|
tls_appl_trace_level = TLS_BT_LOG_VERBOSE; //Should be set with a config define
|
||||||
|
|
||||||
|
if(bt_adapter_state == WM_BT_STATE_ON) {
|
||||||
|
TLS_BT_APPL_TRACE_VERBOSE("ble modem already on"NEW_LINE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TLS_BT_APPL_TRACE_DEBUG("ble modem running, uart_no=%d, log_level=%d"NEW_LINE, uart_no,
|
||||||
|
tls_appl_trace_level);
|
||||||
|
status = tls_bt_init(uart_no);
|
||||||
|
|
||||||
|
if((status != BLE_HS_ENOERR) && (status != BLE_HS_EALREADY)) {
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, tls_bt_init ret:%s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start the ble service if it was asked and if it is not yet started
|
||||||
|
if(startService && !ble_service_is_started())
|
||||||
|
serviceStartSuccess = ble_service_start();
|
||||||
|
|
||||||
|
return ((status == BLE_HS_ENOERR || status == BLE_HS_EALREADY) && serviceStartSuccess) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_modem_off(void)
|
||||||
|
{
|
||||||
|
int status = BLE_HS_ENOERR;
|
||||||
|
bool serviceStopSuccess = true;
|
||||||
|
TLS_BT_APPL_TRACE_DEBUG("ble modem off"NEW_LINE);
|
||||||
|
|
||||||
|
if(bt_adapter_state == WM_BT_STATE_OFF)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_VERBOSE("ble modem already off"NEW_LINE);
|
||||||
|
return TLS_BT_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ble_service_is_started())
|
||||||
|
{
|
||||||
|
serviceStopSuccess = ble_service_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let's make a busy wait on the status of the ble service:
|
||||||
|
uint8_t timeout = 0;
|
||||||
|
while(ble_service_is_started())
|
||||||
|
{
|
||||||
|
tls_os_time_delay(pdMS_TO_TICKS(5));
|
||||||
|
|
||||||
|
// Service is stuck ? waiting up to 300 ms for it to stop
|
||||||
|
if(++timeout > 60)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_service_stop timeout "NEW_LINE, __FUNCTION__);
|
||||||
|
return serviceStopSuccess;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
status = tls_bt_deinit();
|
||||||
|
|
||||||
|
if((status != BLE_HS_ENOERR) && (status != BLE_HS_EALREADY)) {
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, tls_bt_deinit ret:%s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(status != BLE_HS_EALREADY)
|
||||||
|
{
|
||||||
|
//Starting a wifi scan really stops the BT modem ?? Why ? I don't know
|
||||||
|
tls_wifi_scan();
|
||||||
|
}
|
||||||
|
|
||||||
|
return ((status == BLE_HS_ENOERR || status == BLE_HS_EALREADY) && serviceStopSuccess) ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_ble_modem_on(void)
|
||||||
|
{
|
||||||
|
if(bt_adapter_state == WM_BT_STATE_OFF || bt_system_action != WM_BT_SYSTEM_ACTION_IDLE)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
32
src/W800_SDK_v1.00.10/app/ble/ble_modem.h
Normal file
32
src/W800_SDK_v1.00.10/app/ble/ble_modem.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef BLE_MODEM_H
|
||||||
|
#define BLE_MODEM_H
|
||||||
|
|
||||||
|
#include "wm_type_def.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Turns the BLE modem on
|
||||||
|
*
|
||||||
|
* @param startService to start the ble service when turning the modem on
|
||||||
|
* @return true on success
|
||||||
|
* @return false on failure
|
||||||
|
*/
|
||||||
|
bool ble_modem_on(bool startService);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Turns the BLE modem off
|
||||||
|
* @note If the ble service was started, then it will automatically be turned off with the modem
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
* @return false on failure
|
||||||
|
*/
|
||||||
|
bool ble_modem_off(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Find out if the modem is turned on or not
|
||||||
|
*
|
||||||
|
* @return true if turned on
|
||||||
|
* @return false if turned off
|
||||||
|
*/
|
||||||
|
bool is_ble_modem_on(void);
|
||||||
|
|
||||||
|
#endif //BLE_MODEM_H
|
789
src/W800_SDK_v1.00.10/app/ble/ble_service.c
Normal file
789
src/W800_SDK_v1.00.10/app/ble/ble_service.c
Normal file
@ -0,0 +1,789 @@
|
|||||||
|
#include "ble_service.h"
|
||||||
|
#include "app_common.h"
|
||||||
|
#include "ble_modem.h"
|
||||||
|
#include "host/ble_hs.h"
|
||||||
|
#include "services/gap/ble_svc_gap.h"
|
||||||
|
#include "wm_bt_util.h"
|
||||||
|
#include "bluetooth_sig_values.h"
|
||||||
|
|
||||||
|
#define USABLE_DEFAULT_MTU (20) //23 - 3 of header bytes
|
||||||
|
|
||||||
|
/* ble service internal workings attributes */
|
||||||
|
static volatile ble_service_state_e _ble_service_state = BLE_SERVICE_MODE_STOPPED;
|
||||||
|
static nus_data_rx_fn_t _ble_service_nus_data_rx_cb = NULL;
|
||||||
|
static ble_service_state_change_fn_t _ble_service_state_change_cb = NULL;
|
||||||
|
|
||||||
|
/* Connection handle to the connected device : only one simultaneous connection */
|
||||||
|
static uint16_t ble_device_conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||||
|
static uint16_t usable_mtu = USABLE_DEFAULT_MTU;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Structure used to store the various data to carry out a chunked notification or indication data transfer
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint16_t length; // The length of the data being sent
|
||||||
|
uint16_t offset; // The offset used to be ableto send the next chunk of data in the array
|
||||||
|
uint16_t sent_chunk_size; // The size of the chunk sent
|
||||||
|
const uint8_t *data; // The address of the data to send
|
||||||
|
bool transfer_in_progress; // Is a transfer already in progress ?
|
||||||
|
} data_being_sent_t;
|
||||||
|
|
||||||
|
// Only one transfer of a type () can occur at any given time
|
||||||
|
static data_being_sent_t notification_data = {.data = NULL, .length = 0, .offset = 0, .transfer_in_progress = false};
|
||||||
|
static data_being_sent_t indication_data = {.data = NULL, .length = 0, .offset = 0, .transfer_in_progress = false};
|
||||||
|
|
||||||
|
static struct ble_gap_event_listener ble_gap_event_listener;
|
||||||
|
|
||||||
|
static int battery_level_char_access_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||||
|
static uint16_t battery_level_char_handle = 0;
|
||||||
|
static uint8_t battery_level_value = 42;
|
||||||
|
|
||||||
|
|
||||||
|
static int gatt_nus_char_access_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||||
|
static const ble_uuid128_t gatt_nus_service_uuid = BLE_UUID128_INIT(0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x01, 0x00, 0x40, 0x6E);
|
||||||
|
|
||||||
|
static uint16_t gatt_nus_char_rx_handle = 0;
|
||||||
|
static const ble_uuid128_t gatt_nus_char_rx_uuid = BLE_UUID128_INIT(0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x02, 0x00, 0x40, 0x6E);
|
||||||
|
|
||||||
|
static uint16_t gatt_nus_char_tx_handle = 0;
|
||||||
|
static const ble_uuid128_t gatt_nus_char_tx_uuid = BLE_UUID128_INIT(0x9E, 0xCA, 0xDC, 0x24, 0x0E, 0xE5, 0xA9, 0xE0, 0x93, 0xF3, 0xA3, 0xB5, 0x03, 0x00, 0x40, 0x6E);
|
||||||
|
|
||||||
|
static struct ble_gatt_svc_def gatt_svc[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||||
|
.uuid = BLE_UUID16_DECLARE(BLE_DEVICE_ADV_SERVICE),
|
||||||
|
.characteristics = (struct ble_gatt_chr_def[])
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.uuid = BLE_UUID16_DECLARE(0x2A19),
|
||||||
|
.val_handle = &battery_level_char_handle,
|
||||||
|
.access_cb = &(battery_level_char_access_cb),
|
||||||
|
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.uuid = NULL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = BLE_GATT_SVC_TYPE_PRIMARY,
|
||||||
|
.uuid = &gatt_nus_service_uuid.u,
|
||||||
|
.characteristics = (struct ble_gatt_chr_def[])
|
||||||
|
{
|
||||||
|
{
|
||||||
|
.uuid = &gatt_nus_char_rx_uuid.u,
|
||||||
|
.val_handle = &gatt_nus_char_rx_handle,
|
||||||
|
.access_cb = &(gatt_nus_char_access_cb),
|
||||||
|
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_WRITE_NO_RSP
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
.uuid = &gatt_nus_char_tx_uuid.u,
|
||||||
|
.val_handle = &gatt_nus_char_tx_handle,
|
||||||
|
.access_cb = &(gatt_nus_char_access_cb),
|
||||||
|
.flags = BLE_GATT_CHR_F_NOTIFY
|
||||||
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
.uuid = NULL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.type = BLE_GATT_SVC_TYPE_END
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool ble_service_define_gatt(const struct ble_gatt_svc_def *gatt_svc);
|
||||||
|
static bool ble_service_advertise(bool enable);
|
||||||
|
static int ble_gap_event_cb(struct ble_gap_event *event, void *arg);
|
||||||
|
static int ble_advertise_gap_event_cb(struct ble_gap_event *event, void *arg);
|
||||||
|
static void print_conn_desc(const struct ble_gap_conn_desc *desc);
|
||||||
|
// Raw because it doesn't handle payload fragmentation if mtu size is smaller than the payload size
|
||||||
|
static bool ble_service_send_raw_custom_notification(uint16_t characteristic_handle, const uint8_t *data, uint16_t length);
|
||||||
|
static bool ble_service_send_custom_notification(uint16_t characteristic_handle, data_being_sent_t * const data);
|
||||||
|
static void reset_data_being_sent(data_being_sent_t * const data);
|
||||||
|
|
||||||
|
// Needed to get the reponse after a mtu exchange request
|
||||||
|
static int ble_gatt_mtu_cb(uint16_t conn_handle, const struct ble_gatt_error *error, uint16_t mtu, void *arg);
|
||||||
|
|
||||||
|
const char *ble_service_state_2_str(ble_service_state_e state)
|
||||||
|
{
|
||||||
|
switch(state) {
|
||||||
|
CASE_RETURN_STR(BLE_SERVICE_MODE_STOPPED)
|
||||||
|
CASE_RETURN_STR(BLE_SERVICE_MODE_IDLE)
|
||||||
|
CASE_RETURN_STR(BLE_SERVICE_MODE_ADVERTISING)
|
||||||
|
CASE_RETURN_STR(BLE_SERVICE_MODE_CONNECTED)
|
||||||
|
CASE_RETURN_STR(BLE_SERVICE_MODE_INDICATING)
|
||||||
|
CASE_RETURN_STR(BLE_SERVICE_MODE_EXITING)
|
||||||
|
default:
|
||||||
|
return "unkown ble service state";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PUBLIC FUNCTION DEFINITION
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool ble_service_start(void)
|
||||||
|
{
|
||||||
|
int status = BLE_HS_ENOERR;
|
||||||
|
|
||||||
|
// 1 We first check if the BLE service is stopped
|
||||||
|
if(_ble_service_state != BLE_SERVICE_MODE_STOPPED)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, ble service already running (%s)"NEW_LINE, __FUNCTION__, ble_service_state_2_str(_ble_service_state));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 We check if the BLE MODEM is turned on
|
||||||
|
if(!is_ble_modem_on())
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble modem is not turned on"NEW_LINE, __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3 We set our device name and appearance
|
||||||
|
if((status = ble_svc_gap_device_name_set(BLE_DEVICE_NAME)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, ble_svc_gap_device_name_set "NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
if((status = ble_svc_gap_device_appearance_set(BLE_DEVICE_APPEARANCE)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, ble_svc_gap_device_appearance_set "NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4 We register our gatt (service structure)
|
||||||
|
if(!ble_service_define_gatt(gatt_svc))
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, failed to define gatt"NEW_LINE, __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5 We register a gap event handler callback
|
||||||
|
if((status = ble_gap_event_listener_register(&ble_gap_event_listener, &(ble_gap_event_cb), NULL)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_gap_event_listener_register %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6 We are now ready to make all registered services available to peers
|
||||||
|
if((status = ble_gatts_start()) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_gatts_start failed : %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7 Finally we can start advertising
|
||||||
|
if(!ble_service_advertise(true))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ble_service_state = BLE_SERVICE_MODE_ADVERTISING;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_service_stop(void)
|
||||||
|
{
|
||||||
|
int status = BLE_HS_ENOERR;
|
||||||
|
|
||||||
|
// 1 We first check if the BLE service is not stopped
|
||||||
|
if(_ble_service_state == BLE_SERVICE_MODE_STOPPED)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, ble service already stopped"NEW_LINE, __FUNCTION__);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2 We check if the BLE MODEM is turned on
|
||||||
|
if(!is_ble_modem_on())
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble modem is not turned on"NEW_LINE, __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(_ble_service_state)
|
||||||
|
{
|
||||||
|
case BLE_SERVICE_MODE_CONNECTED:
|
||||||
|
case BLE_SERVICE_MODE_INDICATING:
|
||||||
|
status = ble_gap_terminate(ble_device_conn_handle, BLE_ERR_REM_USER_CONN_TERM);
|
||||||
|
if(status == BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
_ble_service_state = BLE_SERVICE_MODE_EXITING;
|
||||||
|
}
|
||||||
|
else //BLE_HS_EDISABLED || BLE_HS_ENOTCONN or any other error
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, ble_gap_terminate %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
_ble_service_state = BLE_SERVICE_MODE_STOPPED;
|
||||||
|
//Unregister gap event listener
|
||||||
|
if((status = ble_gap_event_listener_unregister(&ble_gap_event_listener)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, ble_gap_event_listener_unregister %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BLE_SERVICE_MODE_ADVERTISING:
|
||||||
|
if(!ble_service_advertise(false))
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, ble_service_advertise failed to stop"NEW_LINE, __FUNCTION__);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_ble_service_state = BLE_SERVICE_MODE_STOPPED;
|
||||||
|
//Unregister gap event listener
|
||||||
|
if((status = ble_gap_event_listener_unregister(&ble_gap_event_listener)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, ble_gap_event_listener_unregister %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: //Just to keep compiler happy since BLE_SERVICE_MODE_STOPPED is rulled out earlier
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_ble_service_state == BLE_SERVICE_MODE_STOPPED)
|
||||||
|
{
|
||||||
|
// We finally clean the gatt registered services
|
||||||
|
if((status = ble_gatts_reset()) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_gatts_reset %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_service_is_started(void)
|
||||||
|
{
|
||||||
|
return _ble_service_state != BLE_SERVICE_MODE_STOPPED;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_service_is_device_connected(void)
|
||||||
|
{
|
||||||
|
return _ble_service_state == BLE_SERVICE_MODE_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_service_register_state_change_cb(ble_service_state_change_fn_t ble_service_state_change_cb)
|
||||||
|
{
|
||||||
|
_ble_service_state_change_cb = ble_service_state_change_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
ble_service_state_e ble_service_get_state(void)
|
||||||
|
{
|
||||||
|
return _ble_service_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_service_update_connection_parameters(
|
||||||
|
uint16_t itvl_min,
|
||||||
|
uint16_t itvl_max,
|
||||||
|
uint16_t latency,
|
||||||
|
uint16_t supervision_timeout,
|
||||||
|
uint16_t min_ce_len,
|
||||||
|
uint16_t max_ce_len)
|
||||||
|
{
|
||||||
|
if(BLE_HS_CONN_HANDLE_NONE == ble_device_conn_handle)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, no active connection" NEW_LINE, __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = BLE_HS_ENOERR;
|
||||||
|
|
||||||
|
struct ble_gap_upd_params gap_params_to_apply = {0};
|
||||||
|
gap_params_to_apply.itvl_min = itvl_min;
|
||||||
|
gap_params_to_apply.itvl_max = itvl_max;
|
||||||
|
gap_params_to_apply.latency = latency;
|
||||||
|
gap_params_to_apply.supervision_timeout = supervision_timeout;
|
||||||
|
gap_params_to_apply.min_ce_len = min_ce_len;
|
||||||
|
gap_params_to_apply.max_ce_len = max_ce_len;
|
||||||
|
|
||||||
|
if ((status = ble_gap_update_params(ble_device_conn_handle, &gap_params_to_apply)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_gap_update_params failed %s" NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_service_request_mtu_exchange(void)
|
||||||
|
{
|
||||||
|
if(BLE_HS_CONN_HANDLE_NONE == ble_device_conn_handle)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, no active connection" NEW_LINE, __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = BLE_HS_ENOERR;
|
||||||
|
|
||||||
|
if((status = ble_gattc_exchange_mtu(ble_device_conn_handle, &(ble_gatt_mtu_cb), NULL)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_gattc_exchange_mtu %s" NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ble_service_send_nus_data(const uint8_t *data, uint16_t length)
|
||||||
|
{
|
||||||
|
// The NUS is TX is using notifications
|
||||||
|
if(notification_data.transfer_in_progress)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, a transfer is already in progress"NEW_LINE, __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
notification_data.transfer_in_progress = true;
|
||||||
|
notification_data.data = data;
|
||||||
|
notification_data.length = length;
|
||||||
|
|
||||||
|
return ble_service_send_custom_notification(gatt_nus_char_tx_handle, ¬ification_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ble_service_register_nus_data_rx_cb(nus_data_rx_fn_t nus_data_rx_cb)
|
||||||
|
{
|
||||||
|
_ble_service_nus_data_rx_cb = nus_data_rx_cb;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* PRIVATE FUNCTION DEFINITION
|
||||||
|
* Used for the internal workings of the service
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool ble_service_send_raw_custom_notification(uint16_t characteristic_handle, const uint8_t *data, uint16_t length)
|
||||||
|
{
|
||||||
|
if(BLE_HS_CONN_HANDLE_NONE == ble_device_conn_handle)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, no active connection" NEW_LINE, __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!data || !length)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, no data" NEW_LINE, __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int status = BLE_HS_ENOERR;
|
||||||
|
struct os_mbuf *om_buf = ble_hs_mbuf_from_flat(data, length);
|
||||||
|
|
||||||
|
if(!om_buf)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_hs_mbuf_from_flat" NEW_LINE, __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((status = ble_gattc_notify_custom(ble_device_conn_handle, characteristic_handle, om_buf)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_hs_mbuf_from_flat %s" NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ble_service_send_custom_notification(uint16_t characteristic_handle, data_being_sent_t * const notif_data)
|
||||||
|
{
|
||||||
|
if(!notif_data)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, notif_data is NULL"NEW_LINE, __FUNCTION__);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We compute the maximum size of the data we can send:
|
||||||
|
uint16_t remaining_data_to_send = notif_data->length - notif_data->offset;
|
||||||
|
notif_data->sent_chunk_size = remaining_data_to_send <= usable_mtu ? remaining_data_to_send : usable_mtu;
|
||||||
|
|
||||||
|
if(!ble_service_send_raw_custom_notification(characteristic_handle, ¬if_data->data[notif_data->offset], notif_data->sent_chunk_size))
|
||||||
|
{
|
||||||
|
//Transfer failed :
|
||||||
|
reset_data_being_sent(notif_data);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ble_gatt_mtu_cb(uint16_t conn_handle, const struct ble_gatt_error *error, uint16_t mtu, void *arg)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_DEBUG("ble_gatt_mtu_cb"NEW_LINE);
|
||||||
|
|
||||||
|
switch(error->status)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
TLS_BT_APPL_TRACE_DEBUG("mtu exchange complete: conn_handle=%d mtu=%d"NEW_LINE,
|
||||||
|
conn_handle, mtu);
|
||||||
|
usable_mtu = mtu - 3;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("Update MTU failed...error->status=%d"NEW_LINE, error->status);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BLE_HS_ENOERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ble_service_define_gatt(const struct ble_gatt_svc_def *gatt_svc)
|
||||||
|
{
|
||||||
|
int status = BLE_HS_ENOERR;
|
||||||
|
|
||||||
|
if((status = ble_gatts_count_cfg(gatt_svc)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_gatts_count_cfg failed : %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((status = ble_gatts_add_svcs(gatt_svc)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_gatts_add_svcs failed : %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return status == BLE_HS_ENOERR ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ble_service_advertise(bool enable)
|
||||||
|
{
|
||||||
|
int status = BLE_HS_ENOERR;
|
||||||
|
|
||||||
|
if(enable)
|
||||||
|
{
|
||||||
|
struct ble_hs_adv_fields advertisement_fields = {0};
|
||||||
|
uint8_t own_addr_type = BLE_OWN_ADDR_RANDOM;
|
||||||
|
|
||||||
|
advertisement_fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
|
||||||
|
|
||||||
|
advertisement_fields.appearance = ble_svc_gap_device_appearance();
|
||||||
|
advertisement_fields.appearance_is_present = 1;
|
||||||
|
|
||||||
|
// Set the name of a watch supported by GB
|
||||||
|
#ifdef GADGETBRIDGE_SUPPORT
|
||||||
|
static const char dev_name[12] = "Bangle.js 2";
|
||||||
|
advertisement_fields.name = (uint8_t *)dev_name;//ble_svc_gap_device_name();
|
||||||
|
advertisement_fields.name_len = 11;//strlen(ble_svc_gap_device_name());
|
||||||
|
#else
|
||||||
|
advertisement_fields.name = (uint8_t *)ble_svc_gap_device_name();
|
||||||
|
advertisement_fields.name_len = strlen(ble_svc_gap_device_name());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
advertisement_fields.name_is_complete = 1;
|
||||||
|
|
||||||
|
advertisement_fields.uuids16 = (ble_uuid16_t[])
|
||||||
|
{
|
||||||
|
BLE_UUID16_INIT(BLE_DEVICE_ADV_SERVICE)
|
||||||
|
};
|
||||||
|
advertisement_fields.num_uuids16 = 1;
|
||||||
|
advertisement_fields.uuids16_is_complete = 1;
|
||||||
|
|
||||||
|
// Lets apply the advertisement data
|
||||||
|
if((status = ble_gap_adv_set_fields(&advertisement_fields)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_gap_adv_set_fields failed : %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We the device address
|
||||||
|
uint8_t device_addr[6] = {0};
|
||||||
|
extern int tls_get_bt_mac_addr(u8 *mac);
|
||||||
|
tls_get_bt_mac_addr(device_addr);
|
||||||
|
|
||||||
|
// Make sure the the device address is compliant with the random address specification :
|
||||||
|
device_addr[5] |= 0xC0;
|
||||||
|
|
||||||
|
if((status = ble_hs_id_set_rnd(device_addr)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_hs_id_set_rnd failed : %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_VERBOSE("addr type : %s"NEW_LINE"device addr : %02X:%02X:%02X:%02X:%02X:%02X"NEW_LINE,
|
||||||
|
tls_bt_addr_type_2_str(own_addr_type),
|
||||||
|
device_addr[5],
|
||||||
|
device_addr[4],
|
||||||
|
device_addr[3],
|
||||||
|
device_addr[2],
|
||||||
|
device_addr[1],
|
||||||
|
device_addr[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We are now ready to configure the advertisement parameters
|
||||||
|
struct ble_gap_adv_params advertisement_params = {0};
|
||||||
|
|
||||||
|
advertisement_params.conn_mode = BLE_GAP_CONN_MODE_UND;
|
||||||
|
advertisement_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
|
||||||
|
|
||||||
|
advertisement_params.itvl_min = 160;
|
||||||
|
advertisement_params.itvl_max = 160; //160 / 0.625 = 100 ms
|
||||||
|
advertisement_params.filter_policy = 0;
|
||||||
|
advertisement_params.channel_map = 0; // Use sane default
|
||||||
|
advertisement_params.high_duty_cycle = 0;
|
||||||
|
|
||||||
|
if((status = ble_gap_adv_start(BLE_OWN_ADDR_RANDOM, NULL, BLE_HS_FOREVER, &advertisement_params, &(ble_advertise_gap_event_cb), NULL)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_gap_adv_start failed : %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if((status = ble_gap_adv_stop()) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_gap_adv_stop failed : %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// This is the brain of the ble service, here we handle all the possible GAP events
|
||||||
|
static int ble_gap_event_cb(struct ble_gap_event *event, void *arg)
|
||||||
|
{
|
||||||
|
int status = BLE_HS_ENOERR;
|
||||||
|
struct ble_gap_conn_desc desc;
|
||||||
|
bool error = false;
|
||||||
|
|
||||||
|
TLS_BT_APPL_TRACE_EVENT("ble_gap_event_cb : %s"NEW_LINE, tls_bt_gap_evt_2_str(event->type));
|
||||||
|
|
||||||
|
switch(event->type)
|
||||||
|
{
|
||||||
|
case BLE_GAP_EVENT_CONNECT:
|
||||||
|
if(event->connect.status == BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
if((status = ble_gap_conn_find(event->connect.conn_handle, &desc)) == BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
print_conn_desc(&desc);
|
||||||
|
if(desc.role == BLE_GAP_ROLE_SLAVE)
|
||||||
|
{
|
||||||
|
_ble_service_state = BLE_SERVICE_MODE_CONNECTED;
|
||||||
|
usable_mtu = USABLE_DEFAULT_MTU;
|
||||||
|
ble_device_conn_handle = event->connect.conn_handle;
|
||||||
|
|
||||||
|
//We call the state change callback if registered
|
||||||
|
if(_ble_service_state_change_cb)_ble_service_state_change_cb(_ble_service_state);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error = true;
|
||||||
|
if((status = ble_gap_terminate(event->connect.conn_handle, BLE_ERR_REM_USER_CONN_TERM)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, ble_gap_terminate %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Resume advertising :
|
||||||
|
if(error)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_VERBOSE("Remote device failed to connect, advertise again"NEW_LINE);
|
||||||
|
if(!ble_service_advertise(true))
|
||||||
|
{
|
||||||
|
_ble_service_state = BLE_SERVICE_MODE_IDLE;
|
||||||
|
return BLE_HS_EUNKNOWN;
|
||||||
|
}
|
||||||
|
_ble_service_state = BLE_SERVICE_MODE_ADVERTISING;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BLE_GAP_EVENT_DISCONNECT:
|
||||||
|
if(event->disconnect.conn.role != BLE_GAP_ROLE_SLAVE) return 0;
|
||||||
|
|
||||||
|
TLS_BT_APPL_TRACE_DEBUG("Server disconnect reason=%d[0x%02x],state=%s"NEW_LINE, event->disconnect.reason,event->disconnect.reason-0x200,
|
||||||
|
ble_service_state_2_str(_ble_service_state));
|
||||||
|
|
||||||
|
// Don't forget to invalidate the connection handle :
|
||||||
|
ble_device_conn_handle = BLE_HS_CONN_HANDLE_NONE;
|
||||||
|
|
||||||
|
if(_ble_service_state == BLE_SERVICE_MODE_EXITING)
|
||||||
|
{
|
||||||
|
_ble_service_state = BLE_SERVICE_MODE_STOPPED;
|
||||||
|
|
||||||
|
if((status = ble_gap_event_listener_unregister(&ble_gap_event_listener)) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, ble_gap_event_listener_unregister %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We finally clean the gatt registered services
|
||||||
|
if((status = ble_gatts_reset()) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, ble_gatts_reset %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Let's advertise again
|
||||||
|
TLS_BT_APPL_TRACE_VERBOSE("Service disconnect event, advertise again"NEW_LINE);
|
||||||
|
if(!ble_service_advertise(true))
|
||||||
|
{
|
||||||
|
_ble_service_state = BLE_SERVICE_MODE_IDLE;
|
||||||
|
return BLE_HS_EUNKNOWN;
|
||||||
|
}
|
||||||
|
_ble_service_state = BLE_SERVICE_MODE_ADVERTISING;
|
||||||
|
}
|
||||||
|
|
||||||
|
//We call the state change callback if registered
|
||||||
|
if(_ble_service_state_change_cb)_ble_service_state_change_cb(_ble_service_state);
|
||||||
|
break;
|
||||||
|
case BLE_GAP_EVENT_CONN_UPDATE:
|
||||||
|
TLS_BT_APPL_TRACE_DEBUG("Conn update status : %d"NEW_LINE, event->conn_update.status);
|
||||||
|
if((status = ble_gap_conn_find(event->connect.conn_handle, &desc)) == BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
print_conn_desc(&desc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, ble_gap_conn_find %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BLE_GAP_EVENT_SUBSCRIBE:
|
||||||
|
TLS_BT_APPL_TRACE_VERBOSE("Attr handle : %u"NEW_LINE
|
||||||
|
"cur_indicate : %u"NEW_LINE
|
||||||
|
"prev_indicate : %u"NEW_LINE
|
||||||
|
"cur_notify : %u"NEW_LINE
|
||||||
|
"prev_notify : %u"NEW_LINE,
|
||||||
|
event->subscribe.attr_handle,
|
||||||
|
event->subscribe.cur_indicate,
|
||||||
|
event->subscribe.prev_indicate,
|
||||||
|
event->subscribe.cur_notify,
|
||||||
|
event->subscribe.prev_notify
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case BLE_GAP_EVENT_MTU:
|
||||||
|
TLS_BT_APPL_TRACE_VERBOSE("MTU update : %u"NEW_LINE, event->mtu.value);
|
||||||
|
usable_mtu = event->mtu.value - 3;
|
||||||
|
break;
|
||||||
|
case BLE_GAP_EVENT_NOTIFY_TX:
|
||||||
|
if(event->notify_tx.indication == 0) // Notification
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_VERBOSE("Type : notification"NEW_LINE);
|
||||||
|
if(event->notify_tx.status != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("%s, notify_tx notification error %d, transfer in progress : %u"NEW_LINE, __FUNCTION__, event->notify_tx.status, notification_data.transfer_in_progress);
|
||||||
|
reset_data_being_sent(¬ification_data);
|
||||||
|
return BLE_HS_EUNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
TLS_BT_APPL_TRACE_DEBUG("transfer : %u"NEW_LINE"length : %u"NEW_LINE"offset : %u"NEW_LINE,
|
||||||
|
notification_data.transfer_in_progress,
|
||||||
|
notification_data.length,
|
||||||
|
notification_data.offset);
|
||||||
|
|
||||||
|
// We update the offset :
|
||||||
|
notification_data.offset += notification_data.sent_chunk_size;
|
||||||
|
|
||||||
|
if(notification_data.offset < notification_data.length) // Still data to send ?
|
||||||
|
{
|
||||||
|
if(!ble_service_send_custom_notification(event->notify_tx.attr_handle, ¬ification_data))
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("Failed to send next notification chunk, aborting"NEW_LINE);
|
||||||
|
reset_data_being_sent(¬ification_data);
|
||||||
|
return BLE_HS_EUNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_VERBOSE("last data chunk sent, end of the transfer"NEW_LINE);
|
||||||
|
// All data has been sent, end of the transfer
|
||||||
|
reset_data_being_sent(¬ification_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Indication
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("Indication not yet handled"NEW_LINE);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("unhandled event !"NEW_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BLE_HS_ENOERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ble_advertise_gap_event_cb(struct ble_gap_event *event, void *arg)
|
||||||
|
{
|
||||||
|
return BLE_HS_ENOERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int battery_level_char_access_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||||
|
{
|
||||||
|
int status = BLE_HS_ENOERR;
|
||||||
|
TLS_BT_APPL_TRACE_EVENT("battery_level_char_access_cb op : %s"NEW_LINE, tls_bt_access_opt_2_str(ctxt->op));
|
||||||
|
switch(ctxt->op)
|
||||||
|
{
|
||||||
|
case BLE_GATT_ACCESS_OP_READ_CHR:
|
||||||
|
if(attr_handle == battery_level_char_handle)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_VERBOSE("battery level reading"NEW_LINE);
|
||||||
|
if((status = os_mbuf_append(ctxt->om, &battery_level_value, sizeof(battery_level_value))) != BLE_HS_ENOERR)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_ERROR("%s, battery level os_mbuf : %s"NEW_LINE, __FUNCTION__, tls_bt_rc_2_str(status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("unhandled operation !"NEW_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BLE_HS_ENOERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gatt_nus_char_access_cb(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt *ctxt, void *arg)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_EVENT("gatt_nus_char_access_cb op : %s"NEW_LINE, tls_bt_access_opt_2_str(ctxt->op));
|
||||||
|
|
||||||
|
switch(ctxt->op)
|
||||||
|
{
|
||||||
|
case BLE_GATT_ACCESS_OP_WRITE_CHR:
|
||||||
|
{
|
||||||
|
struct os_mbuf *om_buf = ctxt->om;
|
||||||
|
while(om_buf)
|
||||||
|
{
|
||||||
|
// Call the nus rx cb function if one is registered
|
||||||
|
if(_ble_service_nus_data_rx_cb)
|
||||||
|
_ble_service_nus_data_rx_cb(om_buf->om_data, om_buf->om_len);
|
||||||
|
|
||||||
|
om_buf = SLIST_NEXT(om_buf, om_next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TLS_BT_APPL_TRACE_WARNING("unhandled operation !"NEW_LINE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BLE_HS_ENOERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_conn_desc(const struct ble_gap_conn_desc *desc)
|
||||||
|
{
|
||||||
|
TLS_BT_APPL_TRACE_VERBOSE("conn_handle : %u"NEW_LINE"conn_itvl : %u"NEW_LINE"conn_latency : %u"NEW_LINE"master_clock_accuracy : %u"NEW_LINE"role : %s"NEW_LINE"supervision_timeout : %u"NEW_LINE
|
||||||
|
"encrypted : %u"NEW_LINE"authenticated : %u"NEW_LINE"bonded : %u"NEW_LINE,
|
||||||
|
desc->conn_handle,
|
||||||
|
desc->conn_itvl,
|
||||||
|
desc->conn_latency,
|
||||||
|
desc->master_clock_accuracy,
|
||||||
|
desc->role == BLE_GAP_ROLE_MASTER ? "MASTER" : "SLAVE",
|
||||||
|
desc->supervision_timeout,
|
||||||
|
desc->sec_state.encrypted,
|
||||||
|
desc->sec_state.authenticated,
|
||||||
|
desc->sec_state.bonded);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reset_data_being_sent(data_being_sent_t * const data)
|
||||||
|
{
|
||||||
|
if(data)
|
||||||
|
{
|
||||||
|
memset(data, 0, sizeof(data_being_sent_t));
|
||||||
|
}
|
||||||
|
}
|
126
src/W800_SDK_v1.00.10/app/ble/ble_service.h
Normal file
126
src/W800_SDK_v1.00.10/app/ble/ble_service.h
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#ifndef BLE_SERVICE_H
|
||||||
|
#define BLE_SERVICE_H
|
||||||
|
|
||||||
|
#include "wm_type_def.h"
|
||||||
|
|
||||||
|
#ifndef CASE_RETURN_STR
|
||||||
|
#define CASE_RETURN_STR(const) case const: return #const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (*nus_data_rx_fn_t)(const uint8_t *data, uint16_t length);
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
BLE_SERVICE_MODE_STOPPED = 0x00,
|
||||||
|
BLE_SERVICE_MODE_IDLE,
|
||||||
|
BLE_SERVICE_MODE_ADVERTISING,
|
||||||
|
BLE_SERVICE_MODE_CONNECTED,
|
||||||
|
BLE_SERVICE_MODE_INDICATING,
|
||||||
|
BLE_SERVICE_MODE_EXITING
|
||||||
|
} ble_service_state_e;
|
||||||
|
|
||||||
|
typedef void (*ble_service_state_change_fn_t)(ble_service_state_e service_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resturns the corresponding enum name as a string
|
||||||
|
*
|
||||||
|
* @param state the enum value
|
||||||
|
* @return const char* the enum name as a string
|
||||||
|
*/
|
||||||
|
const char *ble_service_state_2_str(ble_service_state_e state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Configures and starts the BLE service
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
* @return false on failure
|
||||||
|
*/
|
||||||
|
bool ble_service_start(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinits and stops the BLE service
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
* @return false on failure
|
||||||
|
*/
|
||||||
|
bool ble_service_stop(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check whether the ble service is running or not
|
||||||
|
*
|
||||||
|
* @return true if it is running
|
||||||
|
* @return false if it is stopped
|
||||||
|
*/
|
||||||
|
bool ble_service_is_started(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check whether a device is connected to the ble service or not
|
||||||
|
*
|
||||||
|
* @return true if a device is connected
|
||||||
|
* @return false if no device is connected
|
||||||
|
*/
|
||||||
|
bool ble_service_is_device_connected(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers a callback function called every time the state of the BLE service changes.
|
||||||
|
* For example, you can register a callback to know if a device connected to the service, or disconnected
|
||||||
|
*
|
||||||
|
* @param ble_service_state_change_cb the function to register as the callback. The ble_service_state parameter is set to the new state.
|
||||||
|
*/
|
||||||
|
void ble_service_register_state_change_cb(ble_service_state_change_fn_t ble_service_state_change_cb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the current state of the ble service
|
||||||
|
*
|
||||||
|
* @return ble_service_state_e
|
||||||
|
*/
|
||||||
|
ble_service_state_e ble_service_get_state(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Asks to update the current connection parameters
|
||||||
|
* /!\ A connection should be already active before calling this function.
|
||||||
|
*
|
||||||
|
* @param itvl_min Minimum value for connection interval in 1.25ms units
|
||||||
|
* @param itvl_max Maximum value for connection interval in 1.25ms units
|
||||||
|
* @param latency Connection latency
|
||||||
|
* @param supervision_timeout Supervision timeout in 10ms units
|
||||||
|
* @param min_ce_len Minimum length of connection event in 0.625ms units
|
||||||
|
* @param max_ce_len Maximum length of connection event in 0.625ms units
|
||||||
|
* @return true
|
||||||
|
* @return false
|
||||||
|
*/
|
||||||
|
bool ble_service_update_connection_parameters(
|
||||||
|
uint16_t itvl_min,
|
||||||
|
uint16_t itvl_max,
|
||||||
|
uint16_t latency,
|
||||||
|
uint16_t supervision_timeout,
|
||||||
|
uint16_t min_ce_len,
|
||||||
|
uint16_t max_ce_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Requests a MTU (Maximum Transmission Unit) update in order to hopefully, get something bigger than 20 bytes ...
|
||||||
|
*
|
||||||
|
* @return true on success
|
||||||
|
* @return false on failure
|
||||||
|
*/
|
||||||
|
bool ble_service_request_mtu_exchange(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sends the provided payload of size length using the NUS (Nordic UART Service) TX characteristic
|
||||||
|
*
|
||||||
|
* @param data the data to send through the NUS
|
||||||
|
* @param length the lenght in byte of the data to send
|
||||||
|
* @return true on success
|
||||||
|
* @return false on failure
|
||||||
|
*/
|
||||||
|
bool ble_service_send_nus_data(const uint8_t *data, uint16_t length);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Registers a function which will be called every time data is received by the nus rx
|
||||||
|
* @note To unregister a callback, simply pass NULL to the function
|
||||||
|
*
|
||||||
|
* @param nus_data_rx_cb a pointer to the function to call of type nus_data_rx_fn_t
|
||||||
|
*/
|
||||||
|
void ble_service_register_nus_data_rx_cb(nus_data_rx_fn_t nus_data_rx_cb);
|
||||||
|
|
||||||
|
#endif //BLE_APP_H
|
9
src/W800_SDK_v1.00.10/app/ble/bluetooth_sig_values.h
Normal file
9
src/W800_SDK_v1.00.10/app/ble/bluetooth_sig_values.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef BLUETOOTH_SIG_VALUES_H
|
||||||
|
#define BLUETOOTH_SIG_VALUES_H
|
||||||
|
|
||||||
|
#define BLE_DEVICE_APPEARANCE (0x00C2) //Smart Watch
|
||||||
|
#define BLE_DEVICE_NAME "MDBT42Q_W800SW"
|
||||||
|
|
||||||
|
#define BLE_DEVICE_ADV_SERVICE (0x180F) //Battery Service
|
||||||
|
|
||||||
|
#endif //BLUETOOTH_SIG_VALUES_H
|
File diff suppressed because one or more lines are too long
@ -17,6 +17,9 @@
|
|||||||
#include "watch_peripherals.h"
|
#include "watch_peripherals.h"
|
||||||
#include "watch_settings.h"
|
#include "watch_settings.h"
|
||||||
|
|
||||||
|
#include "ble_modem.h"
|
||||||
|
#include "ble_service.h"
|
||||||
|
|
||||||
static void date_time_cb(struct tm * const dateTime)
|
static void date_time_cb(struct tm * const dateTime)
|
||||||
{
|
{
|
||||||
if(!dateTime)return;
|
if(!dateTime)return;
|
||||||
@ -24,11 +27,7 @@ static void date_time_cb(struct tm * const dateTime)
|
|||||||
//APP_LOG_DEBUG("RTC time : %d:%d:%d", dateTime->tm_hour, dateTime->tm_min, dateTime->tm_sec);
|
//APP_LOG_DEBUG("RTC time : %d:%d:%d", dateTime->tm_hour, dateTime->tm_min, dateTime->tm_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t battery_percentage = 100;
|
static uint8_t _battery_percentage = 100;
|
||||||
static uint8_t battery_indicator_cb(void)
|
|
||||||
{
|
|
||||||
return battery_percentage;
|
|
||||||
}
|
|
||||||
|
|
||||||
WatchFace_t watchFace;
|
WatchFace_t watchFace;
|
||||||
MenuScreen_t menuScreen;
|
MenuScreen_t menuScreen;
|
||||||
@ -39,7 +38,25 @@ struct bma4_dev bma;
|
|||||||
struct bma4_accel_config accel_conf;
|
struct bma4_accel_config accel_conf;
|
||||||
struct bma456w_wrist_wear_wakeup_params setting;
|
struct bma456w_wrist_wear_wakeup_params setting;
|
||||||
struct bma4_int_pin_config pin_config;
|
struct bma4_int_pin_config pin_config;
|
||||||
uint16_t int_status;
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t int_status;
|
||||||
|
bool battery_controller_status;
|
||||||
|
} _interrupts_statuses = {.int_status = 0, .battery_controller_status = false};
|
||||||
|
|
||||||
|
|
||||||
|
/* This call back is automatically called by the watch face when it wants to refresh the battery */
|
||||||
|
static void battery_indicator_cb(uint8_t *levelInPercent, BatteryState_e *batteryState)
|
||||||
|
{
|
||||||
|
*levelInPercent = _battery_percentage;
|
||||||
|
*batteryState = watch_peripherals_get_battery_controller_status();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void battery_controller_status_on_change_cb(battery_controller_status_e old, battery_controller_status_e new)
|
||||||
|
{
|
||||||
|
_interrupts_statuses.battery_controller_status = true;
|
||||||
|
}
|
||||||
|
|
||||||
static void setGetBrightnessCb(uint8_t *brightness, SettingMode_e mode)
|
static void setGetBrightnessCb(uint8_t *brightness, SettingMode_e mode)
|
||||||
{
|
{
|
||||||
@ -49,7 +66,10 @@ static void setGetBrightnessCb(uint8_t *brightness, SettingMode_e mode)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
persistency_get_settings()->display.display_brightness = *brightness;
|
// Updates the settings in the watch settings structure
|
||||||
|
watch_settings_display_set_brightness(*brightness);
|
||||||
|
|
||||||
|
// Physically apply the setting to the hardware
|
||||||
watch_peripherals_set_brightness(*brightness);
|
watch_peripherals_set_brightness(*brightness);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -102,7 +122,7 @@ static void setDisplayVibrationDuration(uint8_t *duration, SettingMode_e mode)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
persistency_get_settings()->display.display_vibrate_on_touch_duration = *duration;
|
watch_settings_display_set_vibrate_on_touch_duration(*duration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +134,7 @@ static void setDisplayVibrationStrength(uint8_t *strength, SettingMode_e mode)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
persistency_get_settings()->display.display_vibrate_on_touch_strength = *strength;
|
watch_settings_display_set_vibrate_on_touch_strength(*strength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +146,7 @@ static void setTimeoutCb(uint8_t *timeout, SettingMode_e mode)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
persistency_get_settings()->display.display_delay_before_sleep = *timeout;
|
watch_settings_display_set_delay_before_sleep(*timeout);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +158,7 @@ static void setOrientationCb(uint8_t *orientation, SettingMode_e mode)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
persistency_get_settings()->display.display_orientation = *orientation;
|
watch_settings_display_set_orientation(*orientation);
|
||||||
watch_peripherals_set_orientation(*orientation);
|
watch_peripherals_set_orientation(*orientation);
|
||||||
// Forces to redraw the full screen to avoid strange artifacts
|
// Forces to redraw the full screen to avoid strange artifacts
|
||||||
lv_obj_invalidate(lv_scr_act());
|
lv_obj_invalidate(lv_scr_act());
|
||||||
@ -153,10 +173,26 @@ static void setBLEEnabledCb(bool *enabled, SettingMode_e mode)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
persistency_get_settings()->connectivity.connectivity_ble_enabled = *enabled;
|
watch_settings_connectivity_set_ble_enabled(*enabled);
|
||||||
|
//Let's turn the BLE on or OFF here
|
||||||
|
if(*enabled)
|
||||||
|
{
|
||||||
|
if(!ble_modem_on(true))
|
||||||
|
APP_LOG_ERROR("Failed to start BLE modem with service");
|
||||||
|
else
|
||||||
|
watch_face_set_bluetooth_indicator(&watchFace, BLUETOOTH_STATE_ON);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!ble_modem_off())
|
||||||
|
APP_LOG_ERROR("Failed to stop BLE modem with service");
|
||||||
|
else
|
||||||
|
watch_face_set_bluetooth_indicator(&watchFace, BLUETOOTH_STATE_OFF);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This may never get implemented due to power consumption */
|
||||||
static void setWiFiEnabledCb(bool *enabled, SettingMode_e mode)
|
static void setWiFiEnabledCb(bool *enabled, SettingMode_e mode)
|
||||||
{
|
{
|
||||||
if(SETTING_MODE_GET == mode)
|
if(SETTING_MODE_GET == mode)
|
||||||
@ -165,7 +201,7 @@ static void setWiFiEnabledCb(bool *enabled, SettingMode_e mode)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
persistency_get_settings()->connectivity.connectivity_wifi_enabled = *enabled;
|
watch_settings_connectivity_set_wifi_enabled(*enabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,21 +213,46 @@ static void setLanguageCb(uint8_t *language, SettingMode_e mode)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
persistency_get_settings()->languageAndUI.language = *language;
|
watch_settings_language_and_UI_set_language(*language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void saveSettingsToFlash(void)
|
||||||
|
{
|
||||||
|
/*if(!persistency_save_settings_to_flash())
|
||||||
|
{
|
||||||
|
APP_LOG_ERROR("Failed to save watch settings to flash");
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void performFactoryReset()
|
||||||
|
{
|
||||||
|
// Reload factory settings
|
||||||
|
persistency_factory_reset();
|
||||||
|
|
||||||
|
if(!persistency_save_settings_to_flash())
|
||||||
|
{
|
||||||
|
APP_LOG_ERROR("Failed to save factory reset settings to flash");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We do a hardware reset of the watch
|
||||||
|
tls_sys_reset();
|
||||||
|
}
|
||||||
|
|
||||||
SettingsScreenAPIInterface_t settingsScreenAPIInterface =
|
SettingsScreenAPIInterface_t settingsScreenAPIInterface =
|
||||||
{
|
{
|
||||||
.setTimeSettingsCb = setTimeCb,
|
.setTimeSettingsCb = &(setTimeCb),
|
||||||
.setBrightnessSettingsCb = setGetBrightnessCb,
|
.setBrightnessSettingsCb = &(setGetBrightnessCb),
|
||||||
.setTimeoutSettingsCb = setTimeoutCb,
|
.setTimeoutSettingsCb = &(setTimeoutCb),
|
||||||
.setDisplayVibrationDurationSettingsCb = setDisplayVibrationDuration,
|
.setDisplayVibrationDurationSettingsCb = &(setDisplayVibrationDuration),
|
||||||
.setDisplayVibrationStrengthSettingsCb = setDisplayVibrationStrength,
|
.setDisplayVibrationStrengthSettingsCb = &(setDisplayVibrationStrength),
|
||||||
.setOrientationSettingsCb = setOrientationCb,
|
.setOrientationSettingsCb = &(setOrientationCb),
|
||||||
.setBLEEnabledSettingsCb = setBLEEnabledCb,
|
.setBLEEnabledSettingsCb = &(setBLEEnabledCb),
|
||||||
.setWiFiEnabledSettingsCb = setWiFiEnabledCb,
|
.setWiFiEnabledSettingsCb = &(setWiFiEnabledCb),
|
||||||
.setLanguageSettingsCb = setLanguageCb,
|
.setLanguageSettingsCb = &(setLanguageCb),
|
||||||
|
.saveSettingsCb = &(saveSettingsToFlash),
|
||||||
|
.factoryResetCb = &(performFactoryReset),
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint16_t angle_with_offset(uint16_t angle, uint16_t offset)
|
static uint16_t angle_with_offset(uint16_t angle, uint16_t offset)
|
||||||
@ -223,6 +284,21 @@ static void delay_us(uint32_t period, void *intf_ptr)
|
|||||||
tls_os_time_delay(pdMS_TO_TICKS(period / 1000));
|
tls_os_time_delay(pdMS_TO_TICKS(period / 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ble_service_state_change_cb(ble_service_state_e ble_service_state)
|
||||||
|
{
|
||||||
|
switch(ble_service_state)
|
||||||
|
{
|
||||||
|
case BLE_SERVICE_MODE_CONNECTED:
|
||||||
|
watch_face_set_bluetooth_indicator(&watchFace, BLUETOOTH_STATE_CONNECTED);
|
||||||
|
break;
|
||||||
|
case BLE_SERVICE_MODE_ADVERTISING:
|
||||||
|
watch_face_set_bluetooth_indicator(&watchFace, BLUETOOTH_STATE_ON);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void scan_result_cb(void)
|
static void scan_result_cb(void)
|
||||||
{
|
{
|
||||||
size_t buffer_size = sizeof(struct tls_scan_bss_format2_t) + sizeof(struct tls_bss_info_format2_t) * 10;
|
size_t buffer_size = sizeof(struct tls_scan_bss_format2_t) + sizeof(struct tls_bss_info_format2_t) * 10;
|
||||||
@ -262,11 +338,26 @@ static void scan_result_cb(void)
|
|||||||
|
|
||||||
void gfx_task(void *param)
|
void gfx_task(void *param)
|
||||||
{
|
{
|
||||||
APP_LOG_TRACE("starting");
|
APP_LOG_TRACE("GFX task starting");
|
||||||
|
|
||||||
/* Init and load watch settings using the persistency layer */
|
/* Init and load watch settings using the persistency layer */
|
||||||
persistency_init();
|
persistency_init();
|
||||||
|
|
||||||
|
if(!persistency_load_settings_from_flash())
|
||||||
|
{
|
||||||
|
APP_LOG_ERROR("Failed to retrieve watch settings from flash");
|
||||||
|
}
|
||||||
|
|
||||||
|
//persistency_debug();
|
||||||
|
|
||||||
|
/* Let's init the watch peripherals driver (vibration motor + battery voltage sense) */
|
||||||
|
watch_peripherals_init(27);
|
||||||
|
watch_peripherals_register_battery_controller_status_change_cb(&(battery_controller_status_on_change_cb));
|
||||||
|
|
||||||
|
/* Make the first battery voltage reading here */
|
||||||
|
uint16_t battery_voltage = watch_peripherals_get_battery_voltage(battery_unit_mv);
|
||||||
|
_battery_percentage = battery_voltage_to_percentage(battery_voltage);
|
||||||
|
|
||||||
/* Check whether the RTC is running or not, if not, then the board was reset
|
/* Check whether the RTC is running or not, if not, then the board was reset
|
||||||
So we start the RTC */
|
So we start the RTC */
|
||||||
if(!tls_is_rtc_running())
|
if(!tls_is_rtc_running())
|
||||||
@ -299,7 +390,7 @@ void gfx_task(void *param)
|
|||||||
lv_scr_load(watchFace.display);
|
lv_scr_load(watchFace.display);
|
||||||
|
|
||||||
/* Let's init the I2C interface */
|
/* Let's init the I2C interface */
|
||||||
i2c_init(I2C_SDA, I2C_SCL, 100000);
|
i2c_init(I2C_SDA, I2C_SCL, I2C_CLOCK_SPEED);
|
||||||
|
|
||||||
uint8_t aliveCounter = 0;
|
uint8_t aliveCounter = 0;
|
||||||
|
|
||||||
@ -374,7 +465,7 @@ void gfx_task(void *param)
|
|||||||
else
|
else
|
||||||
APP_LOG_INFO("BMA456 accel en failed");
|
APP_LOG_INFO("BMA456 accel en failed");
|
||||||
|
|
||||||
bma456w_feature_enable(BMA456W_WRIST_WEAR_WAKEUP, 1, &bma);
|
bma456w_feature_enable(BMA456W_WRIST_WEAR_WAKEUP, BMA4_ENABLE, &bma);
|
||||||
|
|
||||||
bma456w_get_wrist_wear_wakeup_param_config(&setting, &bma);
|
bma456w_get_wrist_wear_wakeup_param_config(&setting, &bma);
|
||||||
|
|
||||||
@ -401,19 +492,21 @@ void gfx_task(void *param)
|
|||||||
else
|
else
|
||||||
APP_LOG_INFO("BMA456 set pin conf failed");
|
APP_LOG_INFO("BMA456 set pin conf failed");
|
||||||
|
|
||||||
/* Let's init the watch peripherals driver (vibration motor + battery voltage sense) */
|
/* Configure BMA's step counter */
|
||||||
watch_peripherals_init(27);
|
if(bma456w_feature_enable(BMA456W_STEP_CNTR, BMA4_ENABLE, &bma) == BMA4_OK)
|
||||||
/* Make the first battery voltage reading here */
|
APP_LOG_INFO("BMA456 step cnter feature enable ok");
|
||||||
uint16_t battery_voltage = watch_peripherals_get_battery_voltage(battery_unit_mv);
|
else
|
||||||
battery_percentage = battery_voltage_to_percentage(battery_voltage);
|
APP_LOG_INFO("BMA456 step cnter feature enable failed");
|
||||||
watch_face_set_battery_indicator(&watchFace, battery_percentage);
|
|
||||||
|
/* Configure and register BLE stack and services callbacks */
|
||||||
|
ble_service_register_state_change_cb(&(ble_service_state_change_cb));
|
||||||
|
|
||||||
/* Once we are done with the initializing steps we
|
/* Once we are done with the initializing steps we
|
||||||
don't forget to turn the backlight on ! */
|
don't forget to turn the backlight on ! */
|
||||||
watch_peripherals_set_brightness(persistency_get_settings()->display.display_brightness);
|
watch_peripherals_set_brightness(persistency_get_settings()->display.display_brightness);
|
||||||
|
|
||||||
/* Enable WiFi hotspot scanning for antenna performance test purposes */
|
/* Enable WiFi hotspot scanning for antenna performance test purposes */
|
||||||
tls_wifi_scan_result_cb_register(&(scan_result_cb));
|
//tls_wifi_scan_result_cb_register(&(scan_result_cb));
|
||||||
|
|
||||||
extern LCDConfig_t LCDConfig;
|
extern LCDConfig_t LCDConfig;
|
||||||
float temperature = 0;
|
float temperature = 0;
|
||||||
@ -441,27 +534,33 @@ void gfx_task(void *param)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t rslt = bma456w_read_int_status(&int_status, &bma);
|
uint8_t rslt = bma456w_read_int_status(&_interrupts_statuses.int_status, &bma);
|
||||||
if(rslt != BMA4_OK)
|
if(rslt != BMA4_OK)
|
||||||
APP_LOG_DEBUG("Failed to read int status");
|
APP_LOG_DEBUG("Failed to read int status");
|
||||||
|
|
||||||
if((BMA4_OK == rslt) && (int_status & BMA456W_WRIST_WEAR_WAKEUP_INT))
|
if((BMA4_OK == rslt) && (_interrupts_statuses.int_status & BMA456W_WRIST_WEAR_WAKEUP_INT))
|
||||||
{
|
{
|
||||||
APP_LOG_DEBUG("Wrist tilt");
|
APP_LOG_DEBUG("Wrist tilt");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(++aliveCounter % 200 == 0)
|
if(++aliveCounter % 200 == 0)
|
||||||
{
|
{
|
||||||
|
uint32_t steps = 0;
|
||||||
|
if(bma456w_step_counter_output(&steps, &bma) != BMA4_OK)
|
||||||
|
APP_LOG_DEBUG("Failed to read step counts");
|
||||||
|
|
||||||
|
watch_face_set_step_count(&watchFace, steps);
|
||||||
|
|
||||||
pressure = BMP280_get_pressure(&temperature);
|
pressure = BMP280_get_pressure(&temperature);
|
||||||
BMP280_trigger_measurement();
|
BMP280_trigger_measurement();
|
||||||
battery_voltage = watch_peripherals_get_battery_voltage(battery_unit_mv);
|
battery_voltage = watch_peripherals_get_battery_voltage(battery_unit_mv);
|
||||||
battery_percentage = battery_voltage_to_percentage(battery_voltage);
|
_battery_percentage = battery_voltage_to_percentage(battery_voltage);
|
||||||
APP_LOG_DEBUG("GFX thread, temp : %0.2f °C, press : %0.2f hPa, bat(%d) : %u mV <-> %u %%",
|
APP_LOG_DEBUG("GFX thread, temp : %0.2f °C, press : %0.2f hPa, battery(%s) : %u mV <-> %u %%",
|
||||||
temperature,
|
temperature,
|
||||||
pressure/100,
|
pressure/100,
|
||||||
watch_peripherals_get_battery_controller_status(),
|
battery_controller_status_2_str(watch_peripherals_get_battery_controller_status()),
|
||||||
battery_voltage,
|
battery_voltage,
|
||||||
battery_percentage);
|
_battery_percentage);
|
||||||
|
|
||||||
//APP_LOG_DEBUG("Scanning WiFi : %d", tls_wifi_scan());
|
//APP_LOG_DEBUG("Scanning WiFi : %d", tls_wifi_scan());
|
||||||
|
|
||||||
@ -512,5 +611,15 @@ void gfx_task(void *param)
|
|||||||
APP_LOG_DEBUG("CPU 160Mhz");
|
APP_LOG_DEBUG("CPU 160Mhz");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle any interrupts status */
|
||||||
|
if(_interrupts_statuses.battery_controller_status)
|
||||||
|
{
|
||||||
|
_interrupts_statuses.battery_controller_status = false;
|
||||||
|
//Let's refresh the battery percentage as well:
|
||||||
|
battery_voltage = watch_peripherals_get_battery_voltage(battery_unit_mv);
|
||||||
|
_battery_percentage = battery_voltage_to_percentage(battery_voltage);
|
||||||
|
watch_face_set_battery_indicator(&watchFace, _battery_percentage, watch_peripherals_get_battery_controller_status());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,6 +4,27 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include "app_log.h"
|
#include "app_log.h"
|
||||||
|
|
||||||
|
LV_IMG_DECLARE(battery_low_icon)
|
||||||
|
LV_IMG_DECLARE(battery_charging_icon)
|
||||||
|
LV_IMG_DECLARE(battery_charged_icon)
|
||||||
|
|
||||||
|
static void _set_bluetooth_indicator(WatchFace_t * const watchFace)
|
||||||
|
{
|
||||||
|
switch(watchFace->bluetoothIndicator.bluetoothState)
|
||||||
|
{
|
||||||
|
case BLUETOOTH_STATE_ON:
|
||||||
|
lv_obj_set_style_img_recolor_opa(watchFace->bluetoothIndicator.bluetoothIcon, 185, LV_PART_MAIN);
|
||||||
|
lv_obj_clear_flag(watchFace->bluetoothIndicator.bluetoothIcon, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
break;
|
||||||
|
case BLUETOOTH_STATE_CONNECTED:
|
||||||
|
lv_obj_set_style_img_recolor_opa(watchFace->bluetoothIndicator.bluetoothIcon, 0, LV_PART_MAIN);
|
||||||
|
lv_obj_clear_flag(watchFace->bluetoothIndicator.bluetoothIcon, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
lv_obj_add_flag(watchFace->bluetoothIndicator.bluetoothIcon, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void gesture_event_cb(lv_event_t * e)
|
static void gesture_event_cb(lv_event_t * e)
|
||||||
{
|
{
|
||||||
WatchFace_t *watchFace = e->user_data;
|
WatchFace_t *watchFace = e->user_data;
|
||||||
@ -17,6 +38,7 @@ static void gesture_event_cb(lv_event_t * e)
|
|||||||
case LV_DIR_RIGHT:
|
case LV_DIR_RIGHT:
|
||||||
LV_LOG_USER("GESTURE : RIGHT");
|
LV_LOG_USER("GESTURE : RIGHT");
|
||||||
// We delete the timer
|
// We delete the timer
|
||||||
|
lv_timer_del(watchFace->batteryIndicator.lowBatteryAnimationTimer);
|
||||||
lv_timer_del(watchFace->handAnimationTimer);
|
lv_timer_del(watchFace->handAnimationTimer);
|
||||||
// We create the menu screen and switch to it
|
// We create the menu screen and switch to it
|
||||||
extern MenuScreen_t menuScreen;
|
extern MenuScreen_t menuScreen;
|
||||||
@ -60,11 +82,17 @@ static void update_watch_hands_angles(WatchFace_t * const watchFace, uint8_t inc
|
|||||||
|
|
||||||
//Don't forget to update the day date window
|
//Don't forget to update the day date window
|
||||||
sprintf(watchFace->dateWindow.dateWindowText, "%s%d", watchFace->dateTime.tm_mday < 10 ? " " : "", watchFace->dateTime.tm_mday);
|
sprintf(watchFace->dateWindow.dateWindowText, "%s%d", watchFace->dateTime.tm_mday < 10 ? " " : "", watchFace->dateTime.tm_mday);
|
||||||
lv_obj_invalidate(watchFace->dateWindow.dateWindowWidget);
|
lv_label_set_text_static(watchFace->dateWindow.dateWindowWidget, watchFace->dateWindow.dateWindowText);
|
||||||
|
|
||||||
APP_LOG_DEBUG("Syncing time");
|
APP_LOG_DEBUG("Syncing time");
|
||||||
|
|
||||||
if(watchFace->batteryIndicatorCb)
|
if(watchFace->batteryIndicatorCb)
|
||||||
watch_face_set_battery_indicator(watchFace, watchFace->batteryIndicatorCb());
|
{
|
||||||
|
uint8_t levelInPercent = 0;
|
||||||
|
BatteryState_e batteryState = BATTERY_STATE_DISCHARGING;
|
||||||
|
watchFace->batteryIndicatorCb(&levelInPercent, &batteryState);
|
||||||
|
watch_face_set_battery_indicator(watchFace, levelInPercent, batteryState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -93,6 +121,57 @@ static void hand_timer_anim_cb(lv_timer_t *timer)
|
|||||||
update_watch_hands_angles(watchFace, 12);
|
update_watch_hands_angles(watchFace, 12);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void battery_timer_anim_cb(lv_timer_t *timer)
|
||||||
|
{
|
||||||
|
WatchFace_t *watchFace = timer->user_data;
|
||||||
|
|
||||||
|
if(lv_obj_has_flag(watchFace->batteryIndicator.batteryIcon, LV_OBJ_FLAG_HIDDEN))
|
||||||
|
{
|
||||||
|
lv_obj_clear_flag(watchFace->batteryIndicator.batteryIcon, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lv_obj_add_flag(watchFace->batteryIndicator.batteryIcon, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_battery_state_icon(WatchFace_t * const watchFace)
|
||||||
|
{
|
||||||
|
switch(watchFace->batteryIndicator.batteryState)
|
||||||
|
{
|
||||||
|
case BATTERY_STATE_CHARGING:
|
||||||
|
lv_timer_pause(watchFace->batteryIndicator.lowBatteryAnimationTimer);
|
||||||
|
lv_obj_clear_flag(watchFace->batteryIndicator.batteryIcon, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_img_set_src(watchFace->batteryIndicator.batteryIcon, &battery_charging_icon);
|
||||||
|
break;
|
||||||
|
case BATTERY_STATE_CHARGED:
|
||||||
|
lv_timer_pause(watchFace->batteryIndicator.lowBatteryAnimationTimer);
|
||||||
|
lv_obj_clear_flag(watchFace->batteryIndicator.batteryIcon, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_img_set_src(watchFace->batteryIndicator.batteryIcon, &battery_charged_icon);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
lv_obj_add_flag(watchFace->batteryIndicator.batteryIcon, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_img_set_src(watchFace->batteryIndicator.batteryIcon, &battery_low_icon);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hide_hour_and_minutes_hand_cb(lv_event_t *e)
|
||||||
|
{
|
||||||
|
WatchFace_t *watchFace = e->user_data;
|
||||||
|
|
||||||
|
if(lv_obj_has_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN))
|
||||||
|
{
|
||||||
|
lv_obj_clear_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_obj_clear_flag(watchFace->minuteHand.handImg, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lv_obj_add_flag(watchFace->hourHand.handImg, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_obj_add_flag(watchFace->minuteHand.handImg, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void watch_face_init(WatchFace_t * const watchFace)
|
void watch_face_init(WatchFace_t * const watchFace)
|
||||||
{
|
{
|
||||||
if(!watchFace)
|
if(!watchFace)
|
||||||
@ -101,6 +180,7 @@ void watch_face_init(WatchFace_t * const watchFace)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
memset(watchFace, 0, sizeof(WatchFace_t));
|
memset(watchFace, 0, sizeof(WatchFace_t));
|
||||||
|
strcpy(watchFace->stepCounter.text, "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_face_register_date_time_cb(WatchFace_t * const watchFace, DateTimeCb_t dateTimeCb)
|
void watch_face_register_date_time_cb(WatchFace_t * const watchFace, DateTimeCb_t dateTimeCb)
|
||||||
@ -139,7 +219,8 @@ void watch_face_create(WatchFace_t * const watchFace)
|
|||||||
LV_IMG_DECLARE(watch_casio_minute_hand_asset)
|
LV_IMG_DECLARE(watch_casio_minute_hand_asset)
|
||||||
LV_IMG_DECLARE(watch_casio_second_hand_asset)
|
LV_IMG_DECLARE(watch_casio_second_hand_asset)
|
||||||
LV_IMG_DECLARE(watch_casio_medium_hand_asset)
|
LV_IMG_DECLARE(watch_casio_medium_hand_asset)
|
||||||
LV_IMG_DECLARE(watch_casio_small_hand_asset)
|
//LV_IMG_DECLARE(watch_casio_small_hand_asset)
|
||||||
|
LV_IMG_DECLARE(bluetooth_icon)
|
||||||
|
|
||||||
//We create our parent screen :
|
//We create our parent screen :
|
||||||
if(watchFace->display)
|
if(watchFace->display)
|
||||||
@ -152,30 +233,31 @@ void watch_face_create(WatchFace_t * const watchFace)
|
|||||||
watchFace->display = lv_img_create(NULL);
|
watchFace->display = lv_img_create(NULL);
|
||||||
lv_img_set_src(watchFace->display, &watch_casio_face_asset);
|
lv_img_set_src(watchFace->display, &watch_casio_face_asset);
|
||||||
lv_obj_set_style_bg_color(watchFace->display, lv_color_black(), LV_PART_MAIN);
|
lv_obj_set_style_bg_color(watchFace->display, lv_color_black(), LV_PART_MAIN);
|
||||||
|
lv_obj_add_event_cb(watchFace->display, &(hide_hour_and_minutes_hand_cb), LV_EVENT_LONG_PRESSED, watchFace);
|
||||||
|
|
||||||
//We load our other assets :
|
//We load our other assets :
|
||||||
lv_obj_t *smallHandImg = lv_img_create(watchFace->display);
|
/*lv_obj_t *smallHandImg = lv_img_create(watchFace->display);
|
||||||
lv_img_set_src(smallHandImg, &watch_casio_small_hand_asset);
|
lv_img_set_src(smallHandImg, &watch_casio_small_hand_asset);
|
||||||
lv_obj_set_pos(smallHandImg, 69, 98);
|
lv_obj_set_pos(smallHandImg, 69, 98);
|
||||||
lv_img_set_pivot(smallHandImg, 4, 20);
|
lv_img_set_pivot(smallHandImg, 4, 20);*/
|
||||||
|
|
||||||
//Battery arc is created here
|
//Battery arc is created here
|
||||||
if(watchFace->batteryIndicator.battery_arc)
|
if(watchFace->batteryIndicator.batteryArc)
|
||||||
{
|
{
|
||||||
LV_LOG_ERROR("battery_arc should be NULL here !");
|
LV_LOG_ERROR("batteryArc should be NULL here !");
|
||||||
lv_obj_del(watchFace->batteryIndicator.battery_arc);
|
lv_obj_del(watchFace->batteryIndicator.batteryArc);
|
||||||
watchFace->batteryIndicator.battery_arc = NULL;
|
watchFace->batteryIndicator.batteryArc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
watchFace->batteryIndicator.battery_arc = lv_arc_create(watchFace->display);
|
watchFace->batteryIndicator.batteryArc = lv_arc_create(watchFace->display);
|
||||||
lv_obj_remove_style(watchFace->batteryIndicator.battery_arc, NULL, LV_PART_KNOB);
|
lv_obj_remove_style(watchFace->batteryIndicator.batteryArc, NULL, LV_PART_KNOB);
|
||||||
lv_obj_clear_flag(watchFace->batteryIndicator.battery_arc, LV_OBJ_FLAG_CLICKABLE);
|
lv_obj_clear_flag(watchFace->batteryIndicator.batteryArc, LV_OBJ_FLAG_CLICKABLE);
|
||||||
lv_obj_set_size(watchFace->batteryIndicator.battery_arc, 60, 60);
|
lv_obj_set_size(watchFace->batteryIndicator.batteryArc, 60, 60);
|
||||||
lv_obj_align(watchFace->batteryIndicator.battery_arc, LV_ALIGN_CENTER, -1, 45);
|
lv_obj_align(watchFace->batteryIndicator.batteryArc, LV_ALIGN_CENTER, -1, 45);
|
||||||
lv_obj_set_style_arc_width(watchFace->batteryIndicator.battery_arc, 5, LV_PART_INDICATOR);
|
lv_obj_set_style_arc_width(watchFace->batteryIndicator.batteryArc, 5, LV_PART_INDICATOR);
|
||||||
lv_obj_set_style_arc_width(watchFace->batteryIndicator.battery_arc, 0, LV_PART_MAIN);
|
lv_obj_set_style_arc_width(watchFace->batteryIndicator.batteryArc, 0, LV_PART_MAIN);
|
||||||
lv_obj_set_style_arc_color(watchFace->batteryIndicator.battery_arc, lv_color_make(228, 233, 236), LV_PART_INDICATOR);
|
lv_obj_set_style_arc_color(watchFace->batteryIndicator.batteryArc, lv_color_make(228, 233, 236), LV_PART_INDICATOR);
|
||||||
lv_arc_set_value(watchFace->batteryIndicator.battery_arc, 100);
|
lv_arc_set_value(watchFace->batteryIndicator.batteryArc, 100);
|
||||||
|
|
||||||
if(watchFace->batteryIndicator.label)
|
if(watchFace->batteryIndicator.label)
|
||||||
{
|
{
|
||||||
@ -188,9 +270,57 @@ void watch_face_create(WatchFace_t * const watchFace)
|
|||||||
strcpy(watchFace->batteryIndicator.text, "100 %");
|
strcpy(watchFace->batteryIndicator.text, "100 %");
|
||||||
lv_label_set_text_static(watchFace->batteryIndicator.label, watchFace->batteryIndicator.text);
|
lv_label_set_text_static(watchFace->batteryIndicator.label, watchFace->batteryIndicator.text);
|
||||||
lv_obj_set_style_text_color(watchFace->batteryIndicator.label, lv_color_white(), LV_PART_MAIN);
|
lv_obj_set_style_text_color(watchFace->batteryIndicator.label, lv_color_white(), LV_PART_MAIN);
|
||||||
lv_obj_align_to(watchFace->batteryIndicator.label, watchFace->batteryIndicator.battery_arc, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align_to(watchFace->batteryIndicator.label, watchFace->batteryIndicator.batteryArc, LV_ALIGN_CENTER, 0, -5);
|
||||||
|
|
||||||
|
// Battery icon is created here
|
||||||
|
if(watchFace->batteryIndicator.batteryIcon)
|
||||||
|
{
|
||||||
|
LV_LOG_ERROR("batteryIcon should be NULL here !");
|
||||||
|
lv_obj_del(watchFace->batteryIndicator.batteryIcon);
|
||||||
|
watchFace->batteryIndicator.batteryIcon = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
watchFace->batteryIndicator.batteryIcon = lv_img_create(watchFace->display);
|
||||||
|
set_battery_state_icon(watchFace);
|
||||||
|
lv_img_set_zoom(watchFace->batteryIndicator.batteryIcon, 141);
|
||||||
|
lv_obj_align_to(watchFace->batteryIndicator.batteryIcon, watchFace->batteryIndicator.label, LV_ALIGN_OUT_BOTTOM_MID, 0, -9);
|
||||||
|
|
||||||
|
if(watchFace->batteryIndicator.lowBatteryAnimationTimer)
|
||||||
|
{
|
||||||
|
LV_LOG_ERROR("battery animation timer should be NULL here !");
|
||||||
|
lv_timer_del(watchFace->batteryIndicator.lowBatteryAnimationTimer);
|
||||||
|
watchFace->batteryIndicator.lowBatteryAnimationTimer = NULL;
|
||||||
|
}
|
||||||
|
watchFace->batteryIndicator.lowBatteryAnimationTimer = lv_timer_create(&(battery_timer_anim_cb), 500, watchFace);
|
||||||
|
lv_timer_pause(watchFace->batteryIndicator.lowBatteryAnimationTimer);
|
||||||
|
|
||||||
|
// Bluetooth status icon is created here
|
||||||
|
if(watchFace->bluetoothIndicator.bluetoothIcon)
|
||||||
|
{
|
||||||
|
LV_LOG_ERROR("bluetoothIcon be NULL here !");
|
||||||
|
lv_obj_del(watchFace->bluetoothIndicator.bluetoothIcon);
|
||||||
|
watchFace->bluetoothIndicator.bluetoothIcon = NULL;
|
||||||
|
}
|
||||||
|
watchFace->bluetoothIndicator.bluetoothIcon = lv_img_create(watchFace->display);
|
||||||
|
lv_img_set_src(watchFace->bluetoothIndicator.bluetoothIcon, &bluetooth_icon);
|
||||||
|
lv_img_set_zoom(watchFace->bluetoothIndicator.bluetoothIcon, 128);
|
||||||
|
lv_obj_add_flag(watchFace->bluetoothIndicator.bluetoothIcon, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
lv_obj_set_style_img_recolor(watchFace->bluetoothIndicator.bluetoothIcon, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
|
||||||
|
lv_obj_align_to(watchFace->bluetoothIndicator.bluetoothIcon, watchFace->batteryIndicator.batteryArc, LV_ALIGN_OUT_LEFT_BOTTOM, -9, 0);
|
||||||
|
_set_bluetooth_indicator(watchFace);
|
||||||
|
|
||||||
|
// StepCounter label is created here
|
||||||
|
if(watchFace->stepCounter.label)
|
||||||
|
{
|
||||||
|
LV_LOG_ERROR("stepCounter should be NULL here !");
|
||||||
|
lv_obj_del(watchFace->stepCounter.label);
|
||||||
|
watchFace->stepCounter.label = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
watchFace->stepCounter.label = lv_label_create(watchFace->display);
|
||||||
|
lv_label_set_text_static(watchFace->stepCounter.label, watchFace->stepCounter.text);
|
||||||
|
lv_obj_set_style_text_color(watchFace->stepCounter.label, lv_color_white(), LV_PART_MAIN);
|
||||||
|
lv_obj_set_pos(watchFace->stepCounter.label, 63, 111);
|
||||||
|
|
||||||
if(watchFace->mediumHand24h.handImg)
|
if(watchFace->mediumHand24h.handImg)
|
||||||
{
|
{
|
||||||
@ -278,7 +408,7 @@ void watch_face_create(WatchFace_t * const watchFace)
|
|||||||
watchFace->handAnimationTimer = lv_timer_create(&(hand_timer_anim_cb), 199, watchFace);
|
watchFace->handAnimationTimer = lv_timer_create(&(hand_timer_anim_cb), 199, watchFace);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_face_set_battery_indicator(WatchFace_t * const watchFace, uint8_t percentage)
|
void watch_face_set_battery_indicator(WatchFace_t * const watchFace, uint8_t levelInPercent, BatteryState_e batteryState)
|
||||||
{
|
{
|
||||||
if(!watchFace)
|
if(!watchFace)
|
||||||
{
|
{
|
||||||
@ -290,18 +420,73 @@ void watch_face_set_battery_indicator(WatchFace_t * const watchFace, uint8_t per
|
|||||||
|
|
||||||
lv_color_t arc_color = lv_color_make(228, 233, 236);
|
lv_color_t arc_color = lv_color_make(228, 233, 236);
|
||||||
|
|
||||||
if(percentage <= 10)
|
if(levelInPercent <= 10)
|
||||||
arc_color = lv_color_make(228, 33, 81);
|
arc_color = lv_color_make(228, 33, 81);
|
||||||
else if(percentage <= 30)
|
else if(levelInPercent <= 30)
|
||||||
arc_color = lv_color_make(247, 148, 29);
|
arc_color = lv_color_make(247, 148, 29);
|
||||||
else if(percentage <= 50)
|
else if(levelInPercent <= 50)
|
||||||
arc_color = lv_color_make(226, 175, 58);
|
arc_color = lv_color_make(226, 175, 58);
|
||||||
|
|
||||||
lv_arc_set_value(watchFace->batteryIndicator.battery_arc, percentage);
|
lv_arc_set_value(watchFace->batteryIndicator.batteryArc, levelInPercent);
|
||||||
lv_obj_set_style_arc_color(watchFace->batteryIndicator.battery_arc, arc_color, LV_PART_INDICATOR);
|
lv_obj_set_style_arc_color(watchFace->batteryIndicator.batteryArc, arc_color, LV_PART_INDICATOR);
|
||||||
sprintf(watchFace->batteryIndicator.text, "%u %%", percentage);
|
sprintf(watchFace->batteryIndicator.text, "%u %%", levelInPercent);
|
||||||
lv_label_set_text_static(watchFace->batteryIndicator.label, watchFace->batteryIndicator.text);
|
lv_label_set_text_static(watchFace->batteryIndicator.label, watchFace->batteryIndicator.text);
|
||||||
lv_obj_align_to(watchFace->batteryIndicator.label, watchFace->batteryIndicator.battery_arc, LV_ALIGN_CENTER, 0, 0);
|
lv_obj_align_to(watchFace->batteryIndicator.label, watchFace->batteryIndicator.batteryArc, LV_ALIGN_CENTER, 0, -5);
|
||||||
|
|
||||||
|
//We save the new battery state only if it's different, this allows to have a trigger when it changes :
|
||||||
|
if(watchFace->batteryIndicator.batteryState != batteryState)
|
||||||
|
{
|
||||||
|
watchFace->batteryIndicator.batteryState = batteryState;
|
||||||
|
set_battery_state_icon(watchFace);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Finally we check if it's time to show the battery low indicator by enabling it's timer
|
||||||
|
if(levelInPercent <= 10 && watchFace->batteryIndicator.batteryState == BATTERY_STATE_DISCHARGING)
|
||||||
|
{
|
||||||
|
lv_timer_resume(watchFace->batteryIndicator.lowBatteryAnimationTimer);
|
||||||
|
}
|
||||||
|
else if(watchFace->batteryIndicator.batteryState == BATTERY_STATE_DISCHARGING)
|
||||||
|
{
|
||||||
|
lv_timer_pause(watchFace->batteryIndicator.lowBatteryAnimationTimer);
|
||||||
|
lv_obj_add_flag(watchFace->batteryIndicator.batteryIcon, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void watch_face_set_bluetooth_indicator(WatchFace_t * const watchFace, BluetoothState_e bluetoothState)
|
||||||
|
{
|
||||||
|
if(!watchFace)
|
||||||
|
{
|
||||||
|
LV_LOG_ERROR("NULL pointer given !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(watchFace->bluetoothIndicator.bluetoothState == bluetoothState) return;
|
||||||
|
|
||||||
|
watchFace->bluetoothIndicator.bluetoothState = bluetoothState;
|
||||||
|
|
||||||
|
if(!watchFace->display) return;
|
||||||
|
|
||||||
|
_set_bluetooth_indicator(watchFace);
|
||||||
|
}
|
||||||
|
|
||||||
|
void watch_face_set_step_count(WatchFace_t * const watchFace, uint32_t step_count)
|
||||||
|
{
|
||||||
|
if(!watchFace)
|
||||||
|
{
|
||||||
|
LV_LOG_ERROR("NULL pointer given !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(step_count < 1000)
|
||||||
|
sprintf(watchFace->stepCounter.text, "%u", step_count);
|
||||||
|
else if(step_count < 9996)
|
||||||
|
sprintf(watchFace->stepCounter.text, "%.2fk", step_count/1000.0);
|
||||||
|
else
|
||||||
|
sprintf(watchFace->stepCounter.text, "%.1fk", step_count/1000.0);
|
||||||
|
|
||||||
|
if(!watchFace->display) return;
|
||||||
|
|
||||||
|
lv_label_set_text_static(watchFace->stepCounter.label, watchFace->stepCounter.text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_face_destroy(WatchFace_t * const watchFace)
|
void watch_face_destroy(WatchFace_t * const watchFace)
|
||||||
@ -319,8 +504,12 @@ void watch_face_destroy(WatchFace_t * const watchFace)
|
|||||||
watchFace->minuteHand.handImg = NULL;
|
watchFace->minuteHand.handImg = NULL;
|
||||||
watchFace->secondHand.handImg = NULL;
|
watchFace->secondHand.handImg = NULL;
|
||||||
watchFace->mediumHand24h.handImg = NULL;
|
watchFace->mediumHand24h.handImg = NULL;
|
||||||
watchFace->batteryIndicator.battery_arc = NULL;
|
watchFace->batteryIndicator.batteryArc = NULL;
|
||||||
watchFace->batteryIndicator.label = NULL;
|
watchFace->batteryIndicator.label = NULL;
|
||||||
|
watchFace->batteryIndicator.batteryIcon = NULL;
|
||||||
|
watchFace->batteryIndicator.lowBatteryAnimationTimer = NULL;
|
||||||
|
watchFace->stepCounter.label = NULL;
|
||||||
|
watchFace->bluetoothIndicator.bluetoothIcon = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void watch_face_force_sync(WatchFace_t *const watchFace)
|
void watch_face_force_sync(WatchFace_t *const watchFace)
|
||||||
|
@ -4,8 +4,23 @@
|
|||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
typedef enum BatteryState
|
||||||
|
{
|
||||||
|
BATTERY_STATE_DISCHARGING = 0,
|
||||||
|
BATTERY_STATE_CHARGING,
|
||||||
|
BATTERY_STATE_CHARGED,
|
||||||
|
} BatteryState_e;
|
||||||
|
|
||||||
|
typedef enum BluetoothState
|
||||||
|
{
|
||||||
|
BLUETOOTH_STATE_OFF = 0,
|
||||||
|
BLUETOOTH_STATE_ON,
|
||||||
|
BLUETOOTH_STATE_CONNECTED
|
||||||
|
} BluetoothState_e;
|
||||||
|
|
||||||
typedef void (*DateTimeCb_t)(struct tm * const dateTime);
|
typedef void (*DateTimeCb_t)(struct tm * const dateTime);
|
||||||
typedef uint8_t (*BatteryIndicatorCb_t)(void);
|
|
||||||
|
typedef void (*BatteryIndicatorCb_t)(uint8_t *levelInPercent, BatteryState_e *batteryState);
|
||||||
|
|
||||||
typedef struct DateWindow
|
typedef struct DateWindow
|
||||||
{
|
{
|
||||||
@ -22,10 +37,25 @@ typedef struct WatchHand
|
|||||||
typedef struct BatteryIndicator
|
typedef struct BatteryIndicator
|
||||||
{
|
{
|
||||||
lv_obj_t *label;
|
lv_obj_t *label;
|
||||||
lv_obj_t *battery_arc;
|
lv_obj_t *batteryArc;
|
||||||
|
lv_obj_t *batteryIcon;
|
||||||
|
lv_timer_t *lowBatteryAnimationTimer;
|
||||||
char text[7];
|
char text[7];
|
||||||
|
BatteryState_e batteryState:2;
|
||||||
} BatteryIndicator_t;
|
} BatteryIndicator_t;
|
||||||
|
|
||||||
|
typedef struct BluetoothIndicator
|
||||||
|
{
|
||||||
|
lv_obj_t *bluetoothIcon;
|
||||||
|
BluetoothState_e bluetoothState;
|
||||||
|
} BluetoothIndicator_t;
|
||||||
|
|
||||||
|
typedef struct StepCounter
|
||||||
|
{
|
||||||
|
lv_obj_t *label;
|
||||||
|
char text[7];
|
||||||
|
} StepCounter_t;
|
||||||
|
|
||||||
/* Watch face context object */
|
/* Watch face context object */
|
||||||
typedef struct WatchFace
|
typedef struct WatchFace
|
||||||
{
|
{
|
||||||
@ -39,7 +69,8 @@ typedef struct WatchFace
|
|||||||
lv_obj_t *display;
|
lv_obj_t *display;
|
||||||
DateWindow_t dateWindow;
|
DateWindow_t dateWindow;
|
||||||
BatteryIndicator_t batteryIndicator;
|
BatteryIndicator_t batteryIndicator;
|
||||||
|
StepCounter_t stepCounter;
|
||||||
|
BluetoothIndicator_t bluetoothIndicator;
|
||||||
struct tm dateTime;
|
struct tm dateTime;
|
||||||
} WatchFace_t;
|
} WatchFace_t;
|
||||||
|
|
||||||
@ -76,7 +107,25 @@ void watch_face_create(WatchFace_t * const watchFace);
|
|||||||
* @param watchFace a pointer to the watch face context structure.
|
* @param watchFace a pointer to the watch face context structure.
|
||||||
* @param percentage the value to set the indicator to in percent.
|
* @param percentage the value to set the indicator to in percent.
|
||||||
*/
|
*/
|
||||||
void watch_face_set_battery_indicator(WatchFace_t * const watchFace, uint8_t percentage);
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the battery level in percent as well as it's current state to draw on the watch face.
|
||||||
|
*
|
||||||
|
* @param watchFace a pointer to the watch face context structure.
|
||||||
|
* @param levelInPercent the level to set the indicator to in percent.
|
||||||
|
* @param batteryState the current state of the battery : BATTERY_STATE_DISCHARGING, BATTERY_STATE_CHARGING or BATTERY_STATE_CHARGED
|
||||||
|
*/
|
||||||
|
void watch_face_set_battery_indicator(WatchFace_t * const watchFace, uint8_t levelInPercent, BatteryState_e batteryState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the current bluetooth state to display on the watch face
|
||||||
|
*
|
||||||
|
* @param watchFace a pointer to the watch face context structure.
|
||||||
|
* @param bluetoothState the state of the bluetooth modem to show, can be : BLUETOOTH_STATE_OFF, BLUETOOTH_STATE_ON or BLUETOOTH_STATE_CONNECTED
|
||||||
|
*/
|
||||||
|
void watch_face_set_bluetooth_indicator(WatchFace_t * const watchFace, BluetoothState_e bluetoothState);
|
||||||
|
|
||||||
|
void watch_face_set_step_count(WatchFace_t * const watchFace, uint32_t step_count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Forces the watch face to sync up with the RTC by calling the provided date_time_cb
|
* @brief Forces the watch face to sync up with the RTC by calling the provided date_time_cb
|
||||||
|
@ -55,8 +55,10 @@ static void touch_panel_feedback_cb(struct _lv_indev_drv_t *lv_indev_drv, uint8_
|
|||||||
{
|
{
|
||||||
(void)lv_indev_drv;
|
(void)lv_indev_drv;
|
||||||
|
|
||||||
uint32_t vibration_duration_ms = persistency_get_settings()->display.display_vibrate_on_touch_duration*50;
|
|
||||||
uint16_t vibration_strength = persistency_get_settings()->display.display_vibrate_on_touch_strength*32;
|
uint16_t vibration_strength = persistency_get_settings()->display.display_vibrate_on_touch_strength*32;
|
||||||
|
uint32_t vibration_duration_ms = 0;
|
||||||
|
if(persistency_get_settings()->display.display_vibrate_on_touch_duration)
|
||||||
|
vibration_duration_ms = persistency_get_settings()->display.display_vibrate_on_touch_duration*50 + 50;
|
||||||
|
|
||||||
switch(lv_event_code)
|
switch(lv_event_code)
|
||||||
{
|
{
|
||||||
|
@ -167,14 +167,14 @@ tls_bt_init(uint8_t uart_idx)
|
|||||||
ble_hs_cfg.gatts_register_cb = on_svr_register_cb;
|
ble_hs_cfg.gatts_register_cb = on_svr_register_cb;
|
||||||
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
|
ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
|
||||||
/* Initialize all packages. */
|
/* Initialize all packages. */
|
||||||
nimble_port_init();
|
nimble_port_init(); // 7 k ram gone --> 112691
|
||||||
/*Application levels code entry*/
|
/*Application levels code entry*/
|
||||||
tls_ble_gap_init();
|
tls_ble_gap_init(); // 0k ram gone
|
||||||
tls_bt_util_init();
|
tls_bt_util_init(); // 0k ram gone
|
||||||
/*Initialize the vuart interface and enable controller*/
|
/*Initialize the vuart interface and enable controller*/
|
||||||
ble_hci_vuart_init(uart_idx);
|
ble_hci_vuart_init(uart_idx); // 47k gone --> 65423
|
||||||
/* As the last thing, process events from default event queue. */
|
/* As the last thing, process events from default event queue. */
|
||||||
tls_nimble_start();
|
tls_nimble_start(); // 3k gone --> 62175
|
||||||
|
|
||||||
while(bt_adapter_state == WM_BT_STATE_OFF) {
|
while(bt_adapter_state == WM_BT_STATE_OFF) {
|
||||||
tls_os_time_delay(10);
|
tls_os_time_delay(10);
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/** NOT PART OF THE OFFICIAL SDK **/
|
||||||
|
int tls_bt_init(uint8_t uart_idx);
|
||||||
|
int tls_bt_deinit(void);
|
||||||
|
/**********************************/
|
||||||
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
WM_BT_SYSTEM_ACTION_IDLE,
|
WM_BT_SYSTEM_ACTION_IDLE,
|
||||||
|
@ -109,9 +109,6 @@ const char *tls_bt_gap_evt_2_str(uint32_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define BLE_HS_ENOERR 0
|
|
||||||
|
|
||||||
const char *tls_bt_rc_2_str(uint32_t event)
|
const char *tls_bt_rc_2_str(uint32_t event)
|
||||||
{
|
{
|
||||||
switch(event) {
|
switch(event) {
|
||||||
@ -153,7 +150,33 @@ const char *tls_bt_rc_2_str(uint32_t event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *tls_bt_addr_type_2_str(uint8_t addr_type)
|
||||||
|
{
|
||||||
|
switch(addr_type)
|
||||||
|
{
|
||||||
|
CASE_RETURN_STR(BLE_OWN_ADDR_PUBLIC)
|
||||||
|
CASE_RETURN_STR(BLE_OWN_ADDR_RANDOM)
|
||||||
|
CASE_RETURN_STR(BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT)
|
||||||
|
CASE_RETURN_STR(BLE_OWN_ADDR_RPA_RANDOM_DEFAULT)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "unknown addr_type";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *tls_bt_access_opt_2_str(uint8_t op)
|
||||||
|
{
|
||||||
|
switch(op)
|
||||||
|
{
|
||||||
|
CASE_RETURN_STR(BLE_GATT_ACCESS_OP_READ_CHR)
|
||||||
|
CASE_RETURN_STR(BLE_GATT_ACCESS_OP_WRITE_CHR)
|
||||||
|
CASE_RETURN_STR(BLE_GATT_ACCESS_OP_READ_DSC)
|
||||||
|
CASE_RETURN_STR(BLE_GATT_ACCESS_OP_WRITE_DSC)
|
||||||
|
|
||||||
|
default:
|
||||||
|
return "unknown operation type";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void async_evt_func(struct ble_npl_event *ev)
|
static void async_evt_func(struct ble_npl_event *ev)
|
||||||
{
|
{
|
||||||
|
@ -47,12 +47,15 @@ extern tls_bt_log_level_t tls_appl_trace_level;
|
|||||||
#define TLS_BT_APPL_TRACE_EVENT(...)
|
#define TLS_BT_APPL_TRACE_EVENT(...)
|
||||||
#define TLS_BT_APPL_TRACE_DEBUG(...)
|
#define TLS_BT_APPL_TRACE_DEBUG(...)
|
||||||
#define TLS_BT_APPL_TRACE_VERBOSE(...)
|
#define TLS_BT_APPL_TRACE_VERBOSE(...)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define BLE_HS_ENOERR 0
|
||||||
|
|
||||||
void tls_bt_log(uint32_t trace_set_mask, const char *fmt_str, ...);
|
void tls_bt_log(uint32_t trace_set_mask, const char *fmt_str, ...);
|
||||||
const char *tls_bt_gap_evt_2_str(uint32_t event);
|
const char *tls_bt_gap_evt_2_str(uint32_t event);
|
||||||
const char *tls_bt_rc_2_str(uint32_t event);
|
const char *tls_bt_rc_2_str(uint32_t event);
|
||||||
|
const char *tls_bt_addr_type_2_str(uint8_t addr_type);
|
||||||
|
const char *tls_bt_access_opt_2_str(uint8_t op);
|
||||||
|
|
||||||
extern int tls_bt_util_init(void);
|
extern int tls_bt_util_init(void);
|
||||||
extern int tls_bt_util_deinit(void);
|
extern int tls_bt_util_deinit(void);
|
||||||
|
@ -61,11 +61,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT
|
#ifndef MYNEWT_VAL_MSYS_1_BLOCK_COUNT
|
||||||
#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (24)
|
#define MYNEWT_VAL_MSYS_1_BLOCK_COUNT (10)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE
|
#ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE
|
||||||
#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (292)
|
#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (100) // Default 292
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MYNEWT_VAL_MSYS_1_SANITY_MIN_COUNT
|
#ifndef MYNEWT_VAL_MSYS_1_SANITY_MIN_COUNT
|
||||||
@ -925,7 +925,7 @@
|
|||||||
|
|
||||||
/*** @apache-mynewt-nimble/nimble/transport/socket */
|
/*** @apache-mynewt-nimble/nimble/transport/socket */
|
||||||
#ifndef MYNEWT_VAL_BLE_ACL_BUF_COUNT
|
#ifndef MYNEWT_VAL_BLE_ACL_BUF_COUNT
|
||||||
#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (36)
|
#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (8) // Default 36
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MYNEWT_VAL_BLE_ACL_BUF_SIZE
|
#ifndef MYNEWT_VAL_BLE_ACL_BUF_SIZE
|
||||||
@ -947,11 +947,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT
|
#ifndef MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT
|
||||||
#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (16)
|
#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (5) // Default 16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT
|
#ifndef MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT
|
||||||
#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT (96)
|
#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT (5) // Default 96
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef MYNEWT_VAL_BLE_SOCK_CLI_SYSINIT_STAGE
|
#ifndef MYNEWT_VAL_BLE_SOCK_CLI_SYSINIT_STAGE
|
||||||
|
@ -17,7 +17,7 @@ void tls_nimble_start(void)
|
|||||||
{
|
{
|
||||||
tls_host_task_stack_ptr = (void *)tls_mem_alloc(MYNEWT_VAL(OS_HS_STACK_SIZE) * sizeof(uint32_t));
|
tls_host_task_stack_ptr = (void *)tls_mem_alloc(MYNEWT_VAL(OS_HS_STACK_SIZE) * sizeof(uint32_t));
|
||||||
assert(tls_host_task_stack_ptr != NULL);
|
assert(tls_host_task_stack_ptr != NULL);
|
||||||
tls_os_task_create(&tls_host_task_hdl, "bth",
|
tls_os_task_create(&tls_host_task_hdl, "ble_svc",
|
||||||
nimble_host_task,
|
nimble_host_task,
|
||||||
(void *)0,
|
(void *)0,
|
||||||
(void *)tls_host_task_stack_ptr,
|
(void *)tls_host_task_stack_ptr,
|
||||||
|
@ -43,21 +43,22 @@ INCLUDES += -I $(TOP_DIR)/src/os/rtos/include
|
|||||||
|
|
||||||
INCLUDES += -I $(TOP_DIR)/src/app/factorycmd
|
INCLUDES += -I $(TOP_DIR)/src/app/factorycmd
|
||||||
INCLUDES += -I $(TOP_DIR)/src/app/bleapp
|
INCLUDES += -I $(TOP_DIR)/src/app/bleapp
|
||||||
INCLUDES += -I $(TOP_DIR)/app/app_include
|
|
||||||
|
INCLUDES += -I $(TOP_DIR)/app
|
||||||
INCLUDES += -I $(TOP_DIR)/app/app_drivers/lcd
|
INCLUDES += -I $(TOP_DIR)/app/app_drivers/lcd
|
||||||
INCLUDES += -I $(TOP_DIR)/app/app_drivers/mmc_sdio
|
INCLUDES += -I $(TOP_DIR)/app/app_drivers/mmc_sdio
|
||||||
INCLUDES += -I $(TOP_DIR)/app/app_drivers/i2c
|
INCLUDES += -I $(TOP_DIR)/app/app_drivers/i2c
|
||||||
INCLUDES += -I $(TOP_DIR)/app/app_drivers/watch_peripherals
|
INCLUDES += -I $(TOP_DIR)/app/app_drivers/watch_peripherals
|
||||||
|
INCLUDES += -I $(TOP_DIR)/app/app_include
|
||||||
|
INCLUDES += -I $(TOP_DIR)/app/ble
|
||||||
|
INCLUDES += -I $(TOP_DIR)/app/gfx
|
||||||
INCLUDES += -I $(TOP_DIR)/app/persistency
|
INCLUDES += -I $(TOP_DIR)/app/persistency
|
||||||
INCLUDES += -I $(TOP_DIR)/app/translation
|
INCLUDES += -I $(TOP_DIR)/app/translation
|
||||||
INCLUDES += -I $(TOP_DIR)/app/gfx
|
|
||||||
INCLUDES += -I $(TOP_DIR)/app
|
|
||||||
|
|
||||||
#lvgl include
|
#lvgl include
|
||||||
INCLUDES += -I $(TOP_DIR)/lvgl/lvgl_v8.3
|
INCLUDES += -I $(TOP_DIR)/lvgl/lvgl_v8.3
|
||||||
INCLUDES += -I $(TOP_DIR)/lvgl/lvgl_port
|
INCLUDES += -I $(TOP_DIR)/lvgl/lvgl_port
|
||||||
|
|
||||||
|
|
||||||
#nimble host
|
#nimble host
|
||||||
INCLUDES += -I $(TOP_DIR)/src/bt/blehost/ext/tinycrypt/include
|
INCLUDES += -I $(TOP_DIR)/src/bt/blehost/ext/tinycrypt/include
|
||||||
INCLUDES += -I $(TOP_DIR)/src/bt/blehost/nimble/host/include
|
INCLUDES += -I $(TOP_DIR)/src/bt/blehost/nimble/host/include
|
||||||
|
Loading…
Reference in New Issue
Block a user