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:
@@ -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,
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
@@ -42,6 +42,9 @@ typedef enum {
|
||||
// Comp
|
||||
FuriHalInterruptIdCOMP,
|
||||
|
||||
// RTC
|
||||
FuriHalInterruptIdRtcAlarm,
|
||||
|
||||
// HSEM
|
||||
FuriHalInterruptIdHsem,
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user