Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

目覚め時計 #3906

Merged
merged 22 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
93fe01b
FuriHal: add RTC alarm support
skotopes Sep 7, 2024
c51b70c
Merge remote-tracking branch 'origin/dev' into aku/rtc_alarms
skotopes Sep 7, 2024
a589750
Merge remote-tracking branch 'origin/dev' into aku/rtc_alarms
skotopes Sep 8, 2024
e95147a
Merge remote-tracking branch 'origin/dev' into aku/rtc_alarms
skotopes Sep 15, 2024
da02d99
FuriHal: RTC alarm API. Alarm settings app. Alarm app.
skotopes Sep 17, 2024
694a426
FuriHal: remove unnecessery init mode enters in RTC
skotopes Sep 18, 2024
057cfbd
Update targets/f7/furi_hal/furi_hal_rtc.h
skotopes Sep 20, 2024
11f854d
Update targets/f7/furi_hal/furi_hal_rtc.c
skotopes Sep 20, 2024
d4d6b3c
Update targets/f7/furi_hal/furi_hal_rtc.h
skotopes Sep 20, 2024
b0cf3df
Merge remote-tracking branch 'origin/dev' into aku/rtc_alarms
skotopes Oct 14, 2024
5f96678
FuriHal: add seconds in rtc alarm getter
skotopes Oct 15, 2024
3ed8c15
Merge remote-tracking branch 'origin/dev' into aku/rtc_alarms
skotopes Oct 20, 2024
ffaef5d
Merge remote-tracking branch 'origin/dev' into aku/rtc_alarms
skotopes Oct 20, 2024
c7e385e
Alarm & Clock: redesign and cleanup setting and alarm apps, cleanup API
skotopes Oct 20, 2024
9266d01
Spelling and time separator in alarm
skotopes Oct 20, 2024
f70ef53
Api Symbols: hide rtc alarm related methods
skotopes Oct 20, 2024
e582878
Clock alarm: new thread cleanup routine, hour/minute separator in alarm
skotopes Oct 21, 2024
a32f01d
Clock: move clock_settings_start into clock_settings fam
skotopes Oct 21, 2024
28cbbd1
Merge remote-tracking branch 'origin/dev' into aku/rtc_alarms
skotopes Oct 31, 2024
dbbee19
Seettings: update clock and alarm UI according to figma
skotopes Oct 31, 2024
aaf104b
Format icons
skotopes Oct 31, 2024
31c71b2
Merge branch 'dev' into aku/rtc_alarms
skotopes Oct 31, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions applications/services/notification/notification_messages.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,3 +593,7 @@ const NotificationSequence sequence_lcd_contrast_update = {
&message_lcd_contrast_update,
NULL,
};

const NotificationSequence sequence_empty = {
NULL,
};
3 changes: 3 additions & 0 deletions applications/services/notification/notification_messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ extern const NotificationSequence sequence_audiovisual_alert;
// LCD
extern const NotificationSequence sequence_lcd_contrast_update;

// Wait for notification queue become empty
extern const NotificationSequence sequence_empty;

#ifdef __cplusplus
}
#endif
1 change: 1 addition & 0 deletions applications/settings/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ App(
provides=[
"passport",
"system_settings",
"clock_settings",
"about",
],
)
17 changes: 17 additions & 0 deletions applications/settings/clock_settings/application.fam
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
App(
appid="clock_settings",
name="Clock & Alarm",
apptype=FlipperAppType.SETTINGS,
entry_point="clock_settings",
requires=["gui"],
provides=["clock_settings_start"],
stack_size=1 * 1024,
skotopes marked this conversation as resolved.
Show resolved Hide resolved
order=90,
)

App(
appid="clock_settings_start",
apptype=FlipperAppType.STARTUP,
entry_point="clock_settings_start",
order=1000,
)
71 changes: 71 additions & 0 deletions applications/settings/clock_settings/clock_settings.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#include "clock_settings.h"

#include <furi.h>
#include <furi_hal.h>

static bool clock_settings_custom_event_callback(void* context, uint32_t event) {
furi_assert(context);
ClockSettings* app = context;
return scene_manager_handle_custom_event(app->scene_manager, event);
}

static bool clock_settings_back_event_callback(void* context) {
furi_assert(context);
ClockSettings* app = context;
return scene_manager_handle_back_event(app->scene_manager);
}

ClockSettings* clock_settings_alloc() {
ClockSettings* app = malloc(sizeof(ClockSettings));

app->gui = furi_record_open(RECORD_GUI);

app->view_dispatcher = view_dispatcher_alloc();
app->scene_manager = scene_manager_alloc(&clock_settings_scene_handlers, app);
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);

