Compare commits

...

8 Commits

Author SHA1 Message Date
anschrammh
e2fb8b3822 Reworked the watch's sleep feature and internal workings, added a new sleep mode when BLE is enabled, now sending the watch's battery level, voltage and state to the GadgetBridge app when it connects to the watch 2023-04-13 13:41:42 +02:00
anschrammh
9f241454c6 Finally reworked the way date and time are set so that they have the expected value and behaviour 2023-04-13 13:40:00 +02:00
anschrammh
0789cc62ad Commented debug traces out so that they are not diplayed on the serial port anymore 2023-04-13 13:38:50 +02:00
anschrammh
82ad6d16ba Added a function in the lvgl input device binding file to be able to know if the touch screen was touched or not 2023-04-13 13:37:50 +02:00
anschrammh
c885568e34 Wrapped and added new functions to the watch_peripherals module to be able to prepare the watch for different sleep modes, and being able to detect different wakeup sources. Changed the function used for the BMA456 driver required micro seconds delay 2023-04-13 13:36:48 +02:00
anschrammh
92de986dba Added a new event to the ble_service_state_change event callback function to be able to detect when a BLE master device subscribed to a particular characteristic. Also reworked the allocated buffers for the BLE stack, because of a strage issue, where it is hard for the phone to reconnect to the watch. 2023-04-13 13:34:38 +02:00
anschrammh
cfc42779dd Added new app_utils module/lib containing miscellaneous utility functions like blocking delays and such. Still need to fully implement the elapsed_ms function. 2023-04-13 13:31:54 +02:00
anschrammh
4184be2763 Changed the way the lvgl tick is handled, it was previously called from
the FreeRTOS vApplicationTickHook function and is now called by a timer
interrupt every ms. This permits to stop the timer and thus lvgl when it
is not needed.
2023-04-13 13:27:07 +02:00
19 changed files with 483 additions and 110 deletions

View File

@ -30,11 +30,12 @@ endif
endif
COMPONENTS_$(TARGET) = \
$(TOP_DIR)/app/libuser$(LIB_EXT) \
$(TOP_DIR)/app/app_drivers/libappdrivers$(LIB_EXT) \
$(TOP_DIR)/app/libuser$(LIB_EXT) \
$(TOP_DIR)/app/app_drivers/libappdrivers$(LIB_EXT) \
$(TOP_DIR)/app/persistency/libpersistency$(LIB_EXT) \
$(TOP_DIR)/app/translation/libtranslation$(LIB_EXT) \
$(TOP_DIR)/app/ble/libble$(LIB_EXT) \
$(TOP_DIR)/app/ble/libble$(LIB_EXT) \
$(TOP_DIR)/app/app_utils/libapputils$(LIB_EXT) \
$(TOP_DIR)/lvgl/liblvgl$(LIB_EXT)
ifeq ($(USE_LIB), 0)

View File

