use core::{marker::PhantomData, ops::Neg};
use ufmt::derive::uDebug;
extern "C" {
fn kernal_poly1(poly: *const u8);
fn kernal_poly2(poly: *const u8);
fn kernal_cos();
fn kernal_sin();
fn kernal_tan();
fn kernal_atn();
fn kernal_rdtim() -> u32;
}
pub const TRIG_CONSTANTS: *const TrigConstants = 0xe2e0 as *const _;
#[repr(C, packed)]
pub struct TrigConstants {
pub pi_over_2: F40,
pub pi_times_2: F40,
pub zero_point_2_5: F40,
pub sin_2_pi_x: Polynomial<OddTerms, 6>,
_atn_fn: [u8; 0x30],
pub atn: Polynomial<OddTerms, 12>,
}
#[derive(Clone, Copy, uDebug)]
#[repr(C, packed)]
pub struct F40 {
exp: u8,
sign_mantissa: [u8; 4],
}
impl F40 {
pub const fn zero() -> Self {
Self {
exp: 0,
sign_mantissa: [0; 4],
}
}
pub const fn one() -> Self {
Self {
exp: 0x81,
sign_mantissa: [0; 4],
}
}
}
impl Neg for F40 {
type Output = Self;
fn neg(mut self) -> Self::Output {
self.sign_mantissa[0] ^= 0b1000_0000;
self
}
}
#[derive(Clone, Copy)]
#[repr(C, packed)]
pub struct Polynomial<Terms, const N: usize> {
degree: u8,
coefficients: [F40; N],
_terms: PhantomData<Terms>,
}
pub struct AllTerms;
pub struct OddTerms;
impl<const N: usize> Polynomial<AllTerms, N> {
pub const fn new(coefficients: [F40; N]) -> Option<Self> {
match N.checked_sub(1) {
Some(degree @ 0..=255) => Some(Self {
degree: degree as u8,
coefficients,
_terms: PhantomData,
}),
_ => None,
}
}
#[inline]
pub unsafe fn poly(&self) {
unsafe { kernal_poly2(self as *const _ as _) }
}
}
impl<const N: usize> Polynomial<OddTerms, N> {
pub const fn with_odd_terms(coefficients: [F40; N]) -> Option<Self> {
match N.checked_sub(1) {
Some(degree @ 0..=255) => Some(Self {
degree: degree as u8,
coefficients,
_terms: PhantomData,
}),
_ => None,
}
}
#[inline]
pub unsafe fn poly(&self) {
unsafe { kernal_poly1(self as *const _ as _) }
}
}
#[inline]
pub unsafe fn cos() {
unsafe { kernal_cos() }
}
#[inline]
pub unsafe fn sin() {
unsafe { kernal_sin() }
}
#[inline]
pub unsafe fn tan() {
unsafe { kernal_tan() }
}
#[inline]
pub unsafe fn atn() {
unsafe { kernal_atn() }
}
#[inline]
pub unsafe fn rdtim() -> u32 {
unsafe { kernal_rdtim() }
}