From ea3e59ad3d7655ce37caae1c5d0fce4839176b27 Mon Sep 17 00:00:00 2001 From: Daniel Kampert Date: Mon, 27 May 2024 09:06:11 +0200 Subject: [PATCH] - Add skeleton for RV-8263-C8 RTC - Rename display driver to match it with the vendor_type scheme of the other drivers - Remove Funkytown song from Buzzer driver - Disable selecting of the step counter and battery arc in digital watchface - Reorganize Kconfig and move the application configuration into the "Applications" menu --- app/Kconfig | 48 +- .../zswatch_nrf5340_cpuapp_5.conf | 4 +- .../zswatch_nrf5340_cpuapp_5.overlay | 23 +- app/drivers/CMakeLists.txt | 1 + app/drivers/Kconfig | 6 +- app/drivers/display/gc9a01/CMakeLists.txt | 2 +- app/drivers/display/gc9a01/Kconfig | 2 +- .../gc9a01/{gc9a01.c => buydisplay_gc9a01.c} | 0 app/drivers/input/cst816s/Kconfig | 4 +- app/drivers/rtc/CMakeLists.txt | 6 + app/drivers/rtc/Kconfig | 3 + app/drivers/rtc/rv8263c8/CMakeLists.txt | 7 + app/drivers/rtc/rv8263c8/Kconfig | 58 ++ .../microcrystal_rv8263c8_interrupt.c | 70 +++ .../microcrystal_rv8263c8_interrupt.h | 15 + .../rtc/rv8263c8/microcrystal_rv8263c8.c | 494 ++++++++++++++++++ .../rtc/rv8263c8/microcrystal_rv8263c8.h | 22 + .../private/microcrystal_rv8263c8_types.h | 36 ++ app/drivers/sensor/bmi270/Kconfig | 37 +- app/drivers/sensor/bmi270/bosch_bmi270.c | 2 +- .../bindings/rtc/microcrystal,rv-8263-c8.yml | 39 ++ app/dts/bindings/sensor/bosch,bmi270-plus.yml | 1 + app/prj.conf | 2 +- app/src/applications/compass/compass_app.c | 6 +- .../sensors_summary/sensors_summary_app.c | 2 +- app/src/drivers/zsw_buzzer.c | 16 - .../0_digital/zsw_watchface_digital_ui.c | 17 +- 27 files changed, 840 insertions(+), 83 deletions(-) rename app/drivers/display/gc9a01/{gc9a01.c => buydisplay_gc9a01.c} (100%) create mode 100644 app/drivers/rtc/CMakeLists.txt create mode 100644 app/drivers/rtc/Kconfig create mode 100644 app/drivers/rtc/rv8263c8/CMakeLists.txt create mode 100644 app/drivers/rtc/rv8263c8/Kconfig create mode 100644 app/drivers/rtc/rv8263c8/interrupt/microcrystal_rv8263c8_interrupt.c create mode 100644 app/drivers/rtc/rv8263c8/interrupt/microcrystal_rv8263c8_interrupt.h create mode 100644 app/drivers/rtc/rv8263c8/microcrystal_rv8263c8.c create mode 100644 app/drivers/rtc/rv8263c8/microcrystal_rv8263c8.h create mode 100644 app/drivers/rtc/rv8263c8/private/microcrystal_rv8263c8_types.h create mode 100644 app/dts/bindings/rtc/microcrystal,rv-8263-c8.yml diff --git a/app/Kconfig b/app/Kconfig index b870a3b3..bd17c409 100644 --- a/app/Kconfig +++ b/app/Kconfig @@ -70,6 +70,31 @@ menu "ZSWatch" bool prompt "Activate the application 'PPT remote'" default n + + menu "Configuration" + menu "Compass" + depends on APPLICATIONS_USE_COMPASS + + config APPLICATIONS_CONFIGURATION_COMPASS_REFRESH_INTERVAL_MS + int + prompt "Refresh interval in milliseconds" + default 50 + + config APPLICATIONS_CONFIGURATION_COMPASS_CALIBRATION_TIME_S + int + prompt "Calibration time in seconds" + default 30 + endmenu + + menu "Sensors Summary" + depends on APPLICATIONS_USE_SENSORS_SUMMARY + + config APPLICATIONS_CONFIGURATION_SENSORS_SUMMARY_REFRESH_INTERVAL_MS + int + prompt "Refresh interval in milliseconds" + default 100 + endmenu + endmenu endmenu menu "Watchface" @@ -111,29 +136,6 @@ menu "ZSWatch" default 85 endmenu - menu "Sensors Summary" - depends on APPLICATIONS_USE_SENSORS_SUMMARY - - config DEFAULT_CONFIGURATION_SENSORS_SUMMARY_REFRESH_INTERVAL_MS - int - prompt "Refresh interval in milliseconds" - default 100 - endmenu - - menu "Compass" - depends on APPLICATIONS_USE_COMPASS - - config DEFAULT_CONFIGURATION_COMPASS_REFRESH_INTERVAL_MS - int - prompt "Refresh interval in milliseconds" - default 50 - - config DEFAULT_CONFIGURATION_COMPASS_CALIBRATION_TIME_S - int - prompt "Calibration time in seconds" - default 30 - endmenu - menu "Power Management" config POWER_MANAGEMENT_IDLE_TIMEOUT_SECONDS int diff --git a/app/boards/arm/zswatch_nrf5340/zswatch_nrf5340_cpuapp_5.conf b/app/boards/arm/zswatch_nrf5340/zswatch_nrf5340_cpuapp_5.conf index c2368b48..20ce8c79 100644 --- a/app/boards/arm/zswatch_nrf5340/zswatch_nrf5340_cpuapp_5.conf +++ b/app/boards/arm/zswatch_nrf5340/zswatch_nrf5340_cpuapp_5.conf @@ -1,9 +1,7 @@ CONFIG_ZSWATCH_PCB_REV=5 CONFIG_BT_DIS_HW_REV_STR="5" -#--------------- # FLASH -#----------------- CONFIG_FLASH=y CONFIG_FLASH_PAGE_LAYOUT=y CONFIG_STREAM_FLASH=y @@ -49,3 +47,5 @@ CONFIG_NVS=y CONFIG_DEBUG_COREDUMP_BACKEND_OTHER=y +CONFIG_RTC=y +CONFIG_RTC_ALARM=y \ No newline at end of file diff --git a/app/boards/arm/zswatch_nrf5340/zswatch_nrf5340_cpuapp_5.overlay b/app/boards/arm/zswatch_nrf5340/zswatch_nrf5340_cpuapp_5.overlay index ed16b9ff..bdda7c1c 100644 --- a/app/boards/arm/zswatch_nrf5340/zswatch_nrf5340_cpuapp_5.overlay +++ b/app/boards/arm/zswatch_nrf5340/zswatch_nrf5340_cpuapp_5.overlay @@ -77,6 +77,7 @@ ; low-power-enable; }; + group2 { psels = ; low-power-enable; @@ -125,21 +126,25 @@ buttons: buttons { compatible = "gpio-keys"; + button1: button_1 { label = "top-right"; gpios = <&gpio0 27 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; zephyr,code = ; }; + button2: button_2 { label = "bottom-left"; gpios = <&gpio1 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; zephyr,code = ; }; + button3: button_3 { label = "bottom-right"; gpios = <&gpio0 31 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; zephyr,code = ; }; + button4: button_4 { label = "top-left"; gpios = <&gpio0 26 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; @@ -167,12 +172,15 @@ pwmleds { compatible = "pwm-leds"; + display_blk: pwm_led_0 { pwms = <&pwm0 0 PWM_USEC(15) PWM_POLARITY_INVERTED>; }; + vibrator_pwm: pwm_led_1 { pwms = <&pwm1 0 PWM_MSEC(20) 0>; }; + buzzer_pwm: pwm_led_2 { pwms = <&pwm2 0 PWM_HZ(880) PWM_POLARITY_NORMAL>; }; @@ -181,6 +189,13 @@ }; &i2c1 { + rv_8263_c8: rv-8263-c8@A2 { + compatible = "microcrystal,rv-8263-c8"; + reg = <0xA2>; + status = "okay"; + clkout = <7>; + }; + bmi270: bmi270@68 { compatible = "bosch,bmi270-plus"; reg = <0x68>; @@ -200,6 +215,7 @@ resolution = <0>; frequency = <0>; }; + npm1300_ek_pmic: pmic@6b { compatible = "nordic,npm1300"; reg = <0x6b>; @@ -253,6 +269,7 @@ thermistor-beta = <3380>; charging-enable; }; + npm1300_ek_buttons: buttons { compatible = "gpio-keys"; status = "disabled"; @@ -286,6 +303,7 @@ pinctrl-0 = <&qspi_default>; pinctrl-1 = <&qspi_sleep>; pinctrl-names = "default", "sleep"; + gd25lq128d: gd25lq128d@0 { compatible = "nordic,qspi-nor"; reg = <0>; @@ -309,6 +327,7 @@ / { fstab { compatible = "zephyr,fstab"; + lvgl_lfs: lvgl_lfs { compatible = "zephyr,fstab,littlefs"; mount-point = "/lvgl_lfs"; @@ -336,13 +355,15 @@ label = "littlefs_storage"; reg = <0x00000000 0x00200000>; }; + lvgl_raw_partition: partition@200000 { label = "lvgl_raw_partition"; reg = <0x00200000 0x00200000>; }; + storage_partition: partition@400000 { label = "storage_partition"; reg = <0x400000 0x100000 >; }; }; -}; +}; \ No newline at end of file diff --git a/app/drivers/CMakeLists.txt b/app/drivers/CMakeLists.txt index 31f019e0..5c438f54 100644 --- a/app/drivers/CMakeLists.txt +++ b/app/drivers/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(display) add_subdirectory(input) +add_subdirectory(rtc) add_subdirectory_ifdef(CONFIG_SENSOR sensor) \ No newline at end of file diff --git a/app/drivers/Kconfig b/app/drivers/Kconfig index aa785211..774a916e 100644 --- a/app/drivers/Kconfig +++ b/app/drivers/Kconfig @@ -1,6 +1,4 @@ rsource "display/Kconfig" rsource "input/Kconfig" - -menu "Drivers" - rsource "sensor/Kconfig" -endmenu \ No newline at end of file +rsource "rtc/Kconfig" +rsource "sensor/Kconfig" \ No newline at end of file diff --git a/app/drivers/display/gc9a01/CMakeLists.txt b/app/drivers/display/gc9a01/CMakeLists.txt index a58a904e..860978b4 100644 --- a/app/drivers/display/gc9a01/CMakeLists.txt +++ b/app/drivers/display/gc9a01/CMakeLists.txt @@ -1 +1 @@ -zephyr_sources(gc9a01.c) \ No newline at end of file +zephyr_sources(buydisplay_gc9a01.c) \ No newline at end of file diff --git a/app/drivers/display/gc9a01/Kconfig b/app/drivers/display/gc9a01/Kconfig index 8bc74830..a4562ec0 100644 --- a/app/drivers/display/gc9a01/Kconfig +++ b/app/drivers/display/gc9a01/Kconfig @@ -1,5 +1,5 @@ menuconfig GC9A01 - bool "GC9A01 compatible display controller driver" + bool "GC9A01 Display" default n select SPI help diff --git a/app/drivers/display/gc9a01/gc9a01.c b/app/drivers/display/gc9a01/buydisplay_gc9a01.c similarity index 100% rename from app/drivers/display/gc9a01/gc9a01.c rename to app/drivers/display/gc9a01/buydisplay_gc9a01.c diff --git a/app/drivers/input/cst816s/Kconfig b/app/drivers/input/cst816s/Kconfig index 43adc895..5f4224f9 100644 --- a/app/drivers/input/cst816s/Kconfig +++ b/app/drivers/input/cst816s/Kconfig @@ -3,7 +3,7 @@ # SPDX-License-Identifier: Apache-2.0 menuconfig INPUT_MODIFIED_CST816S - bool "Use modified out of tree CST816S capacitive touch panel driver" + bool "CST816S Capacitive touch panel driver" default y depends on DT_HAS_HYNITRON_CST816S_ENABLED select I2C @@ -26,4 +26,4 @@ config INPUT_CST816S_INTERRUPT help Enable interrupt support (requires GPIO). -endif # INPUT_CST816S +endif diff --git a/app/drivers/rtc/CMakeLists.txt b/app/drivers/rtc/CMakeLists.txt new file mode 100644 index 00000000..a095c974 --- /dev/null +++ b/app/drivers/rtc/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright (c) 2024, Daniel Kampert +# +# SPDX-License-Identifier: Apache-2.0 +# + +add_subdirectory_ifdef(CONFIG_RV_8263_C8 rv8263c8) \ No newline at end of file diff --git a/app/drivers/rtc/Kconfig b/app/drivers/rtc/Kconfig new file mode 100644 index 00000000..903dd8f1 --- /dev/null +++ b/app/drivers/rtc/Kconfig @@ -0,0 +1,3 @@ +if RTC + rsource "rv8263c8/Kconfig" +endif \ No newline at end of file diff --git a/app/drivers/rtc/rv8263c8/CMakeLists.txt b/app/drivers/rtc/rv8263c8/CMakeLists.txt new file mode 100644 index 00000000..900aa7a5 --- /dev/null +++ b/app/drivers/rtc/rv8263c8/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2024, Daniel Kampert +# +# SPDX-License-Identifier: Apache-2.0 +# + +zephyr_sources(microcrystal_rv8263c8.c) +zephyr_sources(interrupt/microcrystal_rv8263c8_interrupt.c) \ No newline at end of file diff --git a/app/drivers/rtc/rv8263c8/Kconfig b/app/drivers/rtc/rv8263c8/Kconfig new file mode 100644 index 00000000..6befd40b --- /dev/null +++ b/app/drivers/rtc/rv8263c8/Kconfig @@ -0,0 +1,58 @@ +# RV-8263-C8 RTC configuration options. + +# Copyright (c) 240, Daniel Kampert +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig RV_8263_C8 + bool "RV-8263-C8 RTC" + depends on DT_HAS_MICROCRYSTAL_RV_8263_C8_ENABLED + default y + select I2C + help + Enable the driver for the RV-8263-C8 RTC. + +if RV_8263_C8 + +module = MICROCRYSTAL_RV_8263_C8 +module-str = MICROCRYSTAL_RV_8263_C8 +source "subsys/logging/Kconfig.template.log_config" + + config RV_8263_C8_THREAD_STACK_SIZE + int "RTC delayed work thread stack size" + depends on RV_8263_C8_INTERRUPT_OWN_THREAD + default 1024 + + config RV_8263_C8_THREAD_PRIORITY + int "RV-8263-C8 thread priority" + depends on RV_8263_C8_INTERRUPT_OWN_THREAD + default 10 + + choice + prompt "RV-8263-C8 interrupt mode" + default RV_8263_C8_INTERRUPT_NONE + + config RV_8263_C8_INTERRUPT_NONE + bool "No interrupt" + help + Disable the INTERRUPT interface. + + config RV_8263_C8_INTERRUPT_GLOBAL_THREAD + depends on GPIO + select RV_8263_C8_INTERRUPT + bool "Use workqueue" + help + Use the global workqueue to process the interrupts from the RV-8263-C8. + + config RV_8263_C8_INTERRUPT_OWN_THREAD + depends on GPIO + select RV_8263_C8_INTERRUPT + bool "Use driver thread" + help + Use a separate thread to process the interrupts from the RV-8263-C8. + endchoice + + config RV_8263_C8_INTERRUPT + bool + +endif \ No newline at end of file diff --git a/app/drivers/rtc/rv8263c8/interrupt/microcrystal_rv8263c8_interrupt.c b/app/drivers/rtc/rv8263c8/interrupt/microcrystal_rv8263c8_interrupt.c new file mode 100644 index 00000000..4e4c20f2 --- /dev/null +++ b/app/drivers/rtc/rv8263c8/interrupt/microcrystal_rv8263c8_interrupt.c @@ -0,0 +1,70 @@ +/* microcrystal_rv8263c8_interrupt.c - Driver for Micro Crystal RV-8263-C8 RTC. */ + +/* + * Copyright (c) 2024, Daniel Kampert + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "../microcrystal_rv8263c8.h" +#include "../private/microcrystal_rv8263c8_types.h" + +LOG_MODULE_REGISTER(microcrystal_rv8263c8_interrupt, CONFIG_MICROCRYSTAL_RV_8263_C8_LOG_LEVEL); + +#ifdef CONFIG_RV_8263_C8_TRIGGER_OWN_THREAD +static K_KERNEL_STACK_DEFINE(rv8263c8_thread_stack, CONFIG_RV_8263_C8_THREAD_STACK_SIZE); +static struct k_thread rv8263c8_thread; +#endif + +/** @brief + * @param p_dev + * @param p_cb + * @param pins +*/ +static void rv8263c8_gpio_on_interrupt_callback(const struct device *p_dev, struct gpio_callback *p_cb, uint32_t pins) +{ + ARG_UNUSED(pins); + ARG_UNUSED(p_dev); +} + +int rv8263c8_init_interrupt(const struct device *p_dev) +{ + struct rv8263c8_data *data = p_dev->data; + const struct rv8263c8_config *config = p_dev->config; + + LOG_DBG("Initialize interrupts..."); + + if (!gpio_is_ready_dt(&config->int_gpio)) { + LOG_ERR("INT GPIO device not ready!"); + return -ENODEV; + } + + if (gpio_pin_configure_dt(&config->int_gpio, GPIO_INPUT)) { + return -EFAULT; + } + /* + data->dev = p_dev; + + #ifdef CONFIG_RV_8263_C8_TRIGGER_OWN_THREAD + k_sem_init(&data->sem, 0, K_SEM_MAX_LIMIT); + + k_thread_create(&bmi2_thread, bmi2_thread_stack, CONFIG_RV_8263_C8_THREAD_STACK_SIZE, + bmi2_worker_thread, data, NULL, NULL, K_PRIO_COOP(CONFIG_RV_8263_C8_THREAD_PRIORITY), + 0, K_NO_WAIT); + #else + data->work.handler = bmi2_worker; + #endif + + gpio_init_callback(&data->gpio_handler, rv8263c8_gpio_on_interrupt_callback, BIT(config->int_gpio.pin)); + + if (gpio_add_callback(config->int_gpio.port, &data->gpio_handler)) { + return -EFAULT; + } + + LOG_DBG("Interrupts ready!"); + */ + return 0; +} \ No newline at end of file diff --git a/app/drivers/rtc/rv8263c8/interrupt/microcrystal_rv8263c8_interrupt.h b/app/drivers/rtc/rv8263c8/interrupt/microcrystal_rv8263c8_interrupt.h new file mode 100644 index 00000000..37287b7a --- /dev/null +++ b/app/drivers/rtc/rv8263c8/interrupt/microcrystal_rv8263c8_interrupt.h @@ -0,0 +1,15 @@ +/* microcrystal_rv8263c8_interrupt.c - Driver for Micro Crystal RV-8263-C8 RTC. */ + +/* + * Copyright (c) 2024, Daniel Kampert + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** @brief + * @param p_dev + * @return 0 when successful +*/ +int rv8263c8_init_interrupt(const struct device *p_dev); \ No newline at end of file diff --git a/app/drivers/rtc/rv8263c8/microcrystal_rv8263c8.c b/app/drivers/rtc/rv8263c8/microcrystal_rv8263c8.c new file mode 100644 index 00000000..78acd90a --- /dev/null +++ b/app/drivers/rtc/rv8263c8/microcrystal_rv8263c8.c @@ -0,0 +1,494 @@ +/* microcrystal_rv8263c8.c - Driver for Micro Crystal RV-8263-C8 RTC. */ + +/* + * Copyright (c) 2024, Daniel Kampert + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "microcrystal_rv8263c8.h" +#include "private/microcrystal_rv8263c8_types.h" +#include "interrupt/microcrystal_rv8263c8_interrupt.h" + +#define RV8263C8_REGISTER_CONTROL1 0x00 +#define RV8263C8_REGISTER_CONTROL2 0x01 +#define RV8263C8_REGISTER_OFFSET 0x02 +#define RV8263C8_REGISTER_RAM 0x03 +#define RV8263C8_REGISTER_SECONDS 0x04 +#define RV8263C8_REGISTER_MINUTES 0x05 +#define RV8263C8_REGISTER_HOURS 0x06 +#define RV8263C8_REGISTER_DATE 0x07 +#define RV8263C8_REGISTER_WEEKDAY 0x08 +#define RV8263C8_REGISTER_MONTH 0x09 +#define RV8263C8_REGISTER_YEAR 0x0A +#define RV8263C8_REGISTER_SECONDS_ALARM 0x0B +#define RV8263C8_REGISTER_MINUTES_ALARM 0x0C +#define RV8263C8_REGISTER_HOURS_ALARM 0x0D +#define RV8263C8_REGISTER_DATE_ALARM 0x0E +#define RV8263C8_REGISTER_WEEKDAY_ALARM 0x0F +#define RV8263C8_REGISTER_TIMER_VALUE 0x10 +#define RV8263C8_REGISTER_TIMER_MODE 0x11 + +#define RV8263C8_24H_MODE_ENABLE (0x00 << 0x01) +#define RV8263C8_24H_MODE_DISABLE (0x00 << 0x01) +#define RV8263C8_CLOCK_ENABLE (0x00 << 0x05) +#define RV8263C8_CLOCK_DISABLE (0x01 << 0x05) +#define RV8263C8_ALARM_INT_ENABLE (0x01 << 0x07) +#define RV8263C8_ALARM_INT_DISABLE (0x00 << 0x05) +#define RV8263C8_MINUTE_INT_ENABLE (0x01 << 0x05) +#define RV8263C8_MINUTE_INT_DISABLE (0x00 << 0x05) +#define RV8263C8_HALF_MINUTE_INT_ENABLE (0x01 << 0x04) +#define RV8263C8_HALF_MINUTE_INT_DISABLE (0x00 << 0x04) +#define RV8263C8_ALARM_ENABLE (0x00 << 0x07) +#define RV8263C8_ALARM_DISABLE (0x01 << 0x07) +#define RV8263C8_SOFTWARE_RESET (0x58) + +#define SECONDS_BITS GENMASK(6, 0) +#define MINUTES_BITS GENMASK(7, 0) +#define HOURS_BITS GENMASK(5, 0) +#define DATE_BITS GENMASK(5, 0) +#define MONTHS_BITS GENMASK(4, 0) +#define WEEKDAY_BITS GENMASK(2, 0) +#define YEAR_BITS GENMASK(7, 0) +#define VALIDATE_24HR BIT(6) + +#define MIN_SEC 0 +#define MAX_SEC 59 +#define MIN_MIN 0 +#define MAX_MIN 59 +#define MIN_HOUR 0 +#define MAX_HOUR 23 +#define MAX_WDAY 7 +#define MIN_WDAY 1 +#define MAX_MDAY 31 +#define MIN_MDAY 1 +#define MAX_MON 12 +#define MIN_MON 1 +#define MIN_YEAR_DIFF 0 // YEAR - 1900 */ +#define MAX_YEAR_DIFF 99 // YEAR - 1999 */ + +#define DT_DRV_COMPAT microcrystal_rv_8263_c8 + +LOG_MODULE_REGISTER(microcrystal_rv8263c8, CONFIG_MICROCRYSTAL_RV_8263_C8_LOG_LEVEL); + +static void rv8263c8_isr(const struct device *p_dev) +{ + struct rv8263c8_data *const dev_data = p_dev->data; + const struct rv8263c8_config *config = p_dev->config; +} + +static int rv8263c8_set_time(const struct device *p_dev, const struct rtc_time *p_tm) +{ + int err; + uint8_t regs[7]; + + struct rv8263c8_data *data = p_dev->data; + const struct rv8263c8_config *config = p_dev->config; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + LOG_DBG("Set time: year = %u, mon = %u, mday = %u, wday = %u, hour = %u, min = %u, sec = %u", + p_tm->tm_year, p_tm->tm_mon, p_tm->tm_mday, p_tm->tm_wday, p_tm->tm_hour, p_tm->tm_min, p_tm->tm_sec); + + regs[0] = bin2bcd(p_tm->tm_sec) & SECONDS_BITS; + regs[1] = bin2bcd(p_tm->tm_min); + regs[2] = bin2bcd(p_tm->tm_hour); + regs[3] = bin2bcd(p_tm->tm_wday); + regs[4] = bin2bcd(p_tm->tm_mday); + regs[5] = bin2bcd(p_tm->tm_mon); + regs[6] = bin2bcd((p_tm->tm_year % 100)); + + err = i2c_burst_write_dt(&config->i2c_bus, RV8263C8_REGISTER_SECONDS, regs, sizeof(regs)); + + k_spin_unlock(&data->lock, key); + + return err; +} + +static int rv8263c8_get_time(const struct device *p_dev, struct rtc_time *p_timeptr) +{ + int err; + uint8_t regs[7]; + + struct rv8263c8_data *data = p_dev->data; + const struct rv8263c8_config *config = p_dev->config; + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + err = i2c_burst_read_dt(&config->i2c_bus, RV8263C8_REGISTER_SECONDS, regs, sizeof(regs)); + if (err != 0) { + goto rv8263c8_get_time_exit; + } + + p_timeptr->tm_sec = bcd2bin(regs[0] & SECONDS_BITS); + p_timeptr->tm_min = bcd2bin(regs[1] & MINUTES_BITS); + p_timeptr->tm_hour = bcd2bin(regs[2] & HOURS_BITS); + p_timeptr->tm_wday = bcd2bin(regs[3] & WEEKDAY_BITS); + p_timeptr->tm_mday = bcd2bin(regs[4] & DATE_BITS); + p_timeptr->tm_mon = bcd2bin(regs[5] & MONTHS_BITS); + p_timeptr->tm_year = bcd2bin(regs[6] & YEAR_BITS); + p_timeptr->tm_year = p_timeptr->tm_year + 100; + + // Unused + p_timeptr->tm_nsec = 0; + p_timeptr->tm_isdst = -1; + p_timeptr->tm_yday = -1; + + // Validate the chip in 24hr mode + if (regs[2] & VALIDATE_24HR) { + err = -ENODATA; + goto rv8263c8_get_time_exit; + } + + LOG_DBG("get time: year = %d, mon = %d, mday = %d, wday = %d, hour = %d, min = %d, sec = %d", + p_timeptr->tm_year, p_timeptr->tm_mon, p_timeptr->tm_mday, p_timeptr->tm_wday, p_timeptr->tm_hour, p_timeptr->tm_min, + p_timeptr->tm_sec); + +rv8263c8_get_time_exit: + k_spin_unlock(&data->lock, key); + + return err; +} + +static int rv8263c8_init(const struct device *p_dev) +{ + int err; + struct rv8263c8_data *data = p_dev->data; + const struct rv8263c8_config *config = p_dev->config; + + if (!i2c_is_ready_dt(&config->i2c_bus)) { + LOG_ERR("I2C bus not ready"); + return -ENODEV; + } + + LOG_DBG("Configure RV-8263-C8:"); + LOG_DBG(" ClkOut: %u", config->clkout); + LOG_DBG(" Fast Mode: %u", config->fast_mode); + LOG_DBG(" Offset: %i", config->offset); + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + // Configure the first config register + err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL1, + RV8263C8_24H_MODE_DISABLE | RV8263C8_CLOCK_ENABLE); + if (err < 0) { + LOG_ERR("Error while writing CONTROL1! Error: %i", err); + goto rv8263c8_init_exit; + } + + // Configure the second config register + err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL2, + RV8263C8_ALARM_INT_ENABLE | RV8263C8_MINUTE_INT_DISABLE | RV8263C8_HALF_MINUTE_INT_DISABLE | (config->clkout << 0x00)); + if (err < 0) { + LOG_ERR("Error while writing CONTROL2! Error: %i", err); + goto rv8263c8_init_exit; + } + + // Configure the offset register + err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_OFFSET, + config->fast_mode << 0x07 | (config->offset & 0x7F)); + if (err < 0) { + LOG_ERR("Error while writing CONTROL2! Error: %i", err); + } + + if (config->int_gpio.port) { + if (rv8263c8_init_interrupt(p_dev)) { + LOG_ERR("Could not initialize interrupts!"); + return -EFAULT; + } + } + +rv8263c8_init_exit: + k_spin_unlock(&data->lock, key); + + return err; +} + +#ifdef CONFIG_RTC_ALARM +static bool rv8263c8_validate_alarm(const struct rtc_time *p_timeptr, uint32_t mask) +{ + if ((mask & RTC_ALARM_TIME_MASK_SECOND) && + (p_timeptr->tm_sec < MIN_SEC || p_timeptr->tm_sec > MAX_SEC)) { + return false; + } + + if ((mask & RTC_ALARM_TIME_MASK_MINUTE) && + (p_timeptr->tm_min < MIN_MIN || p_timeptr->tm_min > MAX_MIN)) { + return false; + } + + if ((mask & RTC_ALARM_TIME_MASK_HOUR) && + (p_timeptr->tm_hour < MIN_HOUR || p_timeptr->tm_hour > MAX_HOUR)) { + return false; + } + + return true; +} + +static int rv8263c8_alarm_get_supported_fields(const struct device *p_dev, uint16_t id, + uint16_t *p_mask) +{ + ARG_UNUSED(p_dev); + + if (id != 0) { + return -EINVAL; + } + + (*p_mask) = (RTC_ALARM_TIME_MASK_SECOND + | RTC_ALARM_TIME_MASK_MINUTE + | RTC_ALARM_TIME_MASK_HOUR); + + return 0; +} + +static int rv8263c8_alarm_set_time(const struct device *p_dev, uint16_t id, uint16_t mask, + const struct rtc_time *p_timeptr) +{ + int err; + struct rv8263c8_data *const dev_data = p_dev->data; + const struct rv8263c8_config *config = p_dev->config; + + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + if (id != 0) { + err = -EINVAL; + goto rv8263c8_alarm_set_time_exit; + } + + if ((mask > 0) && (p_timeptr == NULL)) { + err = -EINVAL; + goto rv8263c8_alarm_set_time_exit; + } + + // Check time valid + if (!rv8263c8_validate_alarm(p_timeptr, mask)) { + err = -EINVAL; + goto rv8263c8_alarm_set_time_exit; + } + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_SECONDS_ALARM, + RV8263C8_ALARM_ENABLE | p_timeptr->tm_sec); + } else { + err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_SECONDS_ALARM, RV8263C8_ALARM_DISABLE); + } + + if (err < 0) { + LOG_ERR("Error while writing SECONDS alarm! Error: %i", err); + goto rv8263c8_alarm_set_time_exit; + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_SECONDS_ALARM, + RV8263C8_ALARM_ENABLE | p_timeptr->tm_min); + } else { + err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_SECONDS_ALARM, RV8263C8_ALARM_DISABLE); + } + + if (err < 0) { + LOG_ERR("Error while writing MINUTE alarm! Error: %i", err); + goto rv8263c8_alarm_set_time_exit; + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_SECONDS_ALARM, + RV8263C8_ALARM_ENABLE | p_timeptr->tm_hour); + } else { + err = i2c_reg_write_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_SECONDS_ALARM, RV8263C8_ALARM_DISABLE); + } + + if (err < 0) { + LOG_ERR("Error while writing HOUR alarm! Error: %i", err); + goto rv8263c8_alarm_set_time_exit; + } + + err = i2c_reg_update_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL2, 0x01 << 0x07, RV8263C8_ALARM_INT_ENABLE); + if (err < 0) { + LOG_ERR("Error while writing CONTROL2! Error: %i", err); + goto rv8263c8_alarm_set_time_exit; + } + + err = 0; + +rv8263c8_alarm_set_time_exit: + k_spin_unlock(&dev_data->lock, key); + + return err; +} + +static int rv8263c8_alarm_get_time(const struct device *p_dev, uint16_t id, uint16_t *p_mask, + struct rtc_time *p_timeptr) +{ + int err; + struct rv8263c8_data *const dev_data = p_dev->data; + const struct rv8263c8_config *config = p_dev->config; + + rtc_alarm_callback cb; + void *cb_data; + rtc_update_callback update_cb; + void *update_cb_data; + uint8_t value; + + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + if (id != 0) { + err = -EINVAL; + goto rv8263c8_alarm_get_time_exit; + } + + if (p_timeptr == NULL) { + err = -EINVAL; + goto rv8263c8_alarm_get_time_exit; + } + + (*p_mask) = 0; + + err = i2c_reg_read_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_SECONDS_ALARM, &value); + if (err < 0) { + LOG_ERR("Error while reading SECONDS! Error: %i", err); + goto rv8263c8_alarm_get_time_exit; + } + + if (value <= MAX_SEC) { + p_timeptr->tm_sec = value; + (*p_mask) |= RTC_ALARM_TIME_MASK_SECOND; + } + + err = i2c_reg_read_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_MINUTES_ALARM, &value); + if (err < 0) { + LOG_ERR("Error while reading MINUTES! Error: %i", err); + goto rv8263c8_alarm_get_time_exit; + } + + if (value <= MAX_MIN) { + p_timeptr->tm_hour = value; + (*p_mask) |= RTC_ALARM_TIME_MASK_MINUTE; + } + + err = i2c_reg_read_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_HOURS_ALARM, &value); + if (err < 0) { + LOG_ERR("Error while reading SECONDS! Error: %i", err); + goto rv8263c8_alarm_get_time_exit; + } + + if (value <= MAX_HOUR) { + p_timeptr->tm_hour = value; + (*p_mask) |= RTC_ALARM_TIME_MASK_HOUR; + } + + err = 0; + +rv8263c8_alarm_get_time_exit: + k_spin_unlock(&dev_data->lock, key); + + return err; +} + +static int rv8263c8_alarm_set_callback(const struct device *p_dev, uint16_t id, + rtc_alarm_callback callback, void *p_user_data) +{ + int err; + struct rv8263c8_data *const dev_data = p_dev->data; + const struct rv8263c8_config *config = p_dev->config; + + if (id != 0) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + dev_data->cb = callback; + dev_data->cb_data = p_user_data; + + if (callback != NULL) { + err = i2c_reg_update_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL2, 0x01 << 0x07, RV8263C8_ALARM_INT_ENABLE); + } else { + err = i2c_reg_update_byte_dt(&config->i2c_bus, RV8263C8_REGISTER_CONTROL2, 0x01 << 0x07, RV8263C8_ALARM_INT_DISABLE); + } + + k_spin_unlock(&dev_data->lock, key); + + if (err < 0) { + LOG_ERR("Error while writing CONTROL2! Error: %i", err); + return err; + } + + return 0; +} + +static int rv8263c8_alarm_is_pending(const struct device *p_dev, uint16_t id) +{ + int ret; + struct rv8263c8_data *const dev_data = p_dev->data; + + if (id != 0) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + ret = dev_data->alarm_pending ? 1 : 0; + dev_data->alarm_pending = false; + + k_spin_unlock(&dev_data->lock, key); + + return ret; +} +#endif + +#ifdef CONFIG_RTC_UPDATE +static int rv8263c8_update_set_callback(const struct device *p_dev, + rtc_update_callback callback, void *p_user_data) +{ + struct rv8263c8_data *const dev_data = p_dev->data; + +#error Not supported + + k_spinlock_key_t key = k_spin_lock(&dev_data->lock); + + dev_data->update_cb = callback; + dev_data->update_cb_data = p_user_data; + + if (callback != NULL) { + // TODO: Enable + } else { + // TODO: Disable + } + + k_spin_unlock(&dev_data->lock, key); + + return 0; +} +#endif + +static const struct rtc_driver_api rv8263c8_driver_api = { + .set_time = rv8263c8_set_time, + .get_time = rv8263c8_get_time, +#ifdef CONFIG_RTC_ALARM + .alarm_get_supported_fields = rv8263c8_alarm_get_supported_fields, + .alarm_set_time = rv8263c8_alarm_set_time, + .alarm_get_time = rv8263c8_alarm_get_time, + .alarm_is_pending = rv8263c8_alarm_is_pending, + .alarm_set_callback = rv8263c8_alarm_set_callback, +#endif + +#ifdef CONFIG_RTC_UPDATE + .update_set_callback = rv8263c8_update_set_callback, +#endif +}; + +#define RV_8263_C8_DEFINE(inst) \ + static struct rv8263c8_data rv8263c8_data_##inst; \ + static const struct rv8263c8_config rv8263c8_config_##inst = { \ + .i2c_bus = I2C_DT_SPEC_INST_GET(inst), \ + .clkout = DT_INST_PROP(inst, clkout), \ + .fast_mode = DT_INST_PROP(inst, fast_mode), \ + .offset = DT_INST_PROP(inst, offset), \ + IF_ENABLED(CONFIG_BMI270_PLUS_TRIGGER, \ + (.int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, { 0 }),)) \ + }; \ + DEVICE_DT_INST_DEFINE(inst, &rv8263c8_init, NULL, &rv8263c8_data_##inst, \ + &rv8263c8_config_##inst, POST_KERNEL, CONFIG_RTC_INIT_PRIORITY, \ + &rv8263c8_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(RV_8263_C8_DEFINE) \ No newline at end of file diff --git a/app/drivers/rtc/rv8263c8/microcrystal_rv8263c8.h b/app/drivers/rtc/rv8263c8/microcrystal_rv8263c8.h new file mode 100644 index 00000000..23fc1068 --- /dev/null +++ b/app/drivers/rtc/rv8263c8/microcrystal_rv8263c8.h @@ -0,0 +1,22 @@ +/* microcrystal_rv8263c8.h - Driver for Micro Crystal RV-8263-C8 RTC. */ + +/* + * Copyright (c 2024, Daniel Kampert + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +/** @brief +*/ +typedef enum { + RV8263C8_OUT_32KHZ = 0, + RV8263C8_OUT_16KHZ, + RV8263C8_OUT_8KHZ, + RV8263C8_OUT_4KHZ, + RV8263C8_OUT_2KHZ, + RV8263C8_OUT_1KHZ, + RV8263C8_OUT_1HZ, + RV8263C8_OUT_LOW, +} rv_8263_c8_clkout_t; \ No newline at end of file diff --git a/app/drivers/rtc/rv8263c8/private/microcrystal_rv8263c8_types.h b/app/drivers/rtc/rv8263c8/private/microcrystal_rv8263c8_types.h new file mode 100644 index 00000000..660c5919 --- /dev/null +++ b/app/drivers/rtc/rv8263c8/private/microcrystal_rv8263c8_types.h @@ -0,0 +1,36 @@ +/* microcrystal_rv8263c8_types.h - Driver for Micro Crystal RV-8263-C8 RTC. */ + +/* + * Copyright (c 2024, Daniel Kampert + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct rv8263c8_config { + struct i2c_dt_spec i2c_bus; + rv_8263_c8_clkout_t clkout; + bool fast_mode; + int8_t offset; + struct gpio_dt_spec int_gpio; +}; + +struct rv8263c8_data { + struct k_spinlock lock; + bool alarm_pending; + rtc_alarm_callback cb; + void *cb_data; + rtc_update_callback update_cb; + void *update_cb_data; +}; \ No newline at end of file diff --git a/app/drivers/sensor/bmi270/Kconfig b/app/drivers/sensor/bmi270/Kconfig index ef546f0d..7c3fa5e4 100644 --- a/app/drivers/sensor/bmi270/Kconfig +++ b/app/drivers/sensor/bmi270/Kconfig @@ -27,25 +27,24 @@ if BMI270_PLUS prompt "BMI270 trigger mode" default BMI270_PLUS_TRIGGER_NONE - config BMI270_PLUS_TRIGGER_NONE - bool "No trigger" - help - Disable the trigger interface. - - config BMI270_PLUS_TRIGGER_GLOBAL_THREAD - depends on GPIO - select BMI270_PLUS_TRIGGER - bool "Use workqueue" - help - Use the global workqueue to process the interrupts from the BMI270. - - config BMI270_PLUS_TRIGGER_OWN_THREAD - depends on GPIO - select BMI270_PLUS_TRIGGER - bool "Use driver thread" - help - Use a separate thread to process the interrupts from the BMI270. - + config BMI270_PLUS_TRIGGER_NONE + bool "No trigger" + help + Disable the trigger interface. + + config BMI270_PLUS_TRIGGER_GLOBAL_THREAD + depends on GPIO + select BMI270_PLUS_TRIGGER + bool "Use workqueue" + help + Use the global workqueue to process the interrupts from the BMI270. + + config BMI270_PLUS_TRIGGER_OWN_THREAD + depends on GPIO + select BMI270_PLUS_TRIGGER + bool "Use driver thread" + help + Use a separate thread to process the interrupts from the BMI270. endchoice config BMI270_PLUS_TRIGGER diff --git a/app/drivers/sensor/bmi270/bosch_bmi270.c b/app/drivers/sensor/bmi270/bosch_bmi270.c index f72a3cdb..90d0707f 100644 --- a/app/drivers/sensor/bmi270/bosch_bmi270.c +++ b/app/drivers/sensor/bmi270/bosch_bmi270.c @@ -542,7 +542,7 @@ static int bmi270_pm_action(const struct device *p_dev, enum pm_device_action ac .swap_xy = DT_INST_PROP(inst, swap_xy), \ .invert_x = DT_INST_PROP(inst, invert_x), \ .invert_y = DT_INST_PROP(inst, invert_y), \ - .rotation = DT_INST_PROP(inst, rotation), \ + .rotation = DT_INST_PROP(inst, rotation), \ IF_ENABLED(CONFIG_BMI270_PLUS_TRIGGER, \ (.int_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, { 0 }),)) \ }; \ diff --git a/app/dts/bindings/rtc/microcrystal,rv-8263-c8.yml b/app/dts/bindings/rtc/microcrystal,rv-8263-c8.yml new file mode 100644 index 00000000..27d3b2d8 --- /dev/null +++ b/app/dts/bindings/rtc/microcrystal,rv-8263-c8.yml @@ -0,0 +1,39 @@ +description: | + The RV-8263-C8 is a CMOS real-time clock/calendar module optimized for low power consumption. An Offset + register makes it possible to compensate for the frequency deviation of the clock of 32.768 kHz + +compatible: "microcrystal,rv-8263-c8" + +include: [rtc-device.yaml, i2c-device.yaml] + +properties: + int-gpios: + type: phandle-array + required: false + + fast_mode: + type: boolean + description: | + Enable fast offset mode (Offset every 4 minutes). + + offset: + type: int + default: 0 + + description: + Offset for timer compensation. + + clkout: + type: int + default: 7 + enum: + - 0 + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + description: + CLKOUT frequency selection. Set to 7 to disable it. \ No newline at end of file diff --git a/app/dts/bindings/sensor/bosch,bmi270-plus.yml b/app/dts/bindings/sensor/bosch,bmi270-plus.yml index bf48212b..f4a49e82 100644 --- a/app/dts/bindings/sensor/bosch,bmi270-plus.yml +++ b/app/dts/bindings/sensor/bosch,bmi270-plus.yml @@ -25,6 +25,7 @@ properties: type: boolean description: | Invert the y axis. + rotation: type: int default: 0 diff --git a/app/prj.conf b/app/prj.conf index cecaecea..5d5b8cb3 100644 --- a/app/prj.conf +++ b/app/prj.conf @@ -180,7 +180,7 @@ CONFIG_WATCHFACE_BACKGROUND_NONE=n # Default watch CONFIG_POWER_MANAGEMENT_IDLE_TIMEOUT_SECONDS=20 -CONFIG_DEFAULT_CONFIGURATION_SENSORS_SUMMARY_REFRESH_INTERVAL_MS=100 +CONFIG_APPLICATIONS_CONFIGURATION_SENSORS_SUMMARY_REFRESH_INTERVAL_MS=100 # CST816S CONFIG_INPUT_CST816S_INTERRUPT=y diff --git a/app/src/applications/compass/compass_app.c b/app/src/applications/compass/compass_app.c index ffec4d1c..de12cfaf 100644 --- a/app/src/applications/compass/compass_app.c +++ b/app/src/applications/compass/compass_app.c @@ -35,7 +35,7 @@ static uint32_t cal_start_ms; static void compass_app_start(lv_obj_t *root, lv_group_t *group) { compass_ui_show(root, on_start_calibration); - refresh_timer = lv_timer_create(timer_callback, CONFIG_DEFAULT_CONFIGURATION_COMPASS_REFRESH_INTERVAL_MS, NULL); + refresh_timer = lv_timer_create(timer_callback, CONFIG_APPLICATIONS_CONFIGURATION_COMPASS_REFRESH_INTERVAL_MS, NULL); zsw_sensor_fusion_init(); } @@ -59,14 +59,14 @@ static void on_start_calibration(void) cal_start_ms = lv_tick_get(); zsw_popup_show("Calibration", "Rotate the watch 360 degrees\naround each x,y,z.\n a few times.", NULL, - CONFIG_DEFAULT_CONFIGURATION_COMPASS_CALIBRATION_TIME_S, false); + CONFIG_APPLICATIONS_CONFIGURATION_COMPASS_CALIBRATION_TIME_S, false); } static void timer_callback(lv_timer_t *timer) { float heading; if (is_calibrating && - (lv_tick_elaps(cal_start_ms) >= (CONFIG_DEFAULT_CONFIGURATION_COMPASS_CALIBRATION_TIME_S * 1000UL))) { + (lv_tick_elaps(cal_start_ms) >= (CONFIG_APPLICATIONS_CONFIGURATION_COMPASS_CALIBRATION_TIME_S * 1000UL))) { zsw_magnetometer_stop_calibration(); is_calibrating = false; zsw_popup_remove(); diff --git a/app/src/applications/sensors_summary/sensors_summary_app.c b/app/src/applications/sensors_summary/sensors_summary_app.c index 00c6c114..7b13ed2a 100644 --- a/app/src/applications/sensors_summary/sensors_summary_app.c +++ b/app/src/applications/sensors_summary/sensors_summary_app.c @@ -39,7 +39,7 @@ static void sensors_summary_app_start(lv_obj_t *root, lv_group_t *group) // Increase ODR since we want high accuracy here. zsw_pressure_sensor_set_odr(BOSCH_BMP581_ODR_160_HZ); - refresh_timer = lv_timer_create(timer_callback, CONFIG_DEFAULT_CONFIGURATION_SENSORS_SUMMARY_REFRESH_INTERVAL_MS, + refresh_timer = lv_timer_create(timer_callback, CONFIG_APPLICATIONS_CONFIGURATION_SENSORS_SUMMARY_REFRESH_INTERVAL_MS, NULL); } diff --git a/app/src/drivers/zsw_buzzer.c b/app/src/drivers/zsw_buzzer.c index f5fcc1d5..ed95e744 100644 --- a/app/src/drivers/zsw_buzzer.c +++ b/app/src/drivers/zsw_buzzer.c @@ -71,22 +71,6 @@ static void buzzer_off_work_handler(struct k_work *work); static void run_next_tone_state(note_duration_t *state); static void pattern_timer_timeout(struct k_timer *timer_id); -static struct note_duration_t funkytown_song[] = { - {.note = C5, .duration = quarter}, - {.note = REST, .duration = eigth}, - {.note = C5, .duration = quarter}, - {.note = Bb4, .duration = quarter}, - {.note = C5, .duration = quarter}, - {.note = REST, .duration = quarter}, - {.note = G4, .duration = quarter}, - {.note = REST, .duration = quarter}, - {.note = G4, .duration = quarter}, - {.note = C5, .duration = quarter}, - {.note = F5, .duration = quarter}, - {.note = E5, .duration = quarter}, - {.note = C5, .duration = quarter} -}; - static struct note_duration_t mario_song[] = { {.note = E6, .duration = quarter}, {.note = REST, .duration = eigth}, diff --git a/app/src/ui/watchfaces/0_digital/zsw_watchface_digital_ui.c b/app/src/ui/watchfaces/0_digital/zsw_watchface_digital_ui.c index ce084374..98f852bb 100644 --- a/app/src/ui/watchfaces/0_digital/zsw_watchface_digital_ui.c +++ b/app/src/ui/watchfaces/0_digital/zsw_watchface_digital_ui.c @@ -309,7 +309,7 @@ static void watchface_show(lv_obj_t *parent, watchface_app_evt_listener evt_cb, lv_obj_add_flag(ui_battery_arc, LV_OBJ_FLAG_EVENT_BUBBLE); lv_obj_clear_flag(ui_battery_arc, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | - LV_OBJ_FLAG_SCROLL_CHAIN); + LV_OBJ_FLAG_SCROLL_CHAIN | LV_OBJ_FLAG_CLICKABLE); lv_obj_set_style_arc_width(ui_battery_arc, 3, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_arc_color(ui_battery_arc, lv_color_hex(0xFFB140), LV_PART_INDICATOR | LV_STATE_DEFAULT); @@ -324,8 +324,9 @@ static void watchface_show(lv_obj_t *parent, watchface_app_evt_listener evt_cb, lv_obj_set_width(ui_battery_arc_icon, LV_SIZE_CONTENT); lv_obj_set_height(ui_battery_arc_icon, LV_SIZE_CONTENT); lv_obj_set_align(ui_battery_arc_icon, LV_ALIGN_CENTER); + lv_obj_add_flag(ui_battery_arc_icon, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_CLICK_FOCUSABLE); lv_obj_clear_flag(ui_battery_arc_icon, - LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | + LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN); lv_obj_set_style_img_recolor(ui_battery_arc_icon, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_img_recolor_opa(ui_battery_arc_icon, 255, LV_PART_MAIN | LV_STATE_DEFAULT); @@ -348,10 +349,9 @@ static void watchface_show(lv_obj_t *parent, watchface_app_evt_listener evt_cb, lv_obj_set_x(ui_step_arc, -52); lv_obj_set_y(ui_step_arc, 67); lv_obj_set_align(ui_step_arc, LV_ALIGN_CENTER); - lv_obj_add_flag(ui_step_arc, LV_OBJ_FLAG_EVENT_BUBBLE); lv_obj_clear_flag(ui_step_arc, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | - LV_OBJ_FLAG_SCROLL_CHAIN); + LV_OBJ_FLAG_SCROLL_CHAIN | LV_OBJ_FLAG_CLICKABLE); lv_obj_set_style_arc_width(ui_step_arc, 3, LV_PART_MAIN | LV_STATE_DEFAULT); lv_obj_set_style_arc_color(ui_step_arc, lv_color_hex(0x9D3BE0), LV_PART_INDICATOR | LV_STATE_DEFAULT); @@ -367,6 +367,7 @@ static void watchface_show(lv_obj_t *parent, watchface_app_evt_listener evt_cb, lv_obj_set_width(ui_step_arc_icon, LV_SIZE_CONTENT); lv_obj_set_height(ui_step_arc_icon, LV_SIZE_CONTENT); lv_obj_set_align(ui_step_arc_icon, LV_ALIGN_CENTER); + lv_obj_add_flag(ui_step_arc_icon, LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_CLICK_FOCUSABLE); lv_obj_clear_flag(ui_step_arc_icon, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM | LV_OBJ_FLAG_SCROLL_CHAIN); lv_obj_set_style_img_recolor(ui_step_arc_icon, lv_color_hex(0xFFFFFF), LV_PART_MAIN | LV_STATE_DEFAULT); @@ -465,8 +466,8 @@ static void watchface_show(lv_obj_t *parent, watchface_app_evt_listener evt_cb, #endif // Listeners - lv_obj_add_event_cb(ui_battery_arc, arc_event_pressed, LV_EVENT_CLICKED, NULL); - lv_obj_add_event_cb(ui_step_arc, arc_event_pressed, LV_EVENT_CLICKED, NULL); + lv_obj_add_event_cb(ui_battery_arc_icon, arc_event_pressed, LV_EVENT_CLICKED, NULL); + lv_obj_add_event_cb(ui_step_arc_icon, arc_event_pressed, LV_EVENT_CLICKED, NULL); } static void watchface_remove(void) @@ -645,10 +646,10 @@ static const void *watchface_get_preview_img(void) static void arc_event_pressed(lv_event_t *e) { watchface_app_evt_t evt = {.type = WATCHFACE_APP_EVENT_OPEN_APP}; - if (lv_event_get_target(e) == ui_battery_arc) { + if (lv_event_get_target(e) == ui_battery_arc_icon) { evt.data.app = WATCHFACE_APP_EVT_CLICK_BATT; ui_evt_cb(evt); - } else if (lv_event_get_target(e) == ui_step_arc) { + } else if (lv_event_get_target(e) == ui_step_arc_icon) { evt.data.app = WATCHFACE_APP_EVT_CLICK_STEP; ui_evt_cb(evt); }