@ -7,8 +7,9 @@
#include "wm_pwm.h"
#include "i2c.h"
#include "BMP280.h"
#include "FreeRTOS.h" // <---- Only needed for the pdMS_TO_TICKS macro, to be removed
#include "bma456w.h"
#include "CST816D.h"
#include "app_utils.h"
#define INTERRUPT_POLICY (0)
#define POLL_POLICY (1)
@ -25,6 +26,10 @@ static uint8_t _vibration_motor_timer_id = WM_TIMER_ID_INVALID;
static battery_controller_status_e _battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING;
static BatteryControllerStatusChangeCb_t _BatteryControllerStatusChangeCb = NULL;
/* Wakeup source boolean */
static bool _wakeup_is_io = false;
static bool _wakeup_is_timer = false;
/* BMA456 strcture */
struct
{
@ -128,6 +133,23 @@ static void battery_controller_irq_cb(void *p)
}
#endif
typedef enum wakeup_source
{
WAKEUP_SOURCE_IO = 0,
WAKEUP_SOURCE_TIMER,
} wakeup_source_e;
static void pmu_wakeup_source_irq_cb(void *arg)
{
wakeup_source_e wakeup_source = (wakeup_source_e)arg;
if(wakeup_source == WAKEUP_SOURCE_IO)
_wakeup_is_io = true;
if(wakeup_source == WAKEUP_SOURCE_TIMER)
_wakeup_is_timer = true;
}
static void watch_peripherals_io_init(void)
{
/* We initialize the ADC input as well as the gpio used to enabled the voltage divider bridge */
@ -150,6 +172,10 @@ static void watch_peripherals_io_init(void)
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
/* We register the IRQs needed to determine the watch wake up source/reason */
tls_pmu_gpio_isr_register(&(pmu_wakeup_source_irq_cb), (void *)WAKEUP_SOURCE_IO);
tls_pmu_timer0_isr_register(&(pmu_wakeup_source_irq_cb), (void *)WAKEUP_SOURCE_TIMER);
}
#ifndef CASE_RETURN_STR
@ -289,6 +315,26 @@ void watch_peripherals_set_orientation(LCDOrientation_e orientation)
lcd_orientation(&LCDConfig, orientation);
}
bool watch_peripherals_wakeup_source_is_user(void)
{
if(_wakeup_is_io)
{
_wakeup_is_io = false;
return true;
}
return false;
}
bool watch_peripherals_wakeup_source_is_timer(void)
{
if(_wakeup_is_timer)
{
_wakeup_is_timer = false;
return true;
}
return false;
}
bool watch_peripherals_magnetometer_init(void)
{
/* Init the magnetometer */
@ -405,11 +451,7 @@ static BMA4_INTF_RET_TYPE _bma4_i2c_write(uint8_t reg_addr, const uint8_t *read_
static void _bma4_delay_us(uint32_t period, void *intf_ptr)
{
(void) intf_ptr;
if(period < 1000)
tls_os_time_delay(1);
else
tls_os_time_delay(pdMS_TO_TICKS(period / 1000));
us_delay(period);
}
bool watch_peripherals_accelerometer_init(void)
@ -594,3 +636,17 @@ bool watch_peripherals_accelerometer_step_count_reset(void)
return true;
}
void watch_peripherals_watch_sleep(void)
{
extern LCDConfig_t LCDConfig;
// First, we disable the display backlight and we set all the peripherals in their low power mode
lcd_set_backlight(&LCDConfig, 0);
//lcd_on(&LCDConfig, false);
lcd_sleep(&LCDConfig, true);
watch_peripherals_magnetometer_power_mode_set(QMC5883L_Mode_Control_Standby);
if(CST816D_sleep())
APP_LOG_DEBUG("CST816D Sleep cmd ok");
else
APP_LOG_ERROR("CST816D Sleep cmd fail");
}

View File

@ -101,6 +101,22 @@ void watch_peripherals_set_brightness(uint8_t brightness);
*/
void watch_peripherals_set_orientation(LCDOrientation_e orientation);
/**
* @brief Check if the watch woke up because of the user(trigger on the wakeup pin : wrist tilt or touch screen).
*
* @return true if the source of the wakeup is the user
* @return false otherwise
*/
bool watch_peripherals_wakeup_source_is_user(void);
/**
* @brief Check if the watch woke up because of a timed event (timer 0 of the PMU module).
*
* @return true if the source of the wake up is the timer 0
* @return false otherwise
*/
bool watch_peripherals_wakeup_source_is_timer(void);
bool watch_peripherals_magnetometer_init(void);
void watch_peripherals_magnetometer_calibration_data_set(
@ -131,4 +147,6 @@ bool watch_peripherals_accelerometer_step_count_read(uint32_t *step_count);
bool watch_peripherals_accelerometer_step_count_reset(void);
void watch_peripherals_watch_sleep(void);
#endif //WATCH_PERIPHERALS_H

View File

@ -0,0 +1,15 @@
TOP_DIR = ../..
sinclude $(TOP_DIR)/tools/w800/conf.mk
ifndef PDIR
GEN_LIBS = libapputils$(LIB_EXT)
endif
#DEFINES +=
sinclude $(TOP_DIR)/tools/w800/rules.mk
INCLUDES := $(INCLUDES) -I $(PDIR)include
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile

View File

@ -0,0 +1,61 @@
#include "app_utils.h"
#include "app_log.h"
static uint32_t _elapsed_ms = 0;
void us_delay(uint32_t us)
{
struct tls_timer_cfg timer_config =
{
.is_repeat = false,
.unit = TLS_TIMER_UNIT_US,
.timeout = 0xFFFFFFFF,
};
uint8_t timer_id = tls_timer_create(&timer_config);
if(WM_TIMER_ID_INVALID == timer_id)
{
APP_LOG_ERROR("Failed to create timer");
return;
}
tls_timer_start(timer_id);
// Perform a blocking delay
while(tls_timer_read(timer_id) < us);
// Don't forget to free the used timer
tls_timer_destroy(timer_id);
}
void ms_delay(uint32_t ms)
{
struct tls_timer_cfg timer_config =
{
.is_repeat = false,
.unit = TLS_TIMER_UNIT_MS,
.timeout = 0xFFFFFFFF,
};
uint8_t timer_id = tls_timer_create(&timer_config);
if(WM_TIMER_ID_INVALID == timer_id)
{
APP_LOG_ERROR("Failed to create timer");
return;
}
tls_timer_start(timer_id);
// Perform a blocking delay
while(tls_timer_read(timer_id) < ms);
// Don't forget to free the used timer
tls_timer_destroy(timer_id);
}
uint32_t elapsed_ms(void)
{
return _elapsed_ms;
}

View File

@ -0,0 +1,27 @@
#ifndef APP_UTILS_H
#define APP_UTILS_H
#include "wm_include.h"
/**
* @brief Wait for the specified time in micro seconds. This is a blocking function !
*
* @param us the specified time to wait in µs.
*/
void us_delay(uint32_t us);
/**
* @brief Wait for the specified time in milli seconds. This is a blocking function !
*
* @param ms the specified time to wait in ms.
*/
void ms_delay(uint32_t ms);
/**
* @brief Returns the current milli seconds count elapsed since the start of the program.
*
* @return uint32_t the elapsed time in ms
*/
uint32_t elapsed_ms(void);
#endif //APP_UTILS_H

View File

@ -660,6 +660,12 @@ static int ble_gap_event_cb(struct ble_gap_event *event, void *arg)
event->subscribe.cur_notify,
event->subscribe.prev_notify
);
if(gatt_nus_char_tx_handle == event->subscribe.attr_handle && (event->subscribe.cur_notify || event->subscribe.cur_indicate))
{
//We call the state change callback if registered
if(_ble_service_state_change_cb)_ble_service_state_change_cb(BLE_SERVICE_MODE_SUBSCRIBED);
}
break;
case BLE_GAP_EVENT_MTU:
TLS_BT_APPL_TRACE_VERBOSE("MTU update : %u"NEW_LINE, event->mtu.value);

View File

@ -15,6 +15,7 @@ typedef enum
BLE_SERVICE_MODE_IDLE,
BLE_SERVICE_MODE_ADVERTISING,
BLE_SERVICE_MODE_CONNECTED,
BLE_SERVICE_MODE_SUBSCRIBED,
BLE_SERVICE_MODE_INDICATING,
BLE_SERVICE_MODE_EXITING
} ble_service_state_e;

