pub struct Mdec(/* private fields */);Expand description
The MDEC’s driver: it owns the two DMA channels that feed and drain it, so every decode step that starts one is a method here and the borrow checker sees a second decoder.
A decode frame is: reset and
load_tables once, then per frame
decode with a closure that pulls the output columns.
The status register stays a free function (status): reading it
cannot disturb a transfer, so it needs no owner.
Implementations§
Source§impl Mdec
impl Mdec
Sourcepub const fn new(dma: MdecDma) -> Self
pub const fn new(dma: MdecDma) -> Self
Take the MDEC’s DMA channels. Touches no register: call
reset next.
Sourcepub fn reset(&mut self) -> bool
pub fn reset(&mut self) -> bool
Reset the MDEC, wait for the reset to finish, then enable its DMA
requests on both channels. false if the MDEC stayed busy after the
reset (the enable is still written).
Sourcepub fn load_tables(&mut self) -> Option<Tables>
pub fn load_tables(&mut self) -> Option<Tables>
Upload the standard quantization tables and the IDCT basis. None if
the MDEC would take them neither over DMA0 nor over the CPU.
Sourcepub fn load_tables_cpu(&mut self) -> bool
pub fn load_tables_cpu(&mut self) -> bool
Upload both tables over CPU writes to MDEC0 only, after
reset. No DMA involved: the control path for a console
whose DMA0 will not feed the MDEC. false if the input FIFO never made
room.
Sourcepub fn write_command(&mut self, word: u32)
pub fn write_command(&mut self, word: u32)
Write one word to MDEC0: a command, or a parameter the CPU feeds itself.
Sourcepub fn read_data(&mut self) -> u32
pub fn read_data(&mut self) -> u32
Read one word of decoded output from MDEC0 (the CPU path; DMA1 is the usual one). Garbage when the output FIFO is empty.
Sourcepub unsafe fn decode_start(
&mut self,
rle: &[u32],
words: usize,
mode: u32,
) -> Result<(), RleLengthError>
pub unsafe fn decode_start( &mut self, rle: &[u32], words: usize, mode: u32, ) -> Result<(), RleLengthError>
Start decoding words 32-bit words of run-length data (a multiple of 32,
as crate::bitstream::decode_frame returns). mode is
[psx_hw::mdec::DECODE_15BPP] or [psx_hw::mdec::DECODE_24BPP],
optionally with [psx_hw::mdec::DECODE_STP].
decode is the safe form: it holds the borrow of rle
until DMA0 is done with it.
§Errors
RleLengthError when words is 0, not a multiple of 32, longer than
the decode command can announce (crate::rle::MAX_WORDS) or longer
than rle. Nothing is written to the MDEC then and no DMA starts.
§Safety
On Ok, DMA0 keeps reading rle after this returns. The caller must
keep rle alive and unmodified until decode_finish
returns, and must call it before the storage is reused or freed.
Sourcepub fn decode<R>(
&mut self,
rle: &[u32],
mode: u32,
columns: impl FnOnce(&mut Self) -> R,
) -> Result<(R, bool), RleLengthError>
pub fn decode<R>( &mut self, rle: &[u32], mode: u32, columns: impl FnOnce(&mut Self) -> R, ) -> Result<(R, bool), RleLengthError>
Decode all of rle (a multiple of 32 words, as
crate::bitstream::decode_frame returns) with DMA0 feeding the MDEC,
the safe form of decode_start.
columns runs while DMA0 feeds the MDEC and pulls the output, normally
with read_column once per column; it gets the
driver back for that. Returns its result and
decode_finish’s: false there means DMA0 was
still busy and has been aborted.
§Errors
RleLengthError when rle is empty, not a whole number of 32-word
blocks or longer than crate::rle::MAX_WORDS; columns does not run.
Sourcepub unsafe fn read_column_start(&mut self, dst: *mut u32, words: usize) -> bool
pub unsafe fn read_column_start(&mut self, dst: *mut u32, words: usize) -> bool
Start pulling the next words words (a multiple of 32) of decoded
pixels over DMA1 into dst and return at once;
column_done says when they are in. The MDEC
decodes only while DMA1 drains its output, so a player that overlaps
work with the decode kicks the next column as soon as the last one
lands.
Only whole 32-word blocks move. Returns false, having started
nothing, when that is no block at all or more than one transfer can
count: the controller reads a zero block count as 65,536 blocks, which
would run far past dst.
§Safety
dst must point at words writable words that stay alive and
untouched until column_done returns true or
DMA1 is aborted (abort_decode).
Sourcepub fn column_done(&self) -> bool
pub fn column_done(&self) -> bool
True once the column read_column_start
asked for has arrived.
Sourcepub fn abort_decode(&mut self)
pub fn abort_decode(&mut self)
Stop both MDEC DMA channels, e.g. when a decode has taken too long. A column or run-length buffer a transfer was using is free again once this returns.
Sourcepub fn read_column(&mut self, dst: &mut [u32]) -> bool
pub fn read_column(&mut self, dst: &mut [u32]) -> bool
Pull the next dst.len() words (a multiple of 32) of decoded pixels
over DMA1 and wait for them. For 15bpp one 16-pixel-wide column of
height h is 8 * h words. false if DMA1 wedged.
Sourcepub fn decode_finish(&mut self) -> bool
pub fn decode_finish(&mut self) -> bool
Confirm DMA0 finished feeding the frame. false (after aborting the
channel) if it is still busy, e.g. the frame held more data than was
read back.