#![no_std] #![feature(trace_macros)] #![feature(concat_idents)] #![feature(proc_macro_hygiene)] #![feature(exclusive_range_pattern)]
extern crate macros as mynewt_macros;
pub use lvgl;
use core::{
ptr,
};
use lvgl::mynewt::{
fill_zero,
kernel::os,
result::*,
sys::console,
Strn,
};
use lvgl::{
core::{
disp,
obj
},
};
pub trait WatchFace {
fn new() -> MynewtResult<Self>
where Self: core::marker::Sized;
fn update(&mut self, state: &WatchFaceState) -> MynewtResult<()>;
}
pub fn start_watch_face(update_watch_face: UpdateWatchFace) -> MynewtResult<()> {
console::print("Init Rust watch face...\n"); console::flush();
unsafe { UPDATE_WATCH_FACE = Some(update_watch_face); }
let screen = get_active_screen();
obj::set_click(screen, true) ? ;
unsafe { os::os_callout_init(
&mut WATCH_FACE_CALLOUT, os::eventq_dflt_get().unwrap(), Some(watch_face_callback), ptr::null_mut() );
}
let rc = unsafe { os::os_callout_reset(
&mut WATCH_FACE_CALLOUT, os::OS_TICKS_PER_SEC * 0 )
};
assert!(rc == 0, "Timer fail");
Ok(())
}
extern fn watch_face_callback(_ev: *mut os::os_event) {
console::print("Update Rust watch face...\n"); console::flush();
assert!(unsafe { UPDATE_WATCH_FACE.is_some() }, "Update watch face missing");
let time = get_system_time()
.expect("Can't get system time");
let state = WatchFaceState {
time,
millivolts: 0, charging: true, powered: true, bluetooth: BluetoothState::BLUETOOTH_STATE_CONNECTED, };
unsafe { UPDATE_WATCH_FACE.unwrap()(&state)
.expect("Update Watch Face fail");
}
let rc = unsafe { pinetime_lvgl_mynewt_render() };
assert!(rc == 0, "LVGL render fail");
let rc = unsafe { os::os_callout_reset(
&mut WATCH_FACE_CALLOUT, os::OS_TICKS_PER_SEC * 60 )
};
assert!(rc == 0, "Timer fail");
}
pub fn get_active_screen() -> lvgl::Ptr {
let screen = disp::get_scr_act(
disp::get_default()
.expect("Failed to get display")
).expect("Failed to get active display");
assert!(!screen.is_null(), "null screen");
screen
}
static mut WATCH_FACE_CALLOUT: os::os_callout = fill_zero!(os::os_callout);
static mut UPDATE_WATCH_FACE: Option<UpdateWatchFace> = None;
type UpdateWatchFace = fn (state: &WatchFaceState) -> MynewtResult<()>;
fn get_system_time() -> MynewtResult<WatchFaceTime> {
static mut TV: os::os_timeval = fill_zero!(os::os_timeval);
static mut TZ: os::os_timezone = fill_zero!(os::os_timezone);
let rc = unsafe { os::os_gettimeofday(&mut TV, &mut TZ) };
assert!(rc == 0, "Can't get time");
static mut CT: clocktime = fill_zero!(clocktime);
let rc = unsafe { timeval_to_clocktime(&TV, &TZ, &mut CT) };
assert!(rc == 0, "Can't convert time");
let result = unsafe { WatchFaceTime {
year: CT.year as u16, month: CT.mon as u8, day: CT.day as u8, hour: CT.hour as u8, minute: CT.min as u8, second: CT.sec as u8, day_of_week: CT.dow as u8, }
};
Ok(result)
}
pub const fn new_string() -> String {
heapless::String(heapless::i::String::new())
}
pub fn to_strn(str: &String) -> Strn {
Strn::new(str.as_bytes())
}
pub type String = heapless::String::<heapless::consts::U64>;
#[repr(C)] pub struct WatchFaceState {
pub time: WatchFaceTime,
pub bluetooth: BluetoothState,
pub millivolts: u32,
pub charging: bool,
pub powered: bool,
}
#[repr(C)] pub struct WatchFaceTime {
pub year: u16,
pub month: u8,
pub day: u8,
pub hour: u8,
pub minute: u8,
pub second: u8,
pub day_of_week: u8,
}
#[repr(u8)] #[derive(PartialEq)] #[allow(dead_code)] #[allow(non_camel_case_types)]
pub enum BluetoothState {
BLUETOOTH_STATE_INACTIVE = 0,
BLUETOOTH_STATE_ADVERTISING = 1,
BLUETOOTH_STATE_DISCONNECTED = 2,
BLUETOOTH_STATE_CONNECTED = 3,
}
extern {
fn pinetime_lvgl_mynewt_render() -> i32;
fn timeval_to_clocktime(tv: *const os::os_timeval, tz: *const os::os_timezone, ct: *mut clocktime) -> i32;
}
#[repr(C)] struct clocktime {
year: i32, mon: i32, day: i32, hour: i32, min: i32, sec: i32, dow: i32, usec: i32, }