View File

@ -1,7 +1,9 @@
#include "app_common.h"
#include "app_utils.h"
#include "lvgl.h"
#include "lv_port_disp.h"
#include "lv_port_indev.h"
#include "lv_port_tick.h"
#include "FreeRTOS.h"
#include "wm_include.h"
#include "lcd.h"
@ -9,9 +11,9 @@
#include "menu_screen.h"
#include "compass_screen.h"
#include "settings_screen.h"
#include "CST816D.h"
#include "watch_peripherals.h"
#include "watch_settings.h"
#include "firmware_version.h"
#include "ble_modem.h"
#include "ble_service.h"
@ -23,6 +25,7 @@ static void date_time_cb(struct tm * const dateTime)
tls_get_rtc(dateTime);
}
bool _is_in_ble_sleep_mode = false;
static void _perform_deferred_display_wake_up_set_timestamp(void);
static void _perform_deferred_display_wake_up(uint8_t deferred_time_in_ms);
@ -358,6 +361,12 @@ static void ble_service_state_change_cb(ble_service_state_e ble_service_state)
case BLE_SERVICE_MODE_ADVERTISING:
watch_face_set_bluetooth_indicator(&watchFace, BLUETOOTH_STATE_ON);
break;
case BLE_SERVICE_MODE_SUBSCRIBED:
/* We also set the current watch firmware version */
gadget_bridge_send_firmware_version(FIRMWARE_VERSION, NULL);
/* We send the current battery level and battery state (charging or not)*/
gadget_bridge_send_battery_status(_battery_stats.battery_percentage, _battery_stats.battery_voltage/1000.0, watch_peripherals_get_battery_controller_status() != BATTERY_CONTROLLER_STATUS_DISCHARGING);
break;
default:
break;
}
@ -449,6 +458,9 @@ void gfx_task(void *param)
lv_port_disp_init();
lv_port_indev_init();
lv_port_tick_init();
lv_port_tick_start();
/* Initialize lvgl screens */
watch_face_init(&watchFace);
@ -484,99 +496,133 @@ void gfx_task(void *param)
for(;;)
{
lv_timer_handler();
tls_os_time_delay(5);
if(compass_screen_is_in_use(&compassScreen))
/* Actions to perform when the watch is active only */
if(!_is_in_ble_sleep_mode)
{
bool is_data_available = false;
uint16_t azimuth = watch_peripherals_magnetometer_azimuth_read(&is_data_available);
lv_timer_handler();
tls_os_time_delay(5);
if(is_data_available)
if(compass_screen_is_in_use(&compassScreen))
{
/*
QMC5883L_MData_t MDataRaw = watch_peripherals_magnetometer_raw_data_read();
APP_LOG_TRACE("X %d Y %d Z %d", MDataRaw.MFieldX, MDataRaw.MFieldY, MDataRaw.MFieldZ);
*/
bool is_data_available = false;
uint16_t azimuth = watch_peripherals_magnetometer_azimuth_read(&is_data_available);
compass_screen_set_azimuth(&compassScreen, angle_with_offset(azimuth, 180));
if(is_data_available)
{
/*
QMC5883L_MData_t MDataRaw = watch_peripherals_magnetometer_raw_data_read();
APP_LOG_TRACE("X %d Y %d Z %d", MDataRaw.MFieldX, MDataRaw.MFieldY, MDataRaw.MFieldZ);
*/
compass_screen_set_azimuth(&compassScreen, angle_with_offset(azimuth, 180));
}
compass_screen_set_temperature(&compassScreen, temperature);
}
compass_screen_set_temperature(&compassScreen, temperature);
}
/* To rework */
if(lv_tick_elaps(update_tick) > 5000)
{
pressure = watch_peripherals_pressure_sensor_get_pressure(&temperature);
if(watch_peripherals_accelerometer_wrist_wakeup_interrupt())
_battery_stats.battery_voltage = watch_peripherals_get_battery_voltage(battery_unit_mv);
_battery_stats.battery_percentage = battery_voltage_to_percentage(_battery_stats.battery_voltage);
APP_LOG_DEBUG("GFX thread, temp : %0.2f °C, press : %0.2f hPa, battery(%s) : %u mV <-> %u %%",
temperature,
pressure/100,
battery_controller_status_2_str(watch_peripherals_get_battery_controller_status()),
_battery_stats.battery_voltage,
_battery_stats.battery_percentage);
update_tick = lv_tick_get();
}
/* Throttle CPU freq down when inactive to save power or to increase responsiveness */
tls_sys_clk clk;
tls_sys_clk_get(&clk);
if(lv_disp_get_inactive_time(NULL) > 5000)
{
if(clk.cpuclk != 40)
{
tls_sys_clk_set(CPU_CLK_40M);
APP_LOG_DEBUG("CPU 40Mhz");
}
}
else
{
if(clk.cpuclk != 160)
{
tls_sys_clk_set(CPU_CLK_160M);
APP_LOG_DEBUG("CPU 160Mhz");
}
}
/* Will wake the display up after some ms to avoid seeing the second hand jumping */
_perform_deferred_display_wake_up(30);
}
else
{
APP_LOG_DEBUG("Wrist tilt");
/* Increase task IDLE time */
tls_os_time_delay(50);
}
if(lv_tick_elaps(update_tick) > 5000)
{
pressure = watch_peripherals_pressure_sensor_get_pressure(&temperature);
_battery_stats.battery_voltage = watch_peripherals_get_battery_voltage(battery_unit_mv);
_battery_stats.battery_percentage = battery_voltage_to_percentage(_battery_stats.battery_voltage);
APP_LOG_DEBUG("GFX thread, temp : %0.2f °C, press : %0.2f hPa, battery(%s) : %u mV <-> %u %%",
temperature,
pressure/100,
battery_controller_status_2_str(watch_peripherals_get_battery_controller_status()),
_battery_stats.battery_voltage,
_battery_stats.battery_percentage);
//APP_LOG_DEBUG("Scanning WiFi : %d", tls_wifi_scan());
update_tick = lv_tick_get();
}
/* Handle inactivity periods : */
if( persistency_get_settings()->display.display_delay_before_sleep != 0 &&
lv_disp_get_inactive_time(NULL) > (persistency_get_settings()->display.display_delay_before_sleep * 5 * 1000))
{
// First, we disable the display backlight and we set all the peripherals in their low power mode
watch_peripherals_set_brightness(0);
//lcd_on(&LCDConfig, false);
lcd_sleep(&LCDConfig, true);
watch_peripherals_magnetometer_power_mode_set(QMC5883L_Mode_Control_Standby);
if(CST816D_sleep())
APP_LOG_DEBUG("CST816D Sleep cmd ok");
else
APP_LOG_DEBUG("CST816D Sleep cmd fail");
// Let's sleep
tls_pmu_sleep_start();
// On wake up, we force the watch face to sync up with the rtc /!\ RTC update delay WTF ?
tls_os_time_delay(1);
watch_face_force_sync(&watchFace);
lv_disp_trig_activity(NULL);
watch_peripherals_magnetometer_power_mode_set(QMC5883L_Mode_Control_Continuous);
//lcd_on(&LCDConfig, true);
lcd_sleep(&LCDConfig, false);
//watch_peripherals_set_brightness(persistency_get_settings()->display.display_brightness);
//lcd_on(&LCDConfig, false);
_perform_deferred_display_wake_up_set_timestamp();
}
/* Turns off the backlight, sets the display in sleep mode as well as some sensors. */
watch_peripherals_watch_sleep();
/* Will wake the display up after some ms to avoid seeing the second hand jumping */
_perform_deferred_display_wake_up(30);
/* Throttle CPU freq down when inactive to save power or to increase responsiveness */
tls_sys_clk clk;
tls_sys_clk_get(&clk);
if(lv_disp_get_inactive_time(NULL) > 5000)
{
if(clk.cpuclk != 40)
/* We need to keep the BLE stack running so we can't juste put the MCU in sleep mode :-( */
if(is_ble_modem_on())
{
tls_sys_clk_set(CPU_CLK_40M);
APP_LOG_DEBUG("CPU 40Mhz");
}
}
else
{
if(clk.cpuclk != 160)
{
tls_sys_clk_set(CPU_CLK_160M);
APP_LOG_DEBUG("CPU 160Mhz");
APP_LOG_DEBUG("Entering BLE sleep mode");
/* We can stop the lvgl timer */
APP_LOG_TRACE("Stopping LVGL tick timer");
lv_port_tick_stop();
_is_in_ble_sleep_mode = true;
}
else
{
do
{
/* We set the pmu timer 0 to wake up every now and then to perform some background tasks before we go back to sleep again */
tls_pmu_timer0_start(5);
/* We clear any potentiential user wakeup source */
watch_peripherals_wakeup_source_is_user();
/* Let's sleep for real */
tls_pmu_sleep_start();
if(watch_peripherals_wakeup_source_is_user())
{
/* Just to clear it off */
tls_pmu_timer0_stop();
watch_peripherals_wakeup_source_is_timer();
break;
}
/* Perform the periodic background tasks */
ms_delay(5);
APP_LOG_INFO("Periodic timer wakeup !");
} while (watch_peripherals_wakeup_source_is_timer());
/* On wake up, we force the watch face to sync up with the rtc /!\ RTC update delay WTF ? */
tls_os_time_delay(1);
watch_face_force_sync(&watchFace);
watch_peripherals_magnetometer_power_mode_set(QMC5883L_Mode_Control_Continuous);
lcd_sleep(&LCDConfig, false);
lcd_on(&LCDConfig, false);
_perform_deferred_display_wake_up_set_timestamp();
}
lv_disp_trig_activity(NULL);
}
/* Handle any interrupts status */
if(_interrupts_statuses.battery_controller_status)
{
@ -586,11 +632,31 @@ void gfx_task(void *param)
_battery_stats.battery_percentage = battery_voltage_to_percentage(_battery_stats.battery_voltage);
watch_face_set_battery_indicator(&watchFace, _battery_stats.battery_percentage, watch_peripherals_get_battery_controller_status());
}
bool wrist_tilt = false , touch_screen_touch = false;
if((wrist_tilt = watch_peripherals_accelerometer_wrist_wakeup_interrupt()) || ((touch_screen_touch = lv_port_indev_touched()) && _is_in_ble_sleep_mode))
{
if(wrist_tilt)
APP_LOG_DEBUG("Wrist tilt");
if(touch_screen_touch)
APP_LOG_DEBUG("Touch screen touch");
if(_is_in_ble_sleep_mode)
{
_is_in_ble_sleep_mode = false;
lv_port_tick_start();
watch_face_force_sync(&watchFace);
watch_peripherals_magnetometer_power_mode_set(QMC5883L_Mode_Control_Continuous);
lcd_sleep(&LCDConfig, false);
lcd_on(&LCDConfig, false);
_perform_deferred_display_wake_up_set_timestamp();
}
}
}
}
/* This handling logic should be moved somewhere ! I just don't know where yet ... */
static uint32_t _ticks = 0;
static bool _was_sleeping = false;

