Compare commits

...

16 Commits

Author SHA1 Message Date
anschrammh
f1e71bba67 Turned off a lot of functionalities related to TCP IP and WiFi to free some RAM, might be turned on back again later if needed and if RAM space left :P 2023-03-24 15:26:11 +01:00
anschrammh
d05aa72135 Updated all the settings callbacks to be compatible with the new setting system 2023-03-24 15:23:17 +01:00
anschrammh
4c1f1e168a Updated a log trace to be more meaningful 2023-03-24 15:22:15 +01:00
anschrammh
f8dace1dc1 Reduced the main's task stack size from 4k to 2k 2023-03-24 15:18:07 +01:00
anschrammh
2761a53a49 Reduced FreeRTOS available heap from 12k to 4k 2023-03-24 15:17:04 +01:00
anschrammh
2481699356 Vibration settings are now taken into account at lvgl input device driver layer 2023-03-24 15:15:19 +01:00
anschrammh
b65ab1ad4e Reduced LVGL allocated RAM by 10K. This RAM will be useful when running the BLE stack ... 2023-03-24 15:10:17 +01:00
anschrammh
b31cc96c10 Added the tls_is_rtc_running function which is not part of the official SDK. This allows to start the RTC after a reset and to know when it stopped running. 2023-03-24 15:10:16 +01:00
anschrammh
061fdb729b Updated the menu to now use the translation module to display the selected language 2023-03-24 15:06:14 +01:00
anschrammh
7e11913535 Added new watch settings in the persistency layer, added flash read and write functions, work still in progress 2023-03-24 15:06:14 +01:00
anschrammh
185b7a7efa Major rework of the settings screen :
- reduced RAM footprint by 10K :-)
- Added the new about category displaying infos about the watch's firmware
- Now widgets are reloaded with current parameters's values
- Almost all settings are taken into account
2023-03-24 15:06:14 +01:00
anschrammh
728394ff22 Reworked the compass screen to work for both possible platforms (breadboard and PCB) 2023-03-24 15:06:14 +01:00
anschrammh
86be55b404 Reworked the common screen header to add scrolling when the title is too long and to be able to update it's title after is has been created 2023-03-24 15:06:14 +01:00
anschrammh
5d3b5b5285 Added new wrapper functions to interact more easily with the watch's peripherals 2023-03-24 15:06:14 +01:00
anschrammh
beec1570c0 Reworked the orientation of the screen depending on the defined platform in app_config.h 2023-03-24 15:06:14 +01:00
anschrammh
f770a8e436 Added new parameter to be able to build the firmware for the breadboard platform or the PCB (latest) platform 2023-03-24 15:06:14 +01:00
25 changed files with 1146 additions and 582 deletions

View File

@ -1,6 +0,0 @@
{
"files.associations": {
"wm_include.h": "c",
"freertos.h": "c"
}
}

View File

@ -8,6 +8,18 @@
*
*/
/**
* @brief Defines for which platform to compile the firmware for :
*
* SMART_WATCH_BREADBOARD : the smart watch dev hardware which is on a breadboard
* SMART_WATCH_PCB : the smart watch using the PCB
*
*/
#define SMART_WATCH_BREADBOARD (0)
#define SMART_WATCH_PCB (1)
#define HARDWARE_PLATFORM SMART_WATCH_PCB
/**
* @brief Define which kind of logs to display :
*

View File

@ -78,7 +78,11 @@ const uint8_t gc9a01_init_seq[] = {
0x02, 0, 0x8E, 0xFF,
0x02, 0, 0x8F, 0xFF,
0x03, 0, 0xB6, 0x00, 0x00,
#if HARDWARE_PLATFORM == SMART_WATCH_BREADBOARD
0x02, 0, 0x36, 0x88,
#elif HARDWARE_PLATFORM == SMART_WATCH_PCB
0x02, 0, 0x36, 0x48,
#endif
0x02, 0, 0x3A, 0x55,
0x05, 0, 0x90, 0x08, 0x08, 0x08, 0x08,
0x02, 0, 0xBD, 0x06,
@ -416,7 +420,7 @@ void lcd_sleep(LCDConfig_t *const LCDConfig, bool state)
lcd_set_data_command(LCDConfig, LCD_DATA);
}
void lcd_orientation(LCDConfig_t *const LCDConfig, LCDOrientation_t orientation)
void lcd_orientation(LCDConfig_t *const LCDConfig, LCDOrientation_e orientation)
{
if(!LCDConfig) return;
@ -434,6 +438,7 @@ void lcd_orientation(LCDConfig_t *const LCDConfig, LCDOrientation_t orientation)
switch(orientation)
{
#if HARDWARE_PLATFORM == SMART_WATCH_BREADBOARD
case LCD_ORIENTATION_90:
mmc_sdio_driver_write_one(0xE8);
break;
@ -445,6 +450,19 @@ void lcd_orientation(LCDConfig_t *const LCDConfig, LCDOrientation_t orientation)
break;
default: //Is default orientation eg : 0
mmc_sdio_driver_write_one(0x88);
#elif HARDWARE_PLATFORM == SMART_WATCH_PCB
case LCD_ORIENTATION_90:
mmc_sdio_driver_write_one(0x28);
break;
case LCD_ORIENTATION_180:
mmc_sdio_driver_write_one(0x88);
break;
case LCD_ORIENTATION_270:
mmc_sdio_driver_write_one(0xE8);
break;
default: //Is default orientation eg : 0
mmc_sdio_driver_write_one(0x48);
#endif
}
lcd_set_cs(LCDConfig, LCD_RELEASED);

View File

@ -46,7 +46,7 @@ typedef enum LCDOrientation
LCD_ORIENTATION_90,
LCD_ORIENTATION_180,
LCD_ORIENTATION_270,
} LCDOrientation_t;
} LCDOrientation_e;
/**
* @brief
@ -62,7 +62,7 @@ typedef struct LCDConfig
enum tls_io_name LCDResetPin;
DrawFinishedCb_t drawFinishedCb;
void *cbArg;
LCDOrientation_t LCDOrientation;
LCDOrientation_e LCDOrientation;
} LCDConfig_t;
/**
@ -139,8 +139,12 @@ void lcd_sleep(LCDConfig_t * const LCDConfig, bool state);
* @brief Sets the LCD orientation.
*
* @param LCDConfig a pointer to a user allocated LCDConfig_t structure
* @param orientation the value of the orientation to set
* @param orientation the value of the orientation to set :
* - LCD_ORIENTATION_DEFAULT or LCD_ORIENTATION_0
* - LCD_ORIENTATION_90
* - LCD_ORIENTATION_180
* - LCD_ORIENTATION_270
*/
void lcd_orientation(LCDConfig_t * const LCDConfig, LCDOrientation_t orientation);
void lcd_orientation(LCDConfig_t * const LCDConfig, LCDOrientation_e orientation);
#endif //LCD_H

