use ufmt::{uDisplay, uwrite};
use crate::{
hal::{AddressSpace, Io, Kernal},
pac::kernal,
};
pub struct KernalRom<'a, LORAM, CHAREN> {
_asp: &'a AddressSpace<Kernal, LORAM, CHAREN>,
}
impl<'a, LORAM, CHAREN> KernalRom<'a, LORAM, CHAREN> {
pub fn new(asp: &'a AddressSpace<Kernal, LORAM, CHAREN>) -> Self {
Self { _asp: asp }
}
pub fn trig_constants(&self) -> &kernal::TrigConstants {
unsafe { &*kernal::TRIG_CONSTANTS }
}
pub fn write_petscii(&self, byte: u8) {
unsafe { kernal::chrout(byte) }
}
pub fn set_reverse_mode(&self, on: bool) {
self.write_petscii(if on { 0x12 } else { 0x92 });
}
pub fn set_system_clock(&self, jiffies: Jiffies) {
unsafe { kernal::settim(jiffies.as_u32()) }
}
pub fn read_system_clock(&self) -> Jiffies {
Jiffies(unsafe { kernal::rdtim() })
}
pub fn screen_size(&self) -> ScreenSize {
let (cols, rows) = unsafe { kernal::screen() };
ScreenSize { cols, rows }
}
pub fn cursor_position(&self) -> CursorPos {
let (row, col) = unsafe { kernal::plot_get() };
CursorPos { row, col }
}
pub fn set_cursor_position(&self, row: u8, col: u8) {
unsafe { kernal::plot_set(row, col) };
}
}
impl<'a, LORAM> KernalRom<'a, LORAM, Io> {
pub fn set_character_set(&self, set: CharacterSet) {
self.write_petscii(match set {
CharacterSet::UppercaseGraphics => 0x8E,
CharacterSet::LowercaseUppercase => 0x0E,
});
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CharacterSet {
UppercaseGraphics,
LowercaseUppercase,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct Jiffies(u32);
impl uDisplay for Jiffies {
fn fmt<W>(&self, f: &mut ufmt::Formatter<'_, W>) -> Result<(), W::Error>
where
W: ufmt::uWrite + ?Sized,
{
const JIFFIES_PER_SECOND: u32 = 60;
const JIFFIES_PER_MINUTE: u32 = JIFFIES_PER_SECOND * 60;
const JIFFIES_PER_HOUR: u32 = JIFFIES_PER_MINUTE * 60;
let hours = self.0 / JIFFIES_PER_HOUR;
let rest = self.0 - (hours * JIFFIES_PER_HOUR);
let mins = rest / JIFFIES_PER_MINUTE;
let rest = rest - (mins * JIFFIES_PER_MINUTE);
let secs = rest / JIFFIES_PER_SECOND;
let jiffies = rest - (secs * JIFFIES_PER_SECOND);
uwrite!(f, "{}:{}:{}.{}", hours, mins, secs, jiffies)
}
}
impl Jiffies {
const STORE_MODULUS: u32 = 0x0100_0000;
const CLOCK_MODULUS: u32 = 24 * 60 * 60 * 60;
pub const fn new(value: u32) -> Option<Self> {
if value < Self::STORE_MODULUS {
Some(Self(value))
} else {
None
}
}
pub const fn wrapping_new(value: u32) -> Self {
Self(value % Self::CLOCK_MODULUS)
}
pub const fn as_u32(self) -> u32 {
self.0
}
}
pub struct ScreenSize {
pub cols: u8,
pub rows: u8,
}
pub struct CursorPos {
pub row: u8,
pub col: u8,
}