1
mirror of https://github.com/flipperdevices/flipperzero-firmware.git synced 2025-12-12 04:41:26 +04:00

目覚め時計 (#3906)

* FuriHal: add RTC alarm support

* FuriHal: RTC alarm API. Alarm settings app. Alarm app.

* FuriHal: remove unnecessery init mode enters in RTC

* Update targets/f7/furi_hal/furi_hal_rtc.h

Co-authored-by: Silent <CookiePLMonster@users.noreply.github.com>

* Update targets/f7/furi_hal/furi_hal_rtc.c

Co-authored-by: Silent <CookiePLMonster@users.noreply.github.com>

* Update targets/f7/furi_hal/furi_hal_rtc.h

Co-authored-by: Silent <CookiePLMonster@users.noreply.github.com>

* FuriHal: add seconds in rtc alarm getter

* Alarm & Clock: redesign and cleanup setting and alarm apps, cleanup API

* Spelling and time separator in alarm

* Api Symbols: hide rtc alarm related methods

* Clock alarm: new thread cleanup routine, hour/minute separator in alarm

* Clock: move clock_settings_start into clock_settings fam

* Seettings: update clock and alarm UI according to figma

* Format icons

---------

Co-authored-by: Silent <CookiePLMonster@users.noreply.github.com>
This commit is contained in:
あく
2024-10-31 20:42:03 +09:00
committed by GitHub
parent 4b8a1a4b11
commit 561b4e947a
28 changed files with 1068 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,78.0,,
Version,+,78.1,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
@@ -1566,6 +1566,7 @@ Function,+,furi_hal_rfid_tim_read_pause,void,
Function,+,furi_hal_rfid_tim_read_start,void,"float, float"
Function,+,furi_hal_rfid_tim_read_stop,void,
Function,-,furi_hal_rtc_deinit_early,void,
Function,-,furi_hal_rtc_get_alarm,_Bool,DateTime*
Function,+,furi_hal_rtc_get_boot_mode,FuriHalRtcBootMode,
Function,+,furi_hal_rtc_get_datetime,void,DateTime*
Function,+,furi_hal_rtc_get_fault_data,uint32_t,
@@ -1583,8 +1584,11 @@ Function,+,furi_hal_rtc_get_timestamp,uint32_t,
Function,-,furi_hal_rtc_init,void,
Function,-,furi_hal_rtc_init_early,void,
Function,+,furi_hal_rtc_is_flag_set,_Bool,FuriHalRtcFlag
Function,-,furi_hal_rtc_prepare_for_shutdown,void,
Function,+,furi_hal_rtc_reset_flag,void,FuriHalRtcFlag
Function,+,furi_hal_rtc_reset_registers,void,
Function,-,furi_hal_rtc_set_alarm,void,"const DateTime*, _Bool"
Function,-,furi_hal_rtc_set_alarm_callback,void,"FuriHalRtcAlarmCallback, void*"
Function,+,furi_hal_rtc_set_boot_mode,void,FuriHalRtcBootMode
Function,+,furi_hal_rtc_set_datetime,void,DateTime*
Function,+,furi_hal_rtc_set_fault_data,void,uint32_t
@@ -3974,6 +3978,7 @@ Variable,+,sequence_display_backlight_off,const NotificationSequence,
Variable,+,sequence_display_backlight_off_delay_1000,const NotificationSequence,
Variable,+,sequence_display_backlight_on,const NotificationSequence,
Variable,+,sequence_double_vibro,const NotificationSequence,
Variable,+,sequence_empty,const NotificationSequence,
Variable,+,sequence_error,const NotificationSequence,
Variable,+,sequence_lcd_contrast_update,const NotificationSequence,
Variable,+,sequence_not_charging,const NotificationSequence,
1 entry status name type params
2 Version + 78.0 78.1
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/bt/bt_service/bt_keys_storage.h
1566 Function + furi_hal_rfid_tim_read_start void float, float
1567 Function + furi_hal_rfid_tim_read_stop void
1568 Function - furi_hal_rtc_deinit_early void
1569 Function - furi_hal_rtc_get_alarm _Bool DateTime*
1570 Function + furi_hal_rtc_get_boot_mode FuriHalRtcBootMode
1571 Function + furi_hal_rtc_get_datetime void DateTime*
1572 Function + furi_hal_rtc_get_fault_data uint32_t
1584 Function - furi_hal_rtc_init void
1585 Function - furi_hal_rtc_init_early void
1586 Function + furi_hal_rtc_is_flag_set _Bool FuriHalRtcFlag
1587 Function - furi_hal_rtc_prepare_for_shutdown void
1588 Function + furi_hal_rtc_reset_flag void FuriHalRtcFlag
1589 Function + furi_hal_rtc_reset_registers void
1590 Function - furi_hal_rtc_set_alarm void const DateTime*, _Bool
1591 Function - furi_hal_rtc_set_alarm_callback void FuriHalRtcAlarmCallback, void*
1592 Function + furi_hal_rtc_set_boot_mode void FuriHalRtcBootMode
1593 Function + furi_hal_rtc_set_datetime void DateTime*
1594 Function + furi_hal_rtc_set_fault_data void uint32_t
3978 Variable + sequence_display_backlight_off_delay_1000 const NotificationSequence
3979 Variable + sequence_display_backlight_on const NotificationSequence
3980 Variable + sequence_double_vibro const NotificationSequence
3981 Variable + sequence_empty const NotificationSequence
3982 Variable + sequence_error const NotificationSequence
3983 Variable + sequence_lcd_contrast_update const NotificationSequence
3984 Variable + sequence_not_charging const NotificationSequence

View File

@@ -68,6 +68,9 @@ const IRQn_Type furi_hal_interrupt_irqn[FuriHalInterruptIdMax] = {
// COMP
[FuriHalInterruptIdCOMP] = COMP_IRQn,
// RTC
[FuriHalInterruptIdRtcAlarm] = RTC_Alarm_IRQn,
// HSEM
[FuriHalInterruptIdHsem] = HSEM_IRQn,
@@ -256,6 +259,10 @@ void DMA2_Channel7_IRQHandler(void) {
furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch7);
}
void RTC_Alarm_IRQHandler(void) {
furi_hal_interrupt_call(FuriHalInterruptIdRtcAlarm);
}
void HSEM_IRQHandler(void) {
furi_hal_interrupt_call(FuriHalInterruptIdHsem);
}

View File

@@ -42,6 +42,9 @@ typedef enum {
// Comp
FuriHalInterruptIdCOMP,
// RTC
FuriHalInterruptIdRtcAlarm,
// HSEM
FuriHalInterruptIdHsem,

View File

@@ -326,6 +326,7 @@ void furi_hal_power_shutdown(void) {
void furi_hal_power_off(void) {
// Crutch: shutting down with ext 3V3 off is causing LSE to stop
furi_hal_rtc_prepare_for_shutdown();
furi_hal_power_enable_external_3_3v();
furi_hal_vibro_on(true);
furi_delay_us(50000);

View File

@@ -1,3 +1,4 @@
#include <furi_hal_interrupt.h>
#include <furi_hal_rtc.h>
#include <furi_hal_light.h>
#include <furi_hal_debug.h>
@@ -42,6 +43,13 @@ typedef struct {
_Static_assert(sizeof(SystemReg) == 4, "SystemReg size mismatch");
typedef struct {
FuriHalRtcAlarmCallback alarm_callback;
void* alarm_callback_context;
} FuriHalRtc;
static FuriHalRtc furi_hal_rtc = {};
static const FuriHalSerialId furi_hal_rtc_log_devices[] = {
[FuriHalRtcLogDeviceUsart] = FuriHalSerialIdUsart,
[FuriHalRtcLogDeviceLpuart] = FuriHalSerialIdLpuart,
@@ -60,6 +68,17 @@ static const uint32_t furi_hal_rtc_log_baud_rates[] = {
[FuriHalRtcLogBaudRate1843200] = 1843200,
};
static void furi_hal_rtc_enter_init_mode(void) {
LL_RTC_EnableInitMode(RTC);
while(LL_RTC_IsActiveFlag_INIT(RTC) != 1)
;
}
static void furi_hal_rtc_exit_init_mode(void) {
LL_RTC_DisableInitMode(RTC);
furi_hal_rtc_sync_shadow();
}
static void furi_hal_rtc_reset(void) {
LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
@@ -127,6 +146,36 @@ static void furi_hal_rtc_recover(void) {
}
}
static void furi_hal_rtc_alarm_handler(void* context) {
UNUSED(context);
if(LL_RTC_IsActiveFlag_ALRA(RTC) != 0) {
/* Clear the Alarm interrupt pending bit */
LL_RTC_ClearFlag_ALRA(RTC);
/* Alarm callback */
furi_check(furi_hal_rtc.alarm_callback);
furi_hal_rtc.alarm_callback(furi_hal_rtc.alarm_callback_context);
}
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_17);
}
static void furi_hal_rtc_set_alarm_out(bool enable) {
FURI_CRITICAL_ENTER();
LL_RTC_DisableWriteProtection(RTC);
if(enable) {
LL_RTC_SetAlarmOutEvent(RTC, LL_RTC_ALARMOUT_ALMA);
LL_RTC_SetOutputPolarity(RTC, LL_RTC_OUTPUTPOLARITY_PIN_LOW);
LL_RTC_SetAlarmOutputType(RTC, LL_RTC_ALARM_OUTPUTTYPE_OPENDRAIN);
} else {
LL_RTC_SetAlarmOutEvent(RTC, LL_RTC_ALARMOUT_DISABLE);
LL_RTC_SetOutputPolarity(RTC, LL_RTC_OUTPUTPOLARITY_PIN_LOW);
LL_RTC_SetAlarmOutputType(RTC, LL_RTC_ALARM_OUTPUTTYPE_OPENDRAIN);
}
LL_RTC_EnableWriteProtection(RTC);
FURI_CRITICAL_EXIT();
}
void furi_hal_rtc_init_early(void) {
// Enable RTCAPB clock
LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
@@ -167,6 +216,11 @@ void furi_hal_rtc_init(void) {
furi_hal_rtc_log_baud_rates[furi_hal_rtc_get_log_baud_rate()]);
FURI_LOG_I(TAG, "Init OK");
furi_hal_rtc_set_alarm_out(false);
}
void furi_hal_rtc_prepare_for_shutdown(void) {
furi_hal_rtc_set_alarm_out(true);
}
void furi_hal_rtc_sync_shadow(void) {
@@ -347,9 +401,7 @@ void furi_hal_rtc_set_datetime(DateTime* datetime) {
LL_RTC_DisableWriteProtection(RTC);
/* Enter Initialization mode and wait for INIT flag to be set */
LL_RTC_EnableInitMode(RTC);
while(!LL_RTC_IsActiveFlag_INIT(RTC)) {
}
furi_hal_rtc_enter_init_mode();
/* Set time */
LL_RTC_TIME_Config(
@@ -368,9 +420,7 @@ void furi_hal_rtc_set_datetime(DateTime* datetime) {
__LL_RTC_CONVERT_BIN2BCD(datetime->year - 2000));
/* Exit Initialization mode */
LL_RTC_DisableInitMode(RTC);
furi_hal_rtc_sync_shadow();
furi_hal_rtc_exit_init_mode();
/* Enable write protection */
LL_RTC_EnableWriteProtection(RTC);
@@ -395,6 +445,82 @@ void furi_hal_rtc_get_datetime(DateTime* datetime) {
datetime->weekday = __LL_RTC_CONVERT_BCD2BIN((date >> 24) & 0xFF);
}
void furi_hal_rtc_set_alarm(const DateTime* datetime, bool enabled) {
furi_check(!FURI_IS_IRQ_MODE());
FURI_CRITICAL_ENTER();
LL_RTC_DisableWriteProtection(RTC);
if(datetime) {
LL_RTC_ALMA_ConfigTime(
RTC,
LL_RTC_ALMA_TIME_FORMAT_AM,
__LL_RTC_CONVERT_BIN2BCD(datetime->hour),
__LL_RTC_CONVERT_BIN2BCD(datetime->minute),
__LL_RTC_CONVERT_BIN2BCD(datetime->second));
LL_RTC_ALMA_SetMask(RTC, LL_RTC_ALMA_MASK_DATEWEEKDAY);
}
if(enabled) {
LL_RTC_ClearFlag_ALRA(RTC);
LL_RTC_ALMA_Enable(RTC);
} else {
LL_RTC_ALMA_Disable(RTC);
LL_RTC_ClearFlag_ALRA(RTC);
}
LL_RTC_EnableWriteProtection(RTC);
FURI_CRITICAL_EXIT();
}
bool furi_hal_rtc_get_alarm(DateTime* datetime) {
furi_check(datetime);
memset(datetime, 0, sizeof(DateTime));
datetime->hour = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_ALMA_GetHour(RTC));
datetime->minute = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_ALMA_GetMinute(RTC));
datetime->second = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_ALMA_GetSecond(RTC));
return READ_BIT(RTC->CR, RTC_CR_ALRAE);
}
void furi_hal_rtc_set_alarm_callback(FuriHalRtcAlarmCallback callback, void* context) {
FURI_CRITICAL_ENTER();
LL_RTC_DisableWriteProtection(RTC);
if(callback) {
furi_check(!furi_hal_rtc.alarm_callback);
// Set our callbacks
furi_hal_rtc.alarm_callback = callback;
furi_hal_rtc.alarm_callback_context = context;
// Enable RTC ISR
furi_hal_interrupt_set_isr(FuriHalInterruptIdRtcAlarm, furi_hal_rtc_alarm_handler, NULL);
// Hello EXTI my old friend
// Chain: RTC->LINE-17->EXTI->NVIC->FuriHalInterruptIdRtcAlarm
LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_17);
LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_17);
// Enable alarm interrupt
LL_RTC_EnableIT_ALRA(RTC);
// Force trigger
furi_hal_rtc_alarm_handler(NULL);
} else {
furi_check(furi_hal_rtc.alarm_callback);
// Cleanup EXTI flags and config
LL_EXTI_DisableIT_0_31(LL_EXTI_LINE_17);
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_17);
LL_EXTI_DisableRisingTrig_0_31(LL_EXTI_LINE_17);
// Cleanup NVIC flags and config
furi_hal_interrupt_set_isr(FuriHalInterruptIdRtcAlarm, NULL, NULL);
// Disable alarm interrupt
LL_RTC_DisableIT_ALRA(RTC);
furi_hal_rtc.alarm_callback = NULL;
furi_hal_rtc.alarm_callback_context = NULL;
}
LL_RTC_EnableWriteProtection(RTC);
FURI_CRITICAL_EXIT();
}
void furi_hal_rtc_set_fault_data(uint32_t value) {
furi_hal_rtc_set_register(FuriHalRtcRegisterFaultData, value);
}

View File

@@ -98,6 +98,14 @@ void furi_hal_rtc_deinit_early(void);
/** Initialize RTC subsystem */
void furi_hal_rtc_init(void);
/** Prepare system for shutdown
*
* This function must be called before system sent to transport mode(power off).
* FlipperZero implementation configures and enables ALARM output on pin PC13
* (Back button). This allows the system to wake-up charger from transport mode.
*/
void furi_hal_rtc_prepare_for_shutdown(void);
/** Force sync shadow registers */
void furi_hal_rtc_sync_shadow(void);
@@ -247,6 +255,38 @@ void furi_hal_rtc_set_datetime(DateTime* datetime);
*/
void furi_hal_rtc_get_datetime(DateTime* datetime);
/** Set alarm
*
* @param[in] datetime The date time to set or NULL if time change is not needed
* @param[in] enabled Indicates if alarm must be enabled or disabled
*/
void furi_hal_rtc_set_alarm(const DateTime* datetime, bool enabled);
/** Get alarm
*
* @param datetime Pointer to DateTime object
*
* @return true if alarm was set, false otherwise
*/
bool furi_hal_rtc_get_alarm(DateTime* datetime);
/** Furi HAL RTC alarm callback signature */
typedef void (*FuriHalRtcAlarmCallback)(void* context);
/** Set alarm callback
*
* Use it to subscribe to alarm trigger event. Setting alarm callback is
* independent from setting alarm.
*
* @warning Normally this callback will be delivered from the ISR, however we may
* deliver it while this function is called. This happens when
* the alarm has already triggered, but there was no ISR set.
*
* @param[in] callback The callback
* @param context The context
*/
void furi_hal_rtc_set_alarm_callback(FuriHalRtcAlarmCallback callback, void* context);
/** Set RTC Fault Data
*
* @param[in] value The value