View File

@ -116,6 +116,8 @@ battery_controller_status_e watch_peripherals_get_battery_controller_status(void
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 */
if(!strength || !durationMs) return;
/* We start the timer which will stop the vibration after durationMs time */
tls_timer_change(_vibration_motor_timer_id, durationMs);
wm_pwm0_config(VIBRATION_MOTOR_ENABLE);
@ -123,3 +125,15 @@ void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs)
tls_pwm_duty_set(VIBRATION_MOTOR_PWM_CHANNEL, strength);
tls_timer_start(_vibration_motor_timer_id);
}
void watch_peripherals_set_brightness(uint8_t brightness)
{
extern LCDConfig_t LCDConfig;
lcd_set_backlight(&LCDConfig, brightness);
}
void watch_peripherals_set_orientation(LCDOrientation_e orientation)
{
extern LCDConfig_t LCDConfig;
lcd_orientation(&LCDConfig, orientation);
}

View File

@ -4,6 +4,7 @@
*/
#ifndef WATCH_PERIPHERALS_H
#define WATCH_PERIPHERALS_H
#include "lcd.h"
#include "wm_type_def.h"
typedef enum battery_unit
@ -63,4 +64,22 @@ battery_controller_status_e watch_peripherals_get_battery_controller_status(void
*/
void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs);
/**
* @brief Sets the brightness of the LCD display
*
* @param brightness from 0 (backlight off) to 255 backlight fully on
*/
void watch_peripherals_set_brightness(uint8_t brightness);
/**
* @brief Sets the orientation of the LCD display
*
* @param orientation the value of the orientation to set :
* - LCD_ORIENTATION_DEFAULT or LCD_ORIENTATION_0
* - LCD_ORIENTATION_90
* - LCD_ORIENTATION_180
* - LCD_ORIENTATION_270
*/
void watch_peripherals_set_orientation(LCDOrientation_e orientation);
#endif //WATCH_PERIPHERALS_H

View File