View File

@ -112,12 +112,11 @@ static void time_roller_cb(lv_event_t *e)
}
else if(roller == settingsScreen->month_roller)
{
index+=1;
settingsScreen->settingsScreenAPIInterface.setTimeSettingsCb(&NOT_SELECTED, &NOT_SELECTED, &NOT_SELECTED, &NOT_SELECTED, &index, &NOT_SELECTED, SETTING_MODE_SET);
}
else
{
index+=22; // Year is starting from 2000
index+=100+22; // Year is starting from 1900
settingsScreen->settingsScreenAPIInterface.setTimeSettingsCb(&NOT_SELECTED, &NOT_SELECTED, &NOT_SELECTED, &NOT_SELECTED, &NOT_SELECTED, &index, SETTING_MODE_SET);
}
}
@ -356,13 +355,13 @@ static void load_time_and_date_side_screen(SettingsScreen_t *settingsScreen)
lv_roller_set_options(settingsScreen->month_roller, month_options, LV_ROLLER_MODE_NORMAL);
lv_obj_align_to(settingsScreen->month_roller, settingsScreen->day_roller, LV_ALIGN_OUT_RIGHT_TOP, 5, 0);
lv_roller_set_visible_row_count(settingsScreen->month_roller, 2);
lv_roller_set_selected(settingsScreen->month_roller, month-1, LV_ANIM_OFF);
lv_roller_set_selected(settingsScreen->month_roller, month, LV_ANIM_OFF);
lv_obj_add_event_cb(settingsScreen->month_roller, &(time_roller_cb), LV_EVENT_RELEASED, settingsScreen);
lv_roller_set_options(settingsScreen->year_roller, year_options, LV_ROLLER_MODE_NORMAL);
lv_obj_align_to(settingsScreen->year_roller, settingsScreen->month_roller, LV_ALIGN_OUT_RIGHT_TOP, 5, 0);
lv_roller_set_visible_row_count(settingsScreen->year_roller, 2);
lv_roller_set_selected(settingsScreen->year_roller, year-22, LV_ANIM_OFF);
lv_roller_set_selected(settingsScreen->year_roller, year-100-22, LV_ANIM_OFF);
lv_obj_add_event_cb(settingsScreen->year_roller, &(time_roller_cb), LV_EVENT_RELEASED, settingsScreen);
// We set the state of the rollers only here, because they are not created yet earlier.
_enable_time_and_date_rollers(!auto_set_enable, settingsScreen);
@ -774,8 +773,8 @@ static void _set_rtc_time_to_label(SettingsScreen_t * const settingsScreen)
settingsScreen->settingsScreenAPIInterface.setTimeSettingsCb(&hour, &minute, &second, &day, &month, &year, SETTING_MODE_GET);
sprintf(settingsScreen->currentTime.current_time_text, "%u:%u:%u %s%u/%s%u/%u", hour, minute, second,
day < 10 ? "0":"", day,
month < 10 ? "0":"", month,
year+2000);
month + 1 < 10 ? "0":"", month,
year+1900);
lv_label_set_text_static(settingsScreen->currentTime.current_time_label, settingsScreen->currentTime.current_time_text);
}

