arctan and arctan2

This commit is contained in:
Lokathor 2022-10-22 22:23:42 -06:00
parent 2ecf62e06e
commit e38ddee38b
3 changed files with 77 additions and 1 deletions

View file

@ -3,6 +3,12 @@
* **0.9.2:**
* Adds support for more BIOS functions, though not all functions are as
clearly documented as I'd like.
* Made much more of the `Fixed` type const friendly. Most ops now have an
inherent method that is `const fn` as well as implementing the `core::ops`
trait (the trait fn just calls the inherent fn). This means that you can't
do `x + y` in a const context, but you can do `x.add(y)`. This is not the
best system, but until const trait impls are stable this is the best middle
ground.
* **0.9.1:**
* Adds some randomization support directly into the crate.
* Added more methods to the `Fixed` type.

View file

@ -8,11 +8,31 @@
//! of the function ends up inlined). Despite this higher cost, some bios
//! functions are useful enough to justify the overhead.
use crate::interrupts::IrqBits;
use crate::{fixed::i16fx14, interrupts::IrqBits};
// Note(Lokathor): All `swi` calls will preserve the flags. You should generally
// not use any other inline-asm options with `swi` calls.
/// `0x00`: Software Reset.
///
/// This clears the BIOS portion of IWRAM (the top `0x200` bytes), resets the
/// SVC, IRQ, and SYS stack pointers to their defaults, then performs a `bx r14`
/// to go to an address based on what's written to the byte at `0x0300_7FFA`:
/// * zero: `0x0800_0000` (ROM)
/// * non-zero: `0x0200_0000` (IWRAM).
///
/// (Note: the target address is determined *before* clearing the top of IWRAM.)
#[inline]
#[instruction_set(arm::t32)]
pub fn SoftReset() -> ! {
unsafe {
core::arch::asm! {
"swi #0x00",
options(noreturn),
}
};
}
/// `0x04`: Waits for a specific interrupt type(s) to happen.
///
/// Pauses the CPU until any of the interrupt types set in `target_irqs` to
@ -62,6 +82,50 @@ pub fn VBlankIntrWait() {
};
}
/// `0x09`: Arc tangent.
///
/// * **Returns:** The output is in the range +/- `pi/2`, but accuracy is worse
/// outside of +/- `pi/4`.
#[inline]
#[instruction_set(arm::t32)]
pub fn ArcTan(theta: i16fx14) -> i16fx14 {
let mut i = theta.into_raw();
unsafe {
core::arch::asm! {
"swi #0x09",
inout("r0") i,
out("r1") _,
out("r3") _,
options(pure, nomem, preserves_flags),
}
};
i16fx14::from_raw(i)
}
/// `0x0A`: The "2-argument arctangent" ([atan2][wp-atan2]).
///
/// [wp-atan2]: https://en.wikipedia.org/wiki/Atan2
///
/// * **Returns:** The angle of the input vector, with `u16::MAX` being
/// equivalent to `2pi`.
#[inline]
#[instruction_set(arm::t32)]
pub fn ArcTan2(x: i16fx14, y: i16fx14) -> u16 {
let x = x.into_raw();
let y = y.into_raw();
let output: u16;
unsafe {
core::arch::asm! {
"swi #0x0A",
inout("r0") x => output,
inout("r1") y => _,
out("r3") _,
options(pure, nomem, preserves_flags),
}
};
output
}
/// Used to provide info to a call of the [`BitUnPack`] function.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(C)]

View file

@ -6,6 +6,12 @@ use core::ops::*;
#[allow(non_camel_case_types)]
pub type i16fx8 = Fixed<i16, 8>;
/// `i16` with 14 bits of fixed-point fraction.
///
/// This is used by the [`ArcTan`] and [`ArcTan2`] BIOS functions.
#[allow(non_camel_case_types)]
pub type i16fx14 = Fixed<i16, 14>;
/// `i32` with 8 bits of fixed-point fraction.
///
/// This is used by the background reference point entries.