cbc8871a0b
this removed the RelocatedProgram construction step from pio uses. there's not all that much to be said for the extra step because the origin can be set on the input program itself, and the remaining information exposed by RelocatedProgram can be exposed from LoadedProgram instead (even though it's already available on the pio_asm programs, albeit perhaps less convenient). we do lose access to the relocated instruction iterator, but we also cannot think of anything this iterator would actually be useful for outside of program loading.
68 lines
1.8 KiB
Rust
68 lines
1.8 KiB
Rust
use core::iter::Iterator;
|
|
|
|
use pio::{Program, SideSet, Wrap};
|
|
|
|
pub struct CodeIterator<'a, I>
|
|
where
|
|
I: Iterator<Item = &'a u16>,
|
|
{
|
|
iter: I,
|
|
offset: u8,
|
|
}
|
|
|
|
impl<'a, I: Iterator<Item = &'a u16>> CodeIterator<'a, I> {
|
|
pub fn new(iter: I, offset: u8) -> CodeIterator<'a, I> {
|
|
CodeIterator { iter, offset }
|
|
}
|
|
}
|
|
|
|
impl<'a, I> Iterator for CodeIterator<'a, I>
|
|
where
|
|
I: Iterator<Item = &'a u16>,
|
|
{
|
|
type Item = u16;
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
self.iter.next().and_then(|&instr| {
|
|
Some(if instr & 0b1110_0000_0000_0000 == 0 {
|
|
// this is a JMP instruction -> add offset to address
|
|
let address = (instr & 0b1_1111) as u8;
|
|
let address = address.wrapping_add(self.offset) % 32;
|
|
instr & (!0b11111) | address as u16
|
|
} else {
|
|
instr
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
pub struct RelocatedProgram<'a, const PROGRAM_SIZE: usize> {
|
|
program: &'a Program<PROGRAM_SIZE>,
|
|
origin: u8,
|
|
}
|
|
|
|
impl<'a, const PROGRAM_SIZE: usize> RelocatedProgram<'a, PROGRAM_SIZE> {
|
|
pub fn new_with_origin(program: &Program<PROGRAM_SIZE>, origin: u8) -> RelocatedProgram<PROGRAM_SIZE> {
|
|
RelocatedProgram { program, origin }
|
|
}
|
|
|
|
pub fn code(&'a self) -> CodeIterator<'a, core::slice::Iter<'a, u16>> {
|
|
CodeIterator::new(self.program.code.iter(), self.origin)
|
|
}
|
|
|
|
pub fn wrap(&self) -> Wrap {
|
|
let wrap = self.program.wrap;
|
|
let origin = self.origin;
|
|
Wrap {
|
|
source: wrap.source.wrapping_add(origin) % 32,
|
|
target: wrap.target.wrapping_add(origin) % 32,
|
|
}
|
|
}
|
|
|
|
pub fn side_set(&self) -> SideSet {
|
|
self.program.side_set
|
|
}
|
|
|
|
pub fn origin(&self) -> u8 {
|
|
self.origin
|
|
}
|
|
}
|