@ -1,7 +1,37 @@
#include "lvgl.h"
/***
* It is needed to have a reference on two header_titles because when
* switching from one screen using a header to an other screen which is also using one
* the header of the new screen will be created BEFORE the header of the previous screen
* is deleted ...
*/
/* A reference to the current and previous header title */
static lv_obj_t *header_title[2] = {NULL, NULL};
/* Pointer to the header_title to use */
lv_obj_t **header_title_p = &header_title[0];
static void cleanup_event_cb(lv_event_t * e)
{
lv_obj_t **header_title_deleted_p = e->user_data;
*header_title_deleted_p = NULL;
LV_LOG_USER("header_title cleanup");
}
void common_screen_header_component(lv_obj_t *parent, const char * title, lv_coord_t height)
{
if(header_title[0] == NULL)
header_title_p = &header_title[0];
else if(header_title[1] == NULL)
header_title_p = &header_title[1];
else
{
LV_LOG_ERROR("no free header_title");
return;
}
lv_obj_t *header = lv_obj_create(parent);
lv_obj_set_style_bg_color(header, lv_color_make(129, 141,181), LV_PART_MAIN);
lv_obj_set_size(header, lv_disp_get_hor_res(NULL), height);
@ -9,9 +39,20 @@ void common_screen_header_component(lv_obj_t *parent, const char * title, lv_coo
lv_obj_set_style_border_width(header, 0, LV_PART_MAIN);
lv_obj_clear_flag(header, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_t *header_title = lv_label_create(header);
lv_label_set_text_static(header_title, title);
lv_obj_set_style_text_color(header_title, lv_color_white(), LV_PART_MAIN);
lv_obj_set_style_text_font(header_title, &lv_font_montserrat_30, LV_PART_MAIN);
lv_obj_set_align(header_title, LV_ALIGN_CENTER);
*header_title_p = lv_label_create(header);
lv_label_set_text_static(*header_title_p, title);
lv_obj_set_style_text_align(*header_title_p, LV_TEXT_ALIGN_CENTER, LV_PART_MAIN);
lv_obj_set_style_text_color(*header_title_p, lv_color_white(), LV_PART_MAIN);
lv_obj_set_style_text_font(*header_title_p, &lv_font_montserrat_30, LV_PART_MAIN);
lv_obj_set_width(*header_title_p, 150);
lv_obj_set_align(*header_title_p, LV_ALIGN_CENTER);
lv_label_set_long_mode(*header_title_p, LV_LABEL_LONG_SCROLL_CIRCULAR);
/* Once the current header_title is destroyed, mark it as NULL to prevent any crashes when trying to change it's title */
lv_obj_add_event_cb(*header_title_p, &(cleanup_event_cb), LV_EVENT_DELETE, header_title_p);
}
void common_screen_header_update_title(const char * title)
{
if(!*header_title_p)return;
lv_label_set_text_static(*header_title_p, title);
}

View File

@ -3,6 +3,20 @@
#include "lvgl.h"
/**
* @brief Adds a screen header with the defined title to the screen passed as parent with the provided height.
*
* @param parent the screen to which the header will be added
* @param title a string used as the header's title
* @param height the height in pixel of the header
*/
void common_screen_header_component(lv_obj_t *parent, const char * title, lv_coord_t height);
/**
* @brief Updates the current title of displayed screen header
*
* @param title a string used as the new header's title
*/
void common_screen_header_update_title(const char * title);
#endif //COMMON_SCREEN_COMPONENTS_H

View File

@ -3,6 +3,7 @@
#include "lvgl.h"
#include "compass_screen.h"
#include "menu_screen.h"
#include "app_config.h"
static const char *cardinals[] =
{
@ -71,9 +72,13 @@ static void rotate_cardinal(CompassCardinal_t *cardinal, uint16_t azimuth)
{
lv_coord_t rotated_x, rotated_y;
float azimuth_in_rads = (float)azimuth*M_PI/180.0;
#if HARDWARE_PLATFORM == SMART_WATCH_BREADBOARD
rotated_x = (float)(cardinal->position.x-120+cardinal->offset.x)*cos(azimuth_in_rads) - (float)(cardinal->position.y-120+cardinal->offset.y)*sin(azimuth_in_rads) + 120-cardinal->offset.x;
rotated_y = (float)(cardinal->position.y-120+cardinal->offset.y)*cos(azimuth_in_rads) + (float)(cardinal->position.x-120+cardinal->offset.x)*sin(azimuth_in_rads) + 120-cardinal->offset.y;
#elif HARDWARE_PLATFORM == SMART_WATCH_PCB
rotated_x = (float)(cardinal->position.x-120+cardinal->offset.x)*cos(azimuth_in_rads) + (float)(cardinal->position.y-120+cardinal->offset.y)*sin(azimuth_in_rads) + 120-cardinal->offset.x;
rotated_y = (float)(cardinal->position.y-120+cardinal->offset.y)*cos(azimuth_in_rads) - (float)(cardinal->position.x-120+cardinal->offset.x)*sin(azimuth_in_rads) + 120-cardinal->offset.y;
#endif
lv_obj_set_pos(cardinal->label, rotated_x, rotated_y);
}
@ -102,7 +107,11 @@ void compass_screen_set_azimuth(CompassScreen_t * const compassScreen, uint16_t
//We make sure the azimuth is in the right range ie 0 to 359
azimuth %= 360;
#if HARDWARE_PLATFORM == SMART_WATCH_BREADBOARD
uint16_t azimuthAdjusted = 359 - azimuth;
#elif HARDWARE_PLATFORM == SMART_WATCH_PCB
uint16_t azimuthAdjusted = azimuth;
#endif
uint8_t index;
@ -129,7 +138,11 @@ void compass_screen_set_azimuth(CompassScreen_t * const compassScreen, uint16_t
//Rotate each cardinal with the current azimuth
rotate_cardinal(&compassScreen->northCardinal, azimuth);
#if HARDWARE_PLATFORM == SMART_WATCH_BREADBOARD
lv_img_set_angle(compassScreen->northMarker, azimuth*10);
#elif HARDWARE_PLATFORM == SMART_WATCH_PCB
lv_img_set_angle(compassScreen->northMarker, -azimuth*10);
#endif
//lv_meter_set_scale_range(compassScreen->compassGraduation.meter, compassScreen->compassGraduation.scale, 0, 330, 330, azimuth-90);
rotate_cardinal(&compassScreen->eastCardinal, azimuth);

View File

@ -41,67 +41,157 @@ struct bma456w_wrist_wear_wakeup_params setting;
struct bma4_int_pin_config pin_config;
uint16_t int_status;
static void setBrightness(uint8_t brightness)
static void setGetBrightnessCb(uint8_t *brightness, SettingMode_e mode)
{
extern LCDConfig_t LCDConfig;
lcd_set_backlight(&LCDConfig, brightness);
}
static void setBrightnessCb(uint8_t brightness)
{
persistency_get_settings()->display.brightness = brightness;
setBrightness(brightness);
if(SETTING_MODE_GET == mode)
{
*brightness = persistency_get_settings()->display.display_brightness;
}
else
{
persistency_get_settings()->display.display_brightness = *brightness;
watch_peripherals_set_brightness(*brightness);
}
}
static void setTimeCb(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t month, uint8_t year)
static void setTimeCb(uint8_t *hour, uint8_t *minute, uint8_t *second, uint8_t *day, uint8_t *month, uint8_t *year, SettingMode_e mode)
{
struct tm timeToSet;
//First we get the current time from the RTC
tls_get_rtc(&timeToSet);
if(hour != 0xFF)
timeToSet.tm_hour = hour;
if(SETTING_MODE_GET == mode)
{
*hour = timeToSet.tm_hour;
*minute = timeToSet.tm_min;
*second = timeToSet.tm_sec;
*day = timeToSet.tm_mday;
*month = timeToSet.tm_mon;
*year = timeToSet.tm_year-100;
}
else
{
if(*hour != 0xFF)
timeToSet.tm_hour = *hour;
if(minute != 0xFF)
timeToSet.tm_min = minute;
if(*minute != 0xFF)
timeToSet.tm_min = *minute;
if(second != 0xFF)
timeToSet.tm_sec = second;
if(*second != 0xFF)
timeToSet.tm_sec = *second;
if(day != 0xFF)
timeToSet.tm_mday = day;
if(*day != 0xFF)
timeToSet.tm_mday = *day;
if(month != 0xFF)
timeToSet.tm_mon = month;
if(*month != 0xFF)
timeToSet.tm_mon = *month;
if(year != 0xFF)
timeToSet.tm_year = year + 100;
if(*year != 0xFF)
timeToSet.tm_year = *year + 100;
tls_set_rtc(&timeToSet);
tls_set_rtc(&timeToSet);
}
}
static void setTimeoutCb(uint8_t timeout)
static void setDisplayVibrationDuration(uint8_t *duration, SettingMode_e mode)
{
persistency_get_settings()->display.sleep_delay = timeout;
if(SETTING_MODE_GET == mode)
{
*duration = persistency_get_settings()->display.display_vibrate_on_touch_duration;
}
else
{
persistency_get_settings()->display.display_vibrate_on_touch_duration = *duration;
}
}
static void setOrientationCb(uint8_t orientation)
static void setDisplayVibrationStrength(uint8_t *strength, SettingMode_e mode)
{
extern LCDConfig_t LCDConfig;
lcd_orientation(&LCDConfig, orientation);
persistency_get_settings()->display.orientation = orientation;
// Forces to redraw the full screen to avoid strange artifact
lv_obj_invalidate(lv_scr_act());
if(SETTING_MODE_GET == mode)
{
*strength = persistency_get_settings()->display.display_vibrate_on_touch_strength;
}
else
{
persistency_get_settings()->display.display_vibrate_on_touch_strength = *strength;
}
}
static void setTimeoutCb(uint8_t *timeout, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
*timeout = persistency_get_settings()->display.display_delay_before_sleep;
}
else
{
persistency_get_settings()->display.display_delay_before_sleep = *timeout;
}
}
static void setOrientationCb(uint8_t *orientation, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
*orientation = persistency_get_settings()->display.display_orientation;
}
else
{
persistency_get_settings()->display.display_orientation = *orientation;
watch_peripherals_set_orientation(*orientation);
// Forces to redraw the full screen to avoid strange artifacts
lv_obj_invalidate(lv_scr_act());
}
}
static void setBLEEnabledCb(bool *enabled, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
*enabled = persistency_get_settings()->connectivity.connectivity_ble_enabled;
}
else
{
persistency_get_settings()->connectivity.connectivity_ble_enabled = *enabled;
}
}
static void setWiFiEnabledCb(bool *enabled, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
*enabled = persistency_get_settings()->connectivity.connectivity_wifi_enabled;
}
else
{
persistency_get_settings()->connectivity.connectivity_wifi_enabled = *enabled;
}
}
static void setLanguageCb(uint8_t *language, SettingMode_e mode)
{
if(SETTING_MODE_GET == mode)
{
*language = persistency_get_settings()->languageAndUI.language;
}
else
{
persistency_get_settings()->languageAndUI.language = *language;
}
}
SettingsScreenAPIInterface_t settingsScreenAPIInterface =
{
.setBrightnessSettingsCb = setBrightnessCb,
.setTimeSettingsCb = setTimeCb,
.setBrightnessSettingsCb = setGetBrightnessCb,
.setTimeoutSettingsCb = setTimeoutCb,
.setDisplayVibrationDurationSettingsCb = setDisplayVibrationDuration,
.setDisplayVibrationStrengthSettingsCb = setDisplayVibrationStrength,
.setOrientationSettingsCb = setOrientationCb,
.setBLEEnabledSettingsCb = setBLEEnabledCb,
.setWiFiEnabledSettingsCb = setWiFiEnabledCb,
.setLanguageSettingsCb = setLanguageCb,
};
static uint16_t angle_with_offset(uint16_t angle, uint16_t offset)
@ -174,6 +264,17 @@ void gfx_task(void *param)
{
APP_LOG_TRACE("starting");
/* Init and load watch settings using the persistency layer */
persistency_init();
/* Check whether the RTC is running or not, if not, then the board was reset
So we start the RTC */
if(!tls_is_rtc_running())
{
struct tm curr_time = {0};
tls_set_rtc(&curr_time);
}
/* Initialize the lvgl library and peripherals (display and input device)*/
lv_init();
@ -299,13 +400,13 @@ void gfx_task(void *param)
/* Let's init the watch peripherals driver (vibration motor + battery voltage sense) */
watch_peripherals_init(27);
/* Make the first battery voltage reading here */
uint16_t battery_voltage = watch_peripherals_get_battery_voltage(Battery_Unit_mV);
uint16_t 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);
/* Once we are done with the initializing steps we
don't forget to turn the backlight on ! */
setBrightness(persistency_get_settings()->display.brightness);
watch_peripherals_set_brightness(persistency_get_settings()->display.display_brightness);
/* Enable WiFi hotspot scanning for antenna performance test purposes */
tls_wifi_scan_result_cb_register(&(scan_result_cb));
@ -349,7 +450,7 @@ void gfx_task(void *param)
{
pressure = BMP280_get_pressure(&temperature);
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);
APP_LOG_DEBUG("GFX thread, temp : %0.2f °C, press : %0.2f hPa, bat(%d) : %u mV <-> %u %%",
temperature,
@ -364,11 +465,11 @@ void gfx_task(void *param)
}
/* Handle inactivity periods : */
if( persistency_get_settings()->display.sleep_delay != 0 &&
lv_disp_get_inactive_time(NULL) > (persistency_get_settings()->display.sleep_delay * 1000))
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
setBrightness(0);
watch_peripherals_set_brightness(0);
//lcd_on(&LCDConfig, false);
lcd_sleep(&LCDConfig, true);
QMC5883L_set_power_mode(Standby);
@ -385,7 +486,7 @@ void gfx_task(void *param)
QMC5883L_set_power_mode(Continuous);
//lcd_on(&LCDConfig, true);
lcd_sleep(&LCDConfig, false);
setBrightness(persistency_get_settings()->display.brightness);
watch_peripherals_set_brightness(persistency_get_settings()->display.display_brightness);
}
/* Throttle CPU freq down when inactive to save power or to increase responsiveness */

