#![no_implicit_prelude]
extern crate core;
extern crate rpsp;
use core::cmp::{Ord, PartialEq};
use core::convert::From;
use core::marker::Send;
use core::mem::MaybeUninit;
use core::ops::Deref;
use core::option::Option::{self};
use core::ptr::NonNull;
use core::result::Result::{self, Ok};
use rpsp::atomic::{Mutex, with};
use rpsp::clock::{AlarmConfig, RtcError};
use rpsp::i2c::I2cController;
use rpsp::pin::gpio::Output;
use rpsp::pin::{Pin, PinID};
use rpsp::spi::{Spi, SpiConfig, SpiDev, SpiFormat, SpiPhase, SpiPolarity};
use rpsp::time::Time;
use rpsp::{Board, static_instance};
use crate::frame::ShiftRegister;
use crate::fs::Storage;
use crate::hw::{Buttons, ButtonsPtr, Leds, LedsPtr, WakeReason};
use crate::pcf::PcfRtc;
use crate::sd::Card;
#[cfg_attr(rustfmt, rustfmt_skip)]
pub use rpsp::{pin, pwm, sleep, sleep_us, ticks, ticks_ms};
const PFC_RTC_HZ: u32 = 400_000u32;
static_instance!(INSTANCE, MaybeUninit<Inner>, Inner::new());
pub struct InkyBoard<'a> {
i: NonNull<Inner<'a>>,
p: Board,
}
struct Inner<'a> {
pwr: Pin<Output>,
rtc: PcfRtc<'a>,
spi: Option<Spi>,
leds: Leds,
wake: WakeReason,
buttons: Buttons,
}
impl<'a> Inner<'a> {
#[inline]
const fn new() -> MaybeUninit<Inner<'a>> {
MaybeUninit::zeroed()
}
#[inline]
fn is_ready(&self) -> bool {
PinID::Pin0.ne(self.pwr.id())
}
#[inline]
fn setup(&mut self, p: &Board) {
self.pwr = Pin::get(&p, PinID::Pin2).output_high();
let s = ShiftRegister::new(&p, PinID::Pin8, PinID::Pin9, PinID::Pin10);
let w = s.read();
self.wake = WakeReason::from(w);
self.buttons = Buttons::new(w, s);
self.rtc = PcfRtc::new(unsafe { I2cController::new(&p, PinID::Pin4, PinID::Pin5, PFC_RTC_HZ).unwrap_unchecked() });
let _ = self.rtc.alarm_clear_state();
let _ = self.rtc.alarm_disable();
let _ = self.rtc.set_timer_interrupt(false, false);
self.leds = Leds::new(p);
}
}
impl<'a> InkyBoard<'a> {
#[inline]
pub fn get() -> InkyBoard<'a> {
let p = Board::get();
InkyBoard {
i: with(|x| {
let f = unsafe { &mut *INSTANCE.borrow_mut(x).assume_init_mut() };
if !f.is_ready() {
f.setup(&p);
}
unsafe { NonNull::new_unchecked(f) }
}),
p,
}
}
#[inline]
pub fn leds(&self) -> &Leds {
&self.ptr().leds
}
#[inline]
pub fn spi_bus(&self) -> &Spi {
self.ptr().spi.get_or_insert_with(|| unsafe {
Spi::new(
&self.p,
SpiConfig::DEFAULT_BAUD_RATE,
SpiConfig::new()
.bits(8)
.format(SpiFormat::Motorola)
.phase(SpiPhase::First)
.polarity(SpiPolarity::Low)
.primary(true),
SpiDev::new_rx(PinID::Pin19, PinID::Pin18, PinID::Pin16).unwrap_unchecked(),
)
.unwrap_unchecked()
})
}
#[inline]
pub fn sync_pcf_to_rtc(&self) {
let _ = self.p.rtc().set_time_from(self.pcf());
}
#[inline]
pub fn sync_rtc_to_pcf(&self) {
let _ = self.pcf().set_time_from(self.p.rtc());
}
#[inline]
pub fn pcf(&self) -> &mut PcfRtc<'a> {
&mut self.ptr().rtc
}
#[inline]
pub fn buttons(&self) -> &mut Buttons {
&mut self.ptr().buttons
}
#[inline]
pub fn set_rtc_and_pcf(&self, v: Time) {
let _ = self.p.rtc().set_time(v);
let _ = self.pcf().set_time(v);
}
#[inline]
pub fn wake_reason(&self) -> WakeReason {
self.ptr().wake
}
#[inline]
pub fn i2c_bus(&self) -> &I2cController {
self.ptr().rtc.i2c_bus()
}
#[inline]
pub fn sd_card(&self) -> Storage<Card<'_>> {
Storage::new(Card::new(&self.p, PinID::Pin22, self.spi_bus()))
}
#[inline]
pub fn shift_register(&self) -> &ShiftRegister {
self.ptr().buttons.shift_register()
}
pub fn set_rtc_wake(&self, secs: u32) -> Result<u32, RtcError> {
let d = self.pcf();
let mut v = d.now()?.add_seconds((secs as i64).min(0x24EA00));
if v.secs >= 55 && v.mins <= 58 {
(v.secs, v.mins) = (5, v.mins + 1);
}
let _ = d.alarm_clear_state()?;
let _ = d.set_alarm(
AlarmConfig::new()
.month(v.month)
.day(v.day)
.hours(v.hours)
.mins(v.mins)
.secs(v.secs),
)?;
let _ = d.set_alarm_interrupt(true)?;
Ok(secs.saturating_mul(1_000))
}
#[inline]
pub unsafe fn power_off(&self) {
self.ptr().pwr.low();
self.sleep(1_500);
}
#[inline]
pub unsafe fn deep_sleep(&self, secs: u32) -> Result<(), RtcError> {
let v = self.set_rtc_wake(secs)?;
unsafe { self.power_off() };
self.p.sleep(v);
let d: &mut PcfRtc<'_> = self.pcf();
let _ = d.alarm_clear_state();
let _ = d.alarm_disable();
let _ = d.set_timer_interrupt(false, false);
Ok(())
}
#[inline]
fn ptr(&self) -> &mut Inner<'a> {
unsafe { &mut *self.i.as_ptr() }
}
}
impl Deref for InkyBoard<'_> {
type Target = Board;
#[inline]
fn deref(&self) -> &Board {
&self.p
}
}
unsafe impl Send for Inner<'_> {}
#[inline]
pub fn leds() -> LedsPtr {
LedsPtr::new(&mut InkyBoard::get().ptr().leds)
}
#[inline]
pub fn buttons() -> ButtonsPtr {
ButtonsPtr::new(InkyBoard::get().buttons())
}