View File

@ -36,6 +36,8 @@ static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
* STATIC VARIABLES
**********************/
static lv_indev_t * indev_touchpad;
static bool _indev_touched = false;
/**********************
* MACROS
@ -49,6 +51,7 @@ static void touch_panel_isr(void *arg)
CST816D_Touch_Data_t *p = arg;
tls_clr_gpio_irq_status(LCD_TOUCH_PANEL_IRQ);
CST816D_read_touch_event(p);
_indev_touched = true;
}
static void touch_panel_feedback_cb(struct _lv_indev_drv_t *lv_indev_drv, uint8_t lv_event_code)
@ -112,6 +115,17 @@ void lv_port_indev_init(void)
indev_touchpad = lv_indev_drv_register(&indev_drv);
}
bool lv_port_indev_touched(void)
{
if(_indev_touched)
{
_indev_touched = false;
return true;
}
return false;
}
/**********************
* STATIC FUNCTIONS
**********************/

View File

@ -30,8 +30,21 @@ extern "C" {
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* @brief Initializes the input device for LVGL to use.
*
*/
void lv_port_indev_init(void);
/**
* @brief Checks if the input device registered a touch event or not.
*
* @return true if a touch event was registered, the event is cleared once the function is called.
* @return false if not
*/
bool lv_port_indev_touched(void);
/**********************
* MACROS
**********************/

View File

@ -0,0 +1,40 @@
#include "wm_include.h"
#include "lvgl.h"
#include "app_log.h"
static uint8_t lv_tick_timer_id = WM_TIMER_ID_INVALID;
static void lv_tick_timer_irq_cb(void *arg)
{
(void)arg;
lv_tick_inc(1);
}
void lv_port_tick_init(void)
{
if(WM_TIMER_ID_INVALID == lv_tick_timer_id)
{
struct tls_timer_cfg lv_tick_timer_cfg =
{
.is_repeat = true,
.unit = TLS_TIMER_UNIT_MS,
.timeout = 1,
.callback = &(lv_tick_timer_irq_cb),
.arg = NULL,
};
if((lv_tick_timer_id = tls_timer_create(&lv_tick_timer_cfg)) == WM_TIMER_ID_INVALID)
APP_LOG_ERROR("Failed to create LVGL tick timer");
}
}
void lv_port_tick_start(void)
{
tls_timer_start(lv_tick_timer_id);
}
void lv_port_tick_stop(void)
{
tls_timer_stop(lv_tick_timer_id);
}

View File

@ -0,0 +1,63 @@
/**
* @file lv_port_tick.h
*
*/
/*Copy this file as "lv_port_tick.h" and set this value to "1" to enable content*/
#if 1
#ifndef LV_PORT_TICK_H
#define LV_PORT_TICK_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* @brief Creates the timer used to call @ref lv_tick_inc periodically.
* This is needed to run lvgl.
* @note This funcion does not start the timer, you must call @ref lv_port_tick_start for that !
*
*/
void lv_port_tick_init(void);
/**
* @brief Starts the timer used to call @ref lv_tick_inc periodically. @ref lv_port_tick_init should be called first at least once.
*
*/
void lv_port_tick_start(void);
/**
* @brief Stops the timer which calls @ref lv_tick_inc periodically.
* This function can be used to pause lvgl.
*
*/
void lv_port_tick_stop(void);
/**********************
* MACROS
**********************/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_PORT_TICK_H*/
#endif /*Disable/Enable content*/

View File

@ -1,8 +0,0 @@
#include "FreeRTOS.h"
#include "lvgl.h"
void vApplicationTickHook(void)
{
/* One tick is 2 ms because configTICK_RATE_HZ = 500. */
lv_tick_inc(2);
}

View File

@ -271,12 +271,12 @@ void tls_pmu_timer1_start(u16 msec)
{
val = msec;
}
//默认采用最小单位1ms
//Ĭ<EFBFBD>ϲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD>λ1ms
val = (val - 5) | (1<<16) | (0<<17) | (0<<20) | (0<<24);
}
else
{
//默认采用最小单位1ms
//Ĭ<EFBFBD>ϲ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><EFBFBD>λ1ms
val = (msec-1)|(1<<16) | (0<<17) | (0<<20) | (0<<24);
}
tls_reg_write32(HR_PMU_TIMER1, val);
@ -316,7 +316,7 @@ void tls_pmu_standby_start(void)
{
u32 val;
tls_irq_enable(PMU_IRQn); //默认打开中断为了清楚IO唤醒的中断标记
tls_irq_enable(PMU_IRQn); //Ĭ<EFBFBD>ϴ<EFBFBD><EFBFBD>ж<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IO<EFBFBD><EFBFBD><EFBFBD>ѵ<EFBFBD><EFBFBD>жϱ<EFBFBD><EFBFBD>
/*Clear Sleep status after exit sleep mode and enter standby mode*/
val = tls_reg_read32(HR_PMU_INTERRUPT_SRC);
@ -326,7 +326,7 @@ void tls_pmu_standby_start(void)
}
val = tls_reg_read32(HR_PMU_PS_CR);
TLS_DBGPRT_INFO("goto standby here\n");
//TLS_DBGPRT_INFO("goto standby here\n");
val |= BIT(0);
tls_reg_write32(HR_PMU_PS_CR, val);
}
@ -345,7 +345,7 @@ void tls_pmu_sleep_start(void)
u32 val;
u32 use40M;
tls_irq_enable(PMU_IRQn); //默认打开中断为了清楚IO唤醒的中断标记
tls_irq_enable(PMU_IRQn); //Ĭ<EFBFBD>ϴ<EFBFBD><EFBFBD>ж<EFBFBD>Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>IO<EFBFBD><EFBFBD><EFBFBD>ѵ<EFBFBD><EFBFBD>жϱ<EFBFBD><EFBFBD>
/*Clear Standby status after exit standby mode and enter sleep mode*/
@ -362,7 +362,7 @@ void tls_pmu_sleep_start(void)
use40M |= BIT(8);
tls_reg_write32(HR_PMU_WLAN_STTS, use40M);
}
TLS_DBGPRT_INFO("goto sleep here\n");
//TLS_DBGPRT_INFO("goto sleep here\n");
val |= BIT(1);
tls_reg_write32(HR_PMU_PS_CR, val);
}