view_dispatcher_set_custom_event_callback(
app->view_dispatcher, clock_settings_custom_event_callback);
view_dispatcher_set_navigation_event_callback(
app->view_dispatcher, clock_settings_back_event_callback);

view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);

app->pwm_view =
clock_settings_module_alloc(view_dispatcher_get_event_loop(app->view_dispatcher));
view_dispatcher_add_view(
app->view_dispatcher, ClockSettingsViewPwm, clock_settings_module_get_view(app->pwm_view));

scene_manager_next_scene(app->scene_manager, ClockSettingsSceneStart);

return app;
}

void clock_settings_free(ClockSettings* app) {
furi_assert(app);

// Views
view_dispatcher_remove_view(app->view_dispatcher, ClockSettingsViewPwm);

clock_settings_module_free(app->pwm_view);

// View dispatcher
view_dispatcher_free(app->view_dispatcher);
scene_manager_free(app->scene_manager);

// Close records
furi_record_close(RECORD_GUI);

free(app);
}

int32_t clock_settings(void* p) {
UNUSED(p);
ClockSettings* clock_settings = clock_settings_alloc();

view_dispatcher_run(clock_settings->view_dispatcher);

clock_settings_free(clock_settings);

return 0;
}
31 changes: 31 additions & 0 deletions applications/settings/clock_settings/clock_settings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include "scenes/clock_settings_scene.h"

#include <furi_hal_clock.h>
#include <furi_hal_pwm.h>

#include <gui/gui.h>
#include <gui/view_dispatcher.h>
#include <gui/scene_manager.h>
#include <gui/modules/submenu.h>
#include <gui/modules/variable_item_list.h>
#include <gui/modules/submenu.h>
#include "views/clock_settings_module.h"

typedef struct ClockSettings ClockSettings;

struct ClockSettings {
Gui* gui;
ViewDispatcher* view_dispatcher;
SceneManager* scene_manager;
ClockSettingsModule* pwm_view;
};

typedef enum {
ClockSettingsViewPwm,
} ClockSettingsView;

typedef enum {
ClockSettingsCustomEventNone,
} ClockSettingsCustomEvent;
177 changes: 177 additions & 0 deletions applications/settings/clock_settings/clock_settings_alarm.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#include <furi.h>
#include <furi_hal.h>

#include <gui/gui.h>
#include <gui/view_port.h>

#include <notification/notification.h>
#include <notification/notification_messages.h>

#include <assets_icons.h>

#define TAG "ClockSettingsAlarm"

typedef struct {
DateTime now;
IconAnimation* icon;
} ClockSettingsAlramModel;

const NotificationSequence sequence_alarm = {
&message_force_speaker_volume_setting_1f,
&message_force_vibro_setting_on,
&message_force_display_brightness_setting_1f,
&message_vibro_on,

&message_display_backlight_on,
&message_note_c7,
&message_delay_250,

&message_display_backlight_off,
&message_note_c4,
&message_delay_250,

&message_display_backlight_on,
&message_note_c7,
&message_delay_250,

&message_display_backlight_off,
&message_note_c4,
&message_delay_250,

&message_sound_off,
&message_vibro_off,
NULL,
};

static void clock_settings_alarm_draw_callback(Canvas* canvas, void* ctx) {
ClockSettingsAlramModel* model = ctx;
char buffer[64] = {};

canvas_draw_icon_animation(canvas, 5, 6, model->icon);

canvas_set_font(canvas, FontBigNumbers);
snprintf(buffer, sizeof(buffer), "%02u:%02u", model->now.hour, model->now.minute);
canvas_draw_str(canvas, 58, 32, buffer);

canvas_set_font(canvas, FontPrimary);
snprintf(
buffer,
sizeof(buffer),
"%02u.%02u.%04u",
model->now.day,
model->now.month,
model->now.year);
canvas_draw_str(canvas, 60, 44, buffer);
}

static void clock_settings_alarm_input_callback(InputEvent* input_event, void* ctx) {
furi_assert(ctx);
FuriMessageQueue* event_queue = ctx;
furi_message_queue_put(event_queue, input_event, FuriWaitForever);
}

void clock_settings_alarm_animation_callback(IconAnimation* instance, void* context) {
UNUSED(instance);
ViewPort* view_port = context;
view_port_update(view_port);
}

int32_t clock_settings_alarm(void* p) {
UNUSED(p);

// View Model
ClockSettingsAlramModel model;

furi_hal_rtc_get_datetime(&model.now);
model.icon = icon_animation_alloc(&A_Alarm_47x39);

// Alloc message queue
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));

