#![cfg_attr(target_arch = "arm", no_std)]
#![feature(slice_from_ptr_range)]
#![warn(missing_docs)]
#![doc = include_str!("../README.md")]
extern crate alloc;
mod ffi;
pub mod midi_message;
#[cfg(feature = "fastmaths")]
pub mod fastmaths;
pub mod fft;
pub mod interpolation;
pub mod program_vector;
pub mod sample_buffer;
pub mod screen_buffer;
pub mod volts_per_octave;
pub use ffi::openware_midi_control::{
OpenWareMidiControl, OpenWareMidiSysexCommand, PatchButtonId, PatchParameterId,
};
pub mod resource;
#[cfg(not(target_arch = "arm"))]
#[doc(hidden)]
pub mod test_harness;
#[cfg(target_arch = "arm")]
use cfg_if::cfg_if;
use ffi::program_vector::ProgramVector as FfiProgramVector;
use core::{
ffi::{c_char, c_void},
mem::MaybeUninit,
};
pub use owl_patch_macros::patch;
#[cfg(target_arch = "arm")]
#[panic_handler]
unsafe fn panic_handler(info: &core::panic::PanicInfo) -> ! {
match info.message().as_str() {
Some(m) => program_vector::error(&m),
None => program_vector::error(&alloc::format!("{}", info.message())),
}
}
#[doc(hidden)]
#[repr(C)]
pub struct ProgramHeader {
magic_word: u32,
start_prog: *const c_void,
endprog: *const c_void,
reset_handler: unsafe extern "C" fn(),
stack: *const c_void,
estack: *const c_void,
programvector: *const MaybeUninit<FfiProgramVector>,
patch_name: [u8; 24],
}
unsafe impl Sync for ProgramHeader {}
impl ProgramHeader {
const MAGIC_WORD: u32 = 0xdadac0de;
pub const fn new(
patch_name: &str,
programvector: *const MaybeUninit<FfiProgramVector>,
) -> Self {
extern "C" {
static mut _startprog: c_void;
static mut _endprog: c_void;
static mut _stack: c_void;
static mut _estack: c_void;
}
let mut name_bytes = [0u8; 24];
let p = patch_name.as_bytes();
let len = if p.len() < name_bytes.len() {
p.len()
} else {
name_bytes.len()
};
let mut n = 0;
while n < len {
name_bytes[n] = p[n];
n += 1;
}
ProgramHeader {
magic_word: Self::MAGIC_WORD,
start_prog: &raw const _startprog,
endprog: &raw const _endprog,
reset_handler,
stack: &raw const _stack,
estack: &raw const _estack,
programvector,
patch_name: name_bytes,
}
}
pub fn patch_name(&self) -> *const c_char {
self.patch_name.as_ptr() as *const c_char
}
}
#[cfg(target_arch = "arm")]
#[link_section = ".text.Reset_Handler"]
unsafe extern "C" fn reset_handler() {
extern "C" {
static mut _sidata: u32;
static mut _sdata: u32;
static mut _edata: u32;
static mut _sbss: u32;
static mut _ebss: u32;
}
extern "Rust" {
fn __main() -> !;
}
cfg_if! {
if #[cfg(feature = "stack_hack")] {
core::arch::asm!("ldr sp, =_estack");
}
}
if &raw mut _sdata < &raw mut _edata {
let data = core::slice::from_ptr_range(&raw mut _sdata..&raw mut _edata);
let idata = core::slice::from_raw_parts_mut(&raw mut _sidata, data.len());
idata.copy_from_slice(data);
}
if &raw mut _sbss < &raw mut _ebss {
let bss = core::slice::from_mut_ptr_range(&raw mut _sbss..&raw mut _ebss);
bss.fill(0);
}
#[cfg(feature = "fastmaths")]
crate::ffi::fastmaths::set_default_tables();
__main()
}
#[cfg(not(target_arch = "arm"))]
unsafe extern "C" fn reset_handler() {}