-
Notifications
You must be signed in to change notification settings - Fork 36
/
example_images.rs
101 lines (82 loc) · 3.35 KB
/
example_images.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
//! Example Images application.
//! See https://github.com/flipperdevices/flipperzero-firmware/blob/dev/applications/examples/example_images/example_images.c
#![no_std]
#![no_main]
use core::ffi::{c_char, c_void};
use core::mem::{self, MaybeUninit};
use flipperzero_rt as rt;
use flipperzero_sys as sys;
rt::manifest!(name = "Example: Images");
rt::entry!(main);
const RECORD_GUI: *const c_char = sys::c_string!("gui");
static mut TARGET_ICON: Icon = Icon {
width: 48,
height: 32,
frame_count: 1,
frame_rate: 0,
frames: unsafe { TARGET_FRAMES.as_ptr() },
};
static mut TARGET_FRAMES: [*const u8; 1] = [ include_bytes!("icons/rustacean-48x32.icon").as_ptr() ];
static mut IMAGE_POSITION: ImagePosition = ImagePosition { x: 0, y: 0 };
#[repr(C)]
struct ImagePosition {
pub x: u8,
pub y: u8,
}
/// Internal icon representation.
#[repr(C)]
struct Icon {
width: u8,
height: u8,
frame_count: u8,
frame_rate: u8,
frames: *const *const u8,
}
// Screen is 128x64 px
extern "C" fn app_draw_callback(canvas: *mut sys::Canvas, _ctx: *mut c_void) {
unsafe {
sys::canvas_clear(canvas);
sys::canvas_draw_icon(canvas, IMAGE_POSITION.x % 128, IMAGE_POSITION.y % 128, &TARGET_ICON as *const Icon as *const c_void as *const sys::Icon);
}
}
extern "C" fn app_input_callback(input_event: *mut sys::InputEvent, ctx: *mut c_void) {
unsafe {
let event_queue = ctx as *mut sys::FuriMessageQueue;
sys::furi_message_queue_put(event_queue, input_event as *mut c_void, 0);
}
}
fn main(_args: *mut u8) -> i32 {
unsafe {
let event_queue = sys::furi_message_queue_alloc(8, mem::size_of::<sys::InputEvent>() as u32) as *mut sys::FuriMessageQueue;
// Configure view port
let view_port = sys::view_port_alloc();
sys::view_port_draw_callback_set(view_port, Some(app_draw_callback), view_port as *mut c_void);
sys::view_port_input_callback_set(view_port, Some(app_input_callback), event_queue as *mut c_void);
// Register view port in GUI
let gui = sys::furi_record_open(RECORD_GUI) as *mut sys::Gui;
sys::gui_add_view_port(gui, view_port, sys::GuiLayer_GuiLayerFullscreen);
let mut event: MaybeUninit<sys::InputEvent> = MaybeUninit::uninit();
let mut running = true;
while running {
if sys::furi_message_queue_get(event_queue, event.as_mut_ptr() as *mut sys::InputEvent as *mut c_void, 100) == sys::FuriStatus_FuriStatusOk {
let event = event.assume_init();
if event.type_ == sys::InputType_InputTypePress || event.type_ == sys::InputType_InputTypeRepeat {
match event.key {
sys::InputKey_InputKeyLeft => IMAGE_POSITION.x -= 2,
sys::InputKey_InputKeyRight => IMAGE_POSITION.x += 2,
sys::InputKey_InputKeyUp => IMAGE_POSITION.y -= 2,
sys::InputKey_InputKeyDown => IMAGE_POSITION.y += 2,
_ => running = false,
}
}
}
sys::view_port_update(view_port);
}
sys::view_port_enabled_set(view_port, false);
sys::gui_remove_view_port(gui, view_port);
sys::view_port_free(view_port);
sys::furi_message_queue_free(event_queue);
sys::furi_record_close(RECORD_GUI);
}
0
}