use core::{
cmp::Ordering,
ffi::CStr,
marker::PhantomData,
ops::{AddAssign, Neg},
};
use crate::{
hal::{basic::BasicRom, kernal::KernalRom, Basic, Kernal},
pac::{
basic,
kernal::{self, F40},
peripheral,
},
};
pub struct FAC<'a, HIRAM, LORAM> {
_fac: peripheral::FAC,
_cur: PhantomData<&'a (HIRAM, LORAM)>,
}
impl<'a> FAC<'a, Kernal, Basic> {
pub fn with_basic<CHAREN>(fac: peripheral::FAC, basic: &'a BasicRom<'_, CHAREN>) -> Self {
let _ = basic;
Self {
_fac: fac,
_cur: PhantomData,
}
}
}
impl<'a, LORAM> FAC<'a, Kernal, LORAM> {
pub fn with_kernal<CHAREN>(
fac: peripheral::FAC,
kernal: &'a KernalRom<'_, LORAM, CHAREN>,
) -> Self {
let _ = kernal;
Self {
_fac: fac,
_cur: PhantomData,
}
}
}
impl<'a> FAC<'a, Kernal, Basic> {
pub fn load(&mut self, value: &F40) {
unsafe { basic::movfm(value) };
}
pub fn read(&mut self) -> F40 {
let mut ret = F40::zero();
unsafe { basic::movmf(&mut ret) };
ret
}
pub fn load_i16(&mut self, value: i16) {
unsafe { basic::givayf(value) }
}
pub fn to_i16(&mut self) -> i16 {
unsafe { basic::facinx() }
}
pub fn load_from_arg(&mut self, arg: &ARG) {
let _ = arg;
unsafe { basic::movaf() };
}
pub fn copy_to_arg(&mut self, arg: &mut ARG) {
let _ = arg;
unsafe { basic::movfa() };
}
pub fn to_cstr<'s>(&mut self, fpstr: &'s mut FPSTR) -> &'s CStr {
let _ = fpstr;
let val = self.read();
let ptr = unsafe { basic::fout() };
self.load(&val);
unsafe { CStr::from_ptr(ptr) }
}
pub fn into_cstr<'s>(&mut self, fpstr: &'s mut FPSTR) -> &'s CStr {
let _ = fpstr;
let ptr = unsafe { basic::fout() };
self.load_i16(0);
unsafe { CStr::from_ptr(ptr) }
}
}
impl<'a, LORAM> FAC<'a, Kernal, LORAM> {
pub fn cos(&mut self) {
unsafe { kernal::cos() }
}
pub fn sin(&mut self) {
unsafe { kernal::sin() }
}
pub fn tan(&mut self) {
unsafe { kernal::tan() }
}
pub fn arctan(&mut self) {
unsafe { kernal::atn() }
}
pub fn poly1<const N: usize>(&mut self, poly: &kernal::Polynomial<kernal::OddTerms, N>) {
unsafe { poly.poly() };
}
pub fn poly2<const N: usize>(&mut self, poly: &kernal::Polynomial<kernal::AllTerms, N>) {
unsafe { poly.poly() };
}
}
impl<'a> PartialEq<F40> for FAC<'a, Kernal, Basic> {
fn eq(&self, other: &F40) -> bool {
matches!(self.partial_cmp(other), Some(Ordering::Equal))
}
}
impl<'a> PartialOrd<F40> for FAC<'a, Kernal, Basic> {
fn partial_cmp(&self, other: &F40) -> Option<Ordering> {
Some(unsafe { basic::fcomp(other) })
}
}
impl<'a> Neg for FAC<'a, Kernal, Basic> {
type Output = Self;
fn neg(self) -> Self::Output {
unsafe { basic::negop() };
self
}
}
impl<'a> AddAssign<&F40> for FAC<'a, Kernal, Basic> {
fn add_assign(&mut self, rhs: &F40) {
unsafe { basic::fadd(rhs) }
}
}
impl<'a> AddAssign<&ARG> for FAC<'a, Kernal, Basic> {
fn add_assign(&mut self, rhs: &ARG) {
let _ = rhs;
unsafe { basic::faddt() }
}
}
pub struct ARG {
_arg: peripheral::ARG,
}
impl ARG {
pub fn new(arg: peripheral::ARG) -> Self {
Self { _arg: arg }
}
}
pub struct FPSTR {
_fpstr: peripheral::FPSTR,
}
impl FPSTR {
pub fn new(fpstr: peripheral::FPSTR) -> Self {
Self { _fpstr: fpstr }
}
}