View File

@ -4,6 +4,7 @@
#include "settings_screen.h"
#include "watch_face.h"
#include "compass_screen.h"
#include "translation.h"
#define array_size(array) (sizeof(array)/sizeof(array[0]))
@ -119,14 +120,14 @@ void menu_screen_create(MenuScreen_t * const menuScreen)
lv_obj_set_style_border_width(scroll_item_container, 0, LV_PART_MAIN);
lv_obj_set_style_pad_right(scroll_item_container, 15, LV_PART_SCROLLBAR);
menu_screen_add_item(scroll_item_container, 0, &watch_menu_clock_icon, "Watch", &(menu_item_cb));
menu_screen_add_item(scroll_item_container, 1, &watch_menu_compass_icon, "Compass", &(menu_item_cb));
menu_screen_add_item(scroll_item_container, 2, &watch_menu_alarm_icon, "Alarm", &(menu_item_cb));
menu_screen_add_item(scroll_item_container, 0, &watch_menu_clock_icon, translation_get_word(TRANSLATION_WATCH), &(menu_item_cb));
menu_screen_add_item(scroll_item_container, 1, &watch_menu_compass_icon, translation_get_word(TRANSLATION_COMPASS), &(menu_item_cb));
menu_screen_add_item(scroll_item_container, 2, &watch_menu_alarm_icon, translation_get_word(TRANSLATION_ALARM), &(menu_item_cb));
menu_screen_add_item(scroll_item_container, 3, &watch_menu_messages_icon, "Text messages", &(menu_item_cb));
menu_screen_add_item(scroll_item_container, 4, &watch_menu_mail_icon, "Mails", &(menu_item_cb));
menu_screen_add_item(scroll_item_container, 5, &watch_menu_dialer_icon, "Phone", &(menu_item_cb));
menu_screen_add_item(scroll_item_container, 6, &watch_menu_contacts_icon, "Contacts", &(menu_item_cb));
menu_screen_add_item(scroll_item_container, 7, &watch_menu_settings_icon, "Settings", &(menu_item_cb));
menu_screen_add_item(scroll_item_container, 7, &watch_menu_settings_icon, translation_get_word(TRANSLATION_SETTINGS), &(menu_item_cb));
//We register the event callback to handle the cleanup
lv_obj_add_event_cb(menuScreen->display, &(cleanup_event_cb), LV_EVENT_DELETE, menuScreen);