View File

@ -65,7 +65,7 @@
#endif
#ifndef MYNEWT_VAL_MSYS_1_BLOCK_SIZE
#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (100) // Default 292
#define MYNEWT_VAL_MSYS_1_BLOCK_SIZE (150) // Default 292
#endif
#ifndef MYNEWT_VAL_MSYS_1_SANITY_MIN_COUNT
@ -925,7 +925,7 @@
/*** @apache-mynewt-nimble/nimble/transport/socket */
#ifndef MYNEWT_VAL_BLE_ACL_BUF_COUNT
#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (8) // Default 36
#define MYNEWT_VAL_BLE_ACL_BUF_COUNT (15) // Default 36
#endif
#ifndef MYNEWT_VAL_BLE_ACL_BUF_SIZE
@ -947,11 +947,11 @@
#endif
#ifndef MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT
#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (5) // Default 16
#define MYNEWT_VAL_BLE_HCI_EVT_HI_BUF_COUNT (10) // Default 16
#endif
#ifndef MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT
#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT (5) // Default 96
#define MYNEWT_VAL_BLE_HCI_EVT_LO_BUF_COUNT (20) // Default 96
#endif
#ifndef MYNEWT_VAL_BLE_SOCK_CLI_SYSINIT_STAGE

View File

@ -70,7 +70,7 @@
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 1 //ʹ<>ÿ<EFBFBD><C3BF>й<EFBFBD><D0B9><EFBFBD>
#define configUSE_TICK_HOOK 1
#define configUSE_TICK_HOOK 0
#define configCPU_CLOCK_HZ ( ( unsigned long ) 40000000 ) /* =12.0MHz xtal multiplied by 5 using the PLL. *///???????????????

View File

@ -51,6 +51,7 @@ INCLUDES += -I $(TOP_DIR)/app/app_drivers/i2c
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/app_utils
INCLUDES += -I $(TOP_DIR)/app/gfx
INCLUDES += -I $(TOP_DIR)/app/persistency
INCLUDES += -I $(TOP_DIR)/app/translation