// Configure view port
ViewPort* view_port = view_port_alloc();
view_port_draw_callback_set(view_port, clock_settings_alarm_draw_callback, &model);
view_port_input_callback_set(view_port, clock_settings_alarm_input_callback, event_queue);

// Register view port in GUI
Gui* gui = furi_record_open(RECORD_GUI);
gui_add_view_port(gui, view_port, GuiLayerFullscreen);

NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
notification_message(notification, &sequence_alarm);

icon_animation_set_update_callback(
model.icon, clock_settings_alarm_animation_callback, view_port);
icon_animation_start(model.icon);

// Process events
InputEvent event;
bool running = true;
while(running) {
if(furi_message_queue_get(event_queue, &event, 2000) == FuriStatusOk) {
if(event.type == InputTypePress) {
running = false;
}
} else {
notification_message(notification, &sequence_alarm);
furi_hal_rtc_get_datetime(&model.now);
view_port_update(view_port);
}
}

icon_animation_stop(model.icon);

notification_message_block(notification, &sequence_empty);
furi_record_close(RECORD_NOTIFICATION);

view_port_enabled_set(view_port, false);
gui_remove_view_port(gui, view_port);
view_port_free(view_port);
furi_message_queue_free(event_queue);
furi_record_close(RECORD_GUI);

icon_animation_free(model.icon);

return 0;
}

FuriThread* clock_settings_alarm_thread = NULL;

static void clock_settings_alarm_thread_state_callback(
FuriThread* thread,
FuriThreadState state,
void* context) {
furi_assert(clock_settings_alarm_thread == thread);
UNUSED(context);

if(state == FuriThreadStateStopped) {
furi_thread_free(thread);
clock_settings_alarm_thread = NULL;
}
}

static void clock_settings_alarm_start(void* context, uint32_t arg) {
UNUSED(context);
UNUSED(arg);

FURI_LOG_I(TAG, "spawning alarm thread");

if(clock_settings_alarm_thread) return;

clock_settings_alarm_thread =
furi_thread_alloc_ex("ClockAlarm", 1024, clock_settings_alarm, NULL);
furi_thread_set_state_callback(
clock_settings_alarm_thread, clock_settings_alarm_thread_state_callback);
furi_thread_start(clock_settings_alarm_thread);
}

static void clock_settings_alarm_isr(void* context) {
UNUSED(context);
furi_timer_pending_callback(clock_settings_alarm_start, NULL, 0);
}

void clock_settings_start(void) {
#ifndef FURI_RAM_EXEC
furi_hal_rtc_set_alarm_callback(clock_settings_alarm_isr, NULL);
#endif
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "../clock_settings.h"

// Generate scene on_enter handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
void (*const clock_settings_scene_on_enter_handlers[])(void*) = {
#include "clock_settings_scene_config.h"
};
#undef ADD_SCENE

// Generate scene on_event handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
bool (*const clock_settings_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
#include "clock_settings_scene_config.h"
};
#undef ADD_SCENE

// Generate scene on_exit handlers array
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
void (*const clock_settings_scene_on_exit_handlers[])(void* context) = {
#include "clock_settings_scene_config.h"
};
#undef ADD_SCENE

// Initialize scene handlers configuration structure
const SceneManagerHandlers clock_settings_scene_handlers = {
.on_enter_handlers = clock_settings_scene_on_enter_handlers,
.on_event_handlers = clock_settings_scene_on_event_handlers,
.on_exit_handlers = clock_settings_scene_on_exit_handlers,
.scene_num = ClockSettingsSceneNum,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#pragma once

#include <gui/scene_manager.h>

// Generate scene id and total number
#define ADD_SCENE(prefix, name, id) ClockSettingsScene##id,
typedef enum {
#include "clock_settings_scene_config.h"
ClockSettingsSceneNum,
} ClockSettingsScene;
#undef ADD_SCENE

extern const SceneManagerHandlers clock_settings_scene_handlers;

// Generate scene on_enter handlers declaration
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
#include "clock_settings_scene_config.h"
#undef ADD_SCENE

// Generate scene on_event handlers declaration
#define ADD_SCENE(prefix, name, id) \
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
#include "clock_settings_scene_config.h"
#undef ADD_SCENE

// Generate scene on_exit handlers declaration
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
#include "clock_settings_scene_config.h"
#undef ADD_SCENE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ADD_SCENE(clock_settings, start, Start)
Loading
Loading