File diff suppressed because it is too large Load Diff

View File

@ -3,24 +3,59 @@
#include "lvgl.h"
typedef enum SettingMode
{
SETTING_MODE_GET = 0,
SETTING_MODE_SET
} SettingMode_e;
typedef struct SettingsScreenAPIInterface
{
void (*setBrightnessSettingsCb)(uint8_t brightness);
void (*setTimeSettingsCb)(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t month, uint8_t year);
void (*setTimeoutSettingsCb)(uint8_t timeout);
void (*setOrientationSettingsCb)(uint8_t orientation);
void (*setTimeSettingsCb)(uint8_t *hour, uint8_t *minute, uint8_t *second, uint8_t *day, uint8_t *month, uint8_t *year, SettingMode_e mode);
void (*setBrightnessSettingsCb)(uint8_t *brightness, SettingMode_e mode);
void (*setTimeoutSettingsCb)(uint8_t *timeout, SettingMode_e mode);
void (*setDisplayVibrationDurationSettingsCb)(uint8_t *duration, SettingMode_e mode);
void (*setDisplayVibrationStrengthSettingsCb)(uint8_t *strength, SettingMode_e mode);
void (*setOrientationSettingsCb)(uint8_t *orientation, SettingMode_e mode);
void (*setBLEEnabledSettingsCb)(bool *enabled, SettingMode_e mode);
void (*setWiFiEnabledSettingsCb)(bool *enabled, SettingMode_e mode);
void (*setLanguageSettingsCb)(uint8_t *language, SettingMode_e mode);
} SettingsScreenAPIInterface_t;
typedef struct SettingsScreen
{
SettingsScreenAPIInterface_t settingsScreenAPIInterface;
/* Menu list items */
lv_obj_t *time_and_date_item;
lv_obj_t *display_item;
lv_obj_t *notifications_item;
lv_obj_t *connectivity_item;
lv_obj_t *language_item;
lv_obj_t *about_item;
lv_obj_t *side_screen;
lv_obj_t *hour_roller;
lv_obj_t *minute_roller;
lv_obj_t *second_roller;
lv_obj_t *checkbox_time_12H;
lv_obj_t *checkbox_time_24H;
lv_obj_t *day_roller;
lv_obj_t *month_roller;
lv_obj_t *year_roller;
lv_obj_t *ble_switch;
lv_obj_t *wifi_switch;
struct
{
lv_obj_t *current_time_label;
char current_time_text[20];
} currentTime;
/* Main screen */
lv_obj_t *display;
/* Other */
lv_timer_t *about_refresh_timer;
} SettingsScreen_t;
void settings_screen_init(SettingsScreen_t * const settingsScreen);
@ -31,6 +66,4 @@ void settings_screen_create(SettingsScreen_t * const settingsScreen);
void settings_screen_destroy(SettingsScreen_t * const settingsScreen);
void settings_screen(void);
#endif //SETTINGS_SCREEN_H

