350 lines
10 KiB
C
350 lines
10 KiB
C
#include "app_common.h"
|
|
#include "lvgl.h"
|
|
#include "lv_port_disp.h"
|
|
#include "lv_port_indev.h"
|
|
#include "FreeRTOS.h"
|
|
#include "wm_include.h"
|
|
#include "lcd.h"
|
|
#include "watch_face.h"
|
|
#include "menu_screen.h"
|
|
#include "compass_screen.h"
|
|
#include "settings_screen.h"
|
|
#include "i2c.h"
|
|
#include "QMC5883L.h"
|
|
#include "BMP280.h"
|
|
#include "bma456w.h"
|
|
#include "watch_peripherals.h"
|
|
#include "watch_settings.h"
|
|
|
|
static void date_time_cb(struct tm * const dateTime)
|
|
{
|
|
if(!dateTime)return;
|
|
tls_get_rtc(dateTime);
|
|
//APP_LOG_DEBUG("RTC time : %d:%d:%d", dateTime->tm_hour, dateTime->tm_min, dateTime->tm_sec);
|
|
}
|
|
|
|
WatchFace_t watchFace;
|
|
MenuScreen_t menuScreen;
|
|
CompassScreen_t compassScreen;
|
|
SettingsScreen_t settingsScreen;
|
|
|
|
struct bma4_dev bma;
|
|
struct bma4_accel_config accel_conf;
|
|
struct bma456w_wrist_wear_wakeup_params setting;
|
|
struct bma4_int_pin_config pin_config;
|
|
uint16_t int_status;
|
|
|
|
static void setBrightness(uint8_t brightness)
|
|
{
|
|
extern LCDConfig_t LCDConfig;
|
|
lcd_set_backlight(&LCDConfig, brightness);
|
|
}
|
|
|
|
static void setBrightnessCb(uint8_t brightness)
|
|
{
|
|
|
|
persistency_get_settings()->display.brightness = brightness;
|
|
setBrightness(brightness);
|
|
}
|
|
|
|
static void setTimeCb(uint8_t hour, uint8_t minute, uint8_t second, uint8_t day, uint8_t month, uint8_t year)
|
|
{
|
|
struct tm timeToSet;
|
|
|
|
//First we get the current time from the RTC
|
|
tls_get_rtc(&timeToSet);
|
|
|
|
if(hour != 0xFF)
|
|
timeToSet.tm_hour = hour;
|
|
|
|
if(minute != 0xFF)
|
|
timeToSet.tm_min = minute;
|
|
|
|
if(second != 0xFF)
|
|
timeToSet.tm_sec = second;
|
|
|
|
if(day != 0xFF)
|
|
timeToSet.tm_mday = day;
|
|
|
|
if(month != 0xFF)
|
|
timeToSet.tm_mon = month;
|
|
|
|
if(year != 0xFF)
|
|
timeToSet.tm_year = year + 100;
|
|
|
|
tls_set_rtc(&timeToSet);
|
|
}
|
|
|
|
static void setTimeoutCb(uint8_t timeout)
|
|
{
|
|
persistency_get_settings()->display.sleep_timeout = timeout;
|
|
}
|
|
|
|
static void setOrientationCb(uint8_t orientation)
|
|
{
|
|
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());
|
|
}
|
|
|
|
SettingsScreenAPIInterface_t settingsScreenAPIInterface =
|
|
{
|
|
.setBrightnessSettingsCb = setBrightnessCb,
|
|
.setTimeSettingsCb = setTimeCb,
|
|
.setTimeoutSettingsCb = setTimeoutCb,
|
|
.setOrientationSettingsCb = setOrientationCb,
|
|
};
|
|
|
|
static uint16_t angle_with_offset(uint16_t angle, uint16_t offset)
|
|
{
|
|
return (angle + offset) >= 360 ? angle + offset - 360 : angle + offset;
|
|
}
|
|
|
|
static BMA4_INTF_RET_TYPE bma4_i2c_read(uint8_t reg_addr, uint8_t *read_data, uint32_t len, void *intf_ptr)
|
|
{
|
|
uint8_t dev_address = *(uint8_t*)intf_ptr;
|
|
|
|
return !i2c_read(dev_address, reg_addr, read_data, len);
|
|
}
|
|
|
|
static BMA4_INTF_RET_TYPE bma4_i2c_write(uint8_t reg_addr, const uint8_t *read_data, uint32_t len, void *intf_ptr)
|
|
{
|
|
uint8_t dev_address = *(uint8_t*)intf_ptr;
|
|
|
|
return !i2c_write(dev_address, reg_addr, read_data, len);
|
|
}
|
|
|
|
static void 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));
|
|
}
|
|
|
|
void gfx_task(void *param)
|
|
{
|
|
APP_LOG_TRACE("starting");
|
|
|
|
/* Initialize the lvgl library and peripherals (display and input device)*/
|
|
lv_init();
|
|
|
|
lv_port_disp_init();
|
|
lv_port_indev_init();
|
|
|
|
/* Initialize lvgl screens */
|
|
watch_face_init(&watchFace);
|
|
menu_screen_init(&menuScreen);
|
|
compass_screen_init(&compassScreen);
|
|
settings_screen_init(&settingsScreen);
|
|
settings_screen_register_API_interface(&settingsScreen, &settingsScreenAPIInterface);
|
|
|
|
watch_face_register_cb(&watchFace, &(date_time_cb));
|
|
watch_face_create(&watchFace);
|
|
|
|
lv_scr_load(watchFace.display);
|
|
|
|
/* Let's init the I2C interface */
|
|
i2c_init(I2C_SDA, I2C_SCL, 100000);
|
|
|
|
uint8_t aliveCounter = 0;
|
|
|
|
/* Init the magnetometer */
|
|
if(!QMC5883L_init())
|
|
APP_LOG_INFO("Failed to init QMC5883L");
|
|
else
|
|
APP_LOG_INFO("Inited QMC5883L");
|
|
tls_os_time_delay(2);
|
|
|
|
if(!QMC5883L_set_power_mode(Continuous))
|
|
APP_LOG_INFO("Failed to set QMC5883L mode");
|
|
else
|
|
APP_LOG_INFO("QMC5883L Mode set");
|
|
tls_os_time_delay(2);
|
|
|
|
if(!QMC5883L_configure_1(ODR_10HZ, FS_2G, OSR_512))
|
|
APP_LOG_INFO("Failed to configure 1 QMC5883L");
|
|
else
|
|
APP_LOG_INFO("QMC5883L configured");
|
|
|
|
//QMC5883L_set_calibration_data(-900, 2500, -1400, 1400, 2300, 7500, 0.0);
|
|
QMC5883L_set_calibration_data(4812, 8550, -3200, 20, -2200, 3500, 0.0);
|
|
|
|
/* Init the BMP280 */
|
|
if(!BMP280_init())
|
|
APP_LOG_INFO("Failed to init BMP280");
|
|
else
|
|
APP_LOG_INFO("Inited BMP280");
|
|
|
|
if(!BMP280_configure(BMP280_Forced, BMP280_Oversampling_x16, BMP280_Oversampling_x16, BMP280_Filter_x16, BMP280_Standby_4000MS))
|
|
APP_LOG_INFO("Failed to configure BMP280");
|
|
else
|
|
APP_LOG_INFO("BMP280 configured");
|
|
|
|
/* Init the BMA456 */
|
|
bma.intf = BMA4_I2C_INTF;
|
|
uint8_t dev_addr = BMA4_I2C_ADDR_SECONDARY;
|
|
bma.intf_ptr = &dev_addr;
|
|
bma.bus_read = &(bma4_i2c_read);
|
|
bma.bus_write = &(bma4_i2c_write);
|
|
bma.variant = BMA45X_VARIANT;
|
|
bma.delay_us = &(delay_us);
|
|
bma.read_write_len = 46;
|
|
bma.perf_mode_status = BMA4_DISABLE;
|
|
|
|
if(bma456w_init(&bma) == BMA4_OK)
|
|
APP_LOG_INFO("BMA456 init");
|
|
else
|
|
APP_LOG_INFO("Failed to init BMA456");
|
|
|
|
bma4_soft_reset(&bma);
|
|
tls_os_time_delay(2);
|
|
|
|
if(bma456w_write_config_file(&bma) == BMA4_OK)
|
|
APP_LOG_INFO("BMA456 config ok");
|
|
else
|
|
APP_LOG_INFO("BMA456 config failed");
|
|
|
|
accel_conf.odr = BMA4_OUTPUT_DATA_RATE_100HZ;
|
|
accel_conf.range = BMA4_ACCEL_RANGE_2G;
|
|
accel_conf.bandwidth = BMA4_ACCEL_NORMAL_AVG4;
|
|
accel_conf.perf_mode = BMA4_CIC_AVG_MODE;
|
|
|
|
if(bma4_set_accel_config(&accel_conf, &bma) == BMA4_OK)
|
|
APP_LOG_INFO("BMA456 accel conf ok");
|
|
else
|
|
APP_LOG_INFO("BMA456 accel conf failed");
|
|
|
|
if(bma4_set_accel_enable(1, &bma) == BMA4_OK)
|
|
APP_LOG_INFO("BMA456 accel en ok");
|
|
else
|
|
APP_LOG_INFO("BMA456 accel en failed");
|
|
|
|
bma456w_feature_enable(BMA456W_WRIST_WEAR_WAKEUP, 1, &bma);
|
|
|
|
bma456w_get_wrist_wear_wakeup_param_config(&setting, &bma);
|
|
|
|
APP_LOG_DEBUG("%d %d %d %d %d %d %d %d", setting.min_angle_focus, setting.min_angle_non_focus, setting.angle_landscape_right, setting.angle_landscape_left, setting.angle_portrait_up, setting.angle_portrait_down, setting.min_dur_moved, setting.min_dur_quite);
|
|
|
|
if(bma4_get_int_pin_config(&pin_config, BMA4_INTR1_MAP, &bma) == BMA4_OK)
|
|
APP_LOG_INFO("BMA456 get pin conf ok");
|
|
else
|
|
APP_LOG_INFO("BMA456 get pin conf failed");
|
|
|
|
if(bma456w_map_interrupt(BMA4_INTR1_MAP, BMA456W_WRIST_WEAR_WAKEUP_INT, BMA4_ENABLE, &bma) == BMA4_OK)
|
|
APP_LOG_INFO("BMA456 map int ok");
|
|
else
|
|
APP_LOG_INFO("BMA456 map int failed");
|
|
|
|
pin_config.edge_ctrl = BMA4_EDGE_TRIGGER;
|
|
pin_config.output_en = BMA4_OUTPUT_ENABLE;
|
|
pin_config.lvl = BMA4_ACTIVE_LOW;
|
|
pin_config.od = BMA4_PUSH_PULL;
|
|
pin_config.input_en = BMA4_INPUT_DISABLE;
|
|
|
|
if(bma4_set_int_pin_config(&pin_config, BMA4_INTR1_MAP, &bma) == BMA4_OK)
|
|
APP_LOG_INFO("BMA456 set pin conf ok");
|
|
else
|
|
APP_LOG_INFO("BMA456 set pin conf failed");
|
|
|
|
watch_peripherals_init(27);
|
|
|
|
/* Once we are done with the initializing steps we
|
|
don't forget to turn the backlight on ! */
|
|
setBrightness(persistency_get_settings()->display.brightness);
|
|
|
|
extern LCDConfig_t LCDConfig;
|
|
float temperature = 0;
|
|
float pressure = 0;
|
|
|
|
for(;;)
|
|
{
|
|
lv_timer_handler();
|
|
tls_os_time_delay(5);
|
|
|
|
if(compass_screen_is_in_use(&compassScreen))
|
|
{
|
|
if(QMC5883L_is_data_available())
|
|
{
|
|
/*
|
|
QMC5883L_MData_t MDataRaw = QMC5883L_get_MFields_raw();
|
|
APP_LOG_TRACE("X %d Y %d Z %d", MDataRaw.MFieldX, MDataRaw.MFieldY, MDataRaw.MFieldZ);
|
|
*/
|
|
|
|
QMC5883L_MData_calibrated_t MData = QMC5883L_get_MFields_calibrated();
|
|
compass_screen_set_azimuth(&compassScreen, angle_with_offset(QMC5883L_get_azimuth(MData), 180));
|
|
}
|
|
|
|
compass_screen_set_temperature(&compassScreen, temperature);
|
|
}
|
|
|
|
|
|
uint8_t rslt = bma456w_read_int_status(&int_status, &bma);
|
|
if(rslt != BMA4_OK)
|
|
APP_LOG_DEBUG("Failed to read int status");
|
|
|
|
if((BMA4_OK == rslt) && (int_status & BMA456W_WRIST_WEAR_WAKEUP_INT))
|
|
{
|
|
APP_LOG_DEBUG("Wrist tilt");
|
|
}
|
|
|
|
if(++aliveCounter % 200 == 0)
|
|
{
|
|
pressure = BMP280_get_pressure(&temperature);
|
|
BMP280_trigger_measurement();
|
|
APP_LOG_DEBUG("GFX thread, temp : %0.2f °C, press : %0.2f hPa, bat : %u mV",
|
|
temperature,
|
|
pressure/100,
|
|
watch_peripherals_get_battery_voltage());
|
|
aliveCounter = 0;
|
|
}
|
|
|
|
/* Handle inactivity periods : */
|
|
if( persistency_get_settings()->display.sleep_timeout != 0 &&
|
|
lv_disp_get_inactive_time(NULL) > (persistency_get_settings()->display.sleep_timeout * 1000))
|
|
{
|
|
// First, we disable the display backlight and we set all the peripherals in their low power mode
|
|
setBrightness(0);
|
|
//lcd_on(&LCDConfig, false);
|
|
lcd_sleep(&LCDConfig, true);
|
|
QMC5883L_set_power_mode(Standby);
|
|
CST816D_set_power_mode();
|
|
// 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);
|
|
QMC5883L_set_power_mode(Continuous);
|
|
//lcd_on(&LCDConfig, true);
|
|
lcd_sleep(&LCDConfig, false);
|
|
setBrightness(persistency_get_settings()->display.brightness);
|
|
}
|
|
|
|
/* 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");
|
|
}
|
|
|
|
}
|
|
}
|
|
} |