View File

@ -39,7 +39,7 @@ void user_task_main(void *param)
{
UBaseType_t writtenSize = vTaskList((char *)buf, 800);
APP_LOG_INFO("Available RAM (bytes)/Total RAM (bytes) : %u/%u"NEW_LINE
"FreeRTOS heap : %u/%u byte(s)"NEW_LINE
"FreeRTOS free heap/total heap : %u/%u byte(s)"NEW_LINE
"Reset reason : %d"NEW_LINE
"Clk : apb(%u), cpu(%u), wlan(%u)"NEW_LINE
"Tasks (%lu) :"NEW_LINE,

View File

@ -1,13 +1,101 @@
#include "watch_settings.h"
#include "wm_internal_flash.h"
#include "app_log.h"
#include "translation.h"
/* WatchSetting object with default values */
static WatchSettings_t watchSettings =
/**
* @brief WatchSetting object with default values.
*
* @note Used to restore factory settings for example or as default values when first start.
*/
static const WatchSettings_t defaultWatchSettings =
{
.timeAndDate = {.hour_format = 0, .date_format = 0, .automatic_time_and_date = 0},
.display = {.brightness = 255, .sleep_delay = 0,},
.timeAndDate = {
.time_and_date_hour_format = 0,
.time_and_date_date_format = 0,
.time_and_date_automatic = 0,
},
.display = {
.display_brightness = 200,
.display_delay_before_sleep = 0,
.display_orientation = LCD_ORIENTATION_DEFAULT,
.display_vibrate_on_touch_duration = 0,
.display_vibrate_on_touch_strength = 0,
.display_wrist_wakeup = true,
},
.notification = {
.notification_vibration_duration = 4,
.notification_vibration_strength = 7,
.vibrate_on_email = true,
.vibrate_on_sms = true,
},
.connectivity = {
.connectivity_ble_enabled = false,
.connectivity_wifi_enabled = false,
},
.languageAndUI = {
.language = TRANSLATION_ENGLISH,
},
};
/**
* @brief Actual watchSettings object which can change and lives in RAM memory.
*
*/
static WatchSettings_t watchSettings;
/**
* @brief Internal variable used to know if something has to be saved or not because some settings changed.
*
* @note This is designed to prevent excessive wear and tear on the flash.
*
*/
static bool _params_changed = false;
void persistency_init(void)
{
memcpy(&watchSettings, &defaultWatchSettings, sizeof(WatchSettings_t));
}
WatchSettings_t *persistency_get_settings(void)
{
return &watchSettings;
}
void display_set_brightness(uint8_t brightness)
{
watchSettings.display.display_brightness = brightness;
_params_changed = true;
}
bool persistency_save_settings(void)
{
if(!_params_changed)
{
APP_LOG_INFO("Nothing to save, no params changed");
return true;
}
uint8_t status = TLS_FLS_STATUS_OK;
if(TLS_FLS_STATUS_OK != (status = tls_fls_write_without_erase(WATCH_SETTINGS_FLASH_STORAGE_ADDRESS, (uint8_t *) &watchSettings, sizeof watchSettings)))
{
APP_LOG_ERROR("Failed to write settings to flash : %u", status);
return false;
}
// Don't forget to reset the state variable here
_params_changed = false;
return true;
}
bool persistency_load_settings(void)
{
uint8_t status = TLS_FLS_STATUS_OK;
if(TLS_FLS_STATUS_OK != (status = tls_fls_read(WATCH_SETTINGS_FLASH_STORAGE_ADDRESS, (uint8_t *) &watchSettings, sizeof watchSettings)))
{
APP_LOG_ERROR("Failed to read settings to flash : %u", status);
return false;
}
return true;
}

View File

@ -2,48 +2,206 @@
#define WATCH_SETTINGS_H
#include "wm_type_def.h"
#include "lcd.h"
/* Time and Date Settings */
/**
* @brief The address in flash storage where the settings are saved
*
*/
#define WATCH_SETTINGS_FLASH_STORAGE_ADDRESS (0x1E0000)
/**
* @brief Time and Date Settings
*
*/
typedef struct TimeAndDate
{
uint32_t hour_format:1;
uint32_t date_format:2;
uint32_t automatic_time_and_date:1;
uint32_t time_and_date_hour_format:1,
time_and_date_date_format:2,
time_and_date_automatic:1;
} TimeAndDate_t;
/* Display Settings */
/**
* @brief Display Settings
*
*/
typedef struct Display
{
uint8_t brightness;
uint8_t sleep_delay;
uint8_t orientation:2;
uint32_t display_brightness:8,
display_delay_before_sleep:4,
display_orientation:2,
display_wrist_wakeup:1,
display_vibrate_on_touch_strength:3,
display_vibrate_on_touch_duration:3;
} Display_t;
/* Connectivity Settings */
/**
* @brief Notification Settings
*
*/
typedef struct Notification
{
uint32_t vibrate_on_sms:1,
vibrate_on_email:1,
notification_vibration_strength:3,
notification_vibration_duration:3;
} Notification_t;
/**
* @brief Connectivity Settings
*
*/
typedef struct Connectivity
{
uint32_t connectivity_ble_enabled:1,
connectivity_wifi_enabled:1;
} Connectivity_t;
/* Language and UI Settings */
/**
* @brief Language and UI Settings
*
* @note Languages : English, French and German will be available
*
*/
typedef struct LanguageAndUI
{
uint32_t language:3;
} LanguageAndUI_t;
/* Main setting structure */
/**
* @brief Main setting structure
*
*/
typedef struct WatchSettings
{
uint32_t first_time_init:1;
TimeAndDate_t timeAndDate;
Display_t display;
Notification_t notification;
Connectivity_t connectivity;
LanguageAndUI_t languageAndUI;
} WatchSettings_t;
/**
* @brief Initializes the persistency layer. Must be called first before any other persistency API functions.
*
*/
void persistency_init(void);
/**
* @brief
*
* @return WatchSettings_t* a pointer to the WatchSettings structure
*/
WatchSettings_t *persistency_get_settings(void);
/**
* @brief
*
* @param hour_24H_format
*/
void time_and_date_set_hour_format(bool hour_24H_format);
/**
* @brief
*
* @param date_format
*/
void time_and_date_set_date_format(uint8_t date_format);
/**
* @brief
*
* @param automatic
*/
void time_and_date_set_automatic(bool automatic);
/**
* @brief
*
* @param brightness
*/
void display_set_brightness(uint8_t brightness);
/**
* @brief
*
* @param delay
*/
void display_set_delay_before_sleep(uint8_t delay);
/**
* @brief
*
* @param orientation
*/
void display_set_orientation(LCDOrientation_e orientation);
/**
* @brief
*
* @param wakeup
*/
void display_set_wrist_wakeup(bool wakeup);
/**
* @brief
*
* @param level
*/
void display_set_vibrate_on_touch_strength(uint8_t level);
/**
* @brief
*
* @param duration
*/
void display_set_vibrate_on_touch_duration(uint8_t duration);
/**
* @brief
*
* @param level
*/
void notification_set_vibration_strength(uint8_t level);
/**
* @brief
*
* @param duration
*/
void notification_set_vibration_duration(uint8_t duration);
/**
* @brief
*
* @param enabled
*/
void connectivity_set_ble_enabled(bool enabled);
/**
* @brief
*
* @param enabled
*/
void connectivity_set_wifi_enabled(bool enabled);
/**
* @brief
*
* @return true
* @return false
*/
bool persistency_save_settings(void);
/**
* @brief
*
* @return true
* @return false
*/
bool persistency_load_settings(void);
#endif //WATCH_SETTINGS_H

View File

@ -58,6 +58,18 @@ void tls_set_rtc(struct tm *tblock);
*/
void tls_get_rtc(struct tm *tblock);
/** NOT PART OF THE OFFICIAL SDK **/
/**
* @brief Checks if the RTC peripheral is running or not
*
* @return true
* @return false
*/
bool tls_is_rtc_running(void);
/**********************************/
/**
* @brief This function is used to register pmu rtc interrupt
*

View File

@ -24,7 +24,7 @@
#define TLS_CONFIG_ONLY_FACTORY_ATCMD CFG_OFF
/**Host Interface&Command**/
#define TLS_CONFIG_HOSTIF CFG_ON
#define TLS_CONFIG_HOSTIF CFG_OFF
#define TLS_CONFIG_AT_CMD (CFG_ON && TLS_CONFIG_HOSTIF)
#define TLS_CONFIG_RI_CMD (CFG_ON && TLS_CONFIG_HOSTIF)
#define TLS_CONFIG_RMMS (CFG_ON && TLS_CONFIG_HOSTIF)
@ -36,15 +36,15 @@
/** SOCKET CONFIG **/
#define TLS_CONFIG_SOCKET_STD CFG_ON
#define TLS_CONFIG_SOCKET_RAW CFG_ON
#define TLS_CONFIG_SOCKET_RAW CFG_OFF
#define TLS_CONFIG_CMD_USE_RAW_SOCKET (CFG_ON && TLS_CONFIG_SOCKET_RAW)
#define TLS_CONFIG_CMD_NET_USE_LIST_FTR CFG_ON
#define TLS_CONFIG_CMD_NET_USE_LIST_FTR CFG_OFF
#define TLS_CONFIG_HARD_CRYPTO CFG_ON
#define TLS_CONFIG_HARD_CRYPTO CFG_OFF
#define TLS_CONFIG_NTO CFG_ON
#define TLS_CONFIG_NTO CFG_OFF
#define TLS_CONFIG_CRYSTAL_24M CFG_OFF
/** HTTP CLIENT **/
@ -54,17 +54,17 @@ HTTPS Lib
SSL LIB
CRYPTO
*/
#define TLS_CONFIG_HTTP_CLIENT (CFG_ON)
#define TLS_CONFIG_HTTP_CLIENT (CFG_OFF)
#define TLS_CONFIG_HTTP_CLIENT_PROXY CFG_OFF
#define TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC CFG_OFF
#define TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST CFG_OFF
#define TLS_CONFIG_HTTP_CLIENT_AUTH (TLS_CONFIG_HTTP_CLIENT_AUTH_BASIC || TLS_CONFIG_HTTP_CLIENT_AUTH_DIGEST)
#define TLS_CONFIG_HTTP_CLIENT_SECURE (CFG_ON && (TLS_CONFIG_USE_POLARSSL || TLS_CONFIG_USE_MBEDTLS))
#define TLS_CONFIG_HTTP_CLIENT_TASK (CFG_ON && TLS_CONFIG_HTTP_CLIENT)
#define TLS_CONFIG_HTTP_CLIENT_SECURE (CFG_OFF && (TLS_CONFIG_USE_POLARSSL || TLS_CONFIG_USE_MBEDTLS))
#define TLS_CONFIG_HTTP_CLIENT_TASK (CFG_OFF && TLS_CONFIG_HTTP_CLIENT)
/*MatrixSSL will be used except one of the following two Macros is CFG_ON*/
#define TLS_CONFIG_USE_POLARSSL CFG_OFF
#define TLS_CONFIG_USE_MBEDTLS CFG_ON
#define TLS_CONFIG_USE_MBEDTLS CFG_OFF
#define TLS_CONFIG_SERVER_SIDE_SSL (CFG_ON && TLS_CONFIG_HTTP_CLIENT_SECURE && TLS_CONFIG_USE_MBEDTLS) /*MUST configure TLS_CONFIG_HTTP_CLIENT_SECURE CFG_ON */
@ -73,7 +73,7 @@ CRYPTO
#define TLS_CONFIG_IGMP CFG_ON
#define TLS_CONFIG_NTP CFG_ON
#define TLS_CONFIG_NTP CFG_OFF
#if NIMBLE_FTR
#define TLS_CONFIG_BLE CFG_ON

View File

@ -49,7 +49,7 @@
#define LV_MEM_CUSTOM 0
#if LV_MEM_CUSTOM == 0
/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
#define LV_MEM_SIZE (40 * 1024U) /*[bytes]*/
#define LV_MEM_SIZE (30 * 1024U) /*[bytes]*/
/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
#define LV_MEM_ADR 0 /*0: unused*/

View File

@ -15,6 +15,7 @@
#include "lcd.h"
#include "CST816D.h"
#include "watch_peripherals.h"
#include "watch_settings.h"
#include "app_log.h"
@ -50,17 +51,20 @@ static void touch_panel_isr(void *arg)
CST816D_read_touch_event(p);
}
void touch_panel_feedback_cb(struct _lv_indev_drv_t *lv_indev_drv, uint8_t lv_event_code)
static void touch_panel_feedback_cb(struct _lv_indev_drv_t *lv_indev_drv, uint8_t lv_event_code)
{
(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;
switch(lv_event_code)
{
case LV_EVENT_LONG_PRESSED:
watch_peripherals_vibrate(255, 200);
watch_peripherals_vibrate(255, vibration_duration_ms);
break;
case LV_EVENT_PRESSED:
watch_peripherals_vibrate(200, 200);
watch_peripherals_vibrate(vibration_strength > 255 ? 255 : vibration_strength, vibration_duration_ms);
break;
}
}
@ -135,6 +139,7 @@ static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
// Set the last pressed coordinates taking into account the current display orientation
switch(LCDConfig.LCDOrientation)
{
#if HARDWARE_PLATFORM == SMART_WATCH_BREADBOARD
case LCD_ORIENTATION_90:
data->point.x = 239-last_y;
data->point.y = last_x;
@ -151,6 +156,24 @@ static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
data->point.x = 239-last_x;
data->point.y = 239-last_y;
break;
#elif HARDWARE_PLATFORM == SMART_WATCH_PCB
case LCD_ORIENTATION_90:
data->point.x = last_y;
data->point.y = 239-last_x;
break;
case LCD_ORIENTATION_180:
data->point.x = 239-last_x;
data->point.y = 239-last_y;
break;
case LCD_ORIENTATION_270:
data->point.x = 239-last_y;
data->point.y = last_x;
break;
default:
data->point.x = last_x;
data->point.y = last_y;
break;
#endif
}
}

View File

@ -82,6 +82,13 @@ void tls_get_rtc(struct tm *tblock)
tblock->tm_sec = ctrl1 & 0x0000003f;
}
bool tls_is_rtc_running(void)
{
int ctrl2 = tls_reg_read32(HR_PMU_RTC_CTRL2);
return ctrl2 & (1 << 16) ? true : false;
}
void PMU_RTC_IRQHandler(void)
{
tls_reg_write32(HR_PMU_INTERRUPT_SRC, BIT(4)); /* clear rtc interrupt */

View File

@ -95,7 +95,7 @@ void _mutex_release (u32 *mutex)
u8 *TaskStartStk = NULL;
tls_os_task_t tststarthdl = NULL;
#define TASK_USERMAIN_STK_SIZE 1024
#define TASK_USERMAIN_STK_SIZE 512
u8 *TaskUsermainStk = NULL;
tls_os_task_t tstusermainhdl = NULL;

View File

@ -77,7 +77,7 @@
#define configTICK_RATE_HZ ( ( portTickType ) 500u )
#define configMAX_PRIORITIES (63)
#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 256 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) 12 * 1024 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) 4 * 1024 )
#define configMAX_TASK_NAME_LEN ( 10 ) //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0