Bounce buffers with a static image working
This commit is contained in:
parent
7e1f0d1b68
commit
04f4070634
|
|
@ -149,8 +149,11 @@ async fn test_bounce_buffers(
|
||||||
st7701s: St7701s<'static, Blocking>,
|
st7701s: St7701s<'static, Blocking>,
|
||||||
) -> DpiTransfer<'static, DmaTxBounceBuf, Blocking> {
|
) -> DpiTransfer<'static, DmaTxBounceBuf, Blocking> {
|
||||||
error!("TEST BOUNCE BUFFERS SECTION ENTERED");
|
error!("TEST BOUNCE BUFFERS SECTION ENTERED");
|
||||||
let windows_len = 960;
|
const WIDTH: usize = 368;
|
||||||
let window_size = 8 * 368 * core::mem::size_of::<u16>();
|
const HEIGHT: usize = 960;
|
||||||
|
const ROWS_PER_WINDOW: usize = 8;
|
||||||
|
let windows_len = HEIGHT / ROWS_PER_WINDOW;
|
||||||
|
let window_size = ROWS_PER_WINDOW * WIDTH * core::mem::size_of::<u16>();
|
||||||
let buffer_src = Box::leak(allocate_dma_buffer_in(
|
let buffer_src = Box::leak(allocate_dma_buffer_in(
|
||||||
windows_len * window_size,
|
windows_len * window_size,
|
||||||
&PSRAM_ALLOCATOR,
|
&PSRAM_ALLOCATOR,
|
||||||
|
|
@ -158,7 +161,19 @@ async fn test_bounce_buffers(
|
||||||
let buffer_src = bytemuck::cast_slice_mut::<u8, Rgb565Pixel>(buffer_src);
|
let buffer_src = bytemuck::cast_slice_mut::<u8, Rgb565Pixel>(buffer_src);
|
||||||
let colors = (0..120_u8)
|
let colors = (0..120_u8)
|
||||||
.rev()
|
.rev()
|
||||||
.map(|val| Rgb565Pixel::from_rgb(val * 2, val * 2, val * 2))
|
.map(|val| {
|
||||||
|
// Rgb565Pixel::from_rgb(
|
||||||
|
// (val % 2) * (0b11111 / (2 - 1)),
|
||||||
|
// (val % 8) * (0b111111 / (8 - 1)),
|
||||||
|
// (val % 32) * (0b11111 / (32 - 1)),
|
||||||
|
// )
|
||||||
|
// Rgb565Pixel::from_rgb(
|
||||||
|
// (0b11111 as f32 * (val as f32 / 119.0)) as u8,
|
||||||
|
// (0b111111 as f32 * (val as f32 / 119.0)) as u8,
|
||||||
|
// (0b11111 as f32 * (val as f32 / 119.0)) as u8,
|
||||||
|
// )
|
||||||
|
Rgb565Pixel::from_rgb(0xFF, val * 2, 0)
|
||||||
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
for (index, pixel) in buffer_src.iter_mut().enumerate() {
|
for (index, pixel) in buffer_src.iter_mut().enumerate() {
|
||||||
let mut x = (index % 368) as i16 - 120;
|
let mut x = (index % 368) as i16 - 120;
|
||||||
|
|
@ -191,6 +206,7 @@ async fn test_bounce_buffers(
|
||||||
internal_memory: InternalBurstConfig::Enabled,
|
internal_memory: InternalBurstConfig::Enabled,
|
||||||
external_memory: ExternalBurstConfig::Size32,
|
external_memory: ExternalBurstConfig::Size32,
|
||||||
},
|
},
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
let _ = buf.send().await;
|
let _ = buf.send().await;
|
||||||
error!("TEST BOUNCE BUFFERS SECTION DONE");
|
error!("TEST BOUNCE BUFFERS SECTION DONE");
|
||||||
|
|
|
||||||
|
|
@ -1273,7 +1273,10 @@ where
|
||||||
// - prevent flash from being used whilst your program is running. (There's a PR to make
|
// - prevent flash from being used whilst your program is running. (There's a PR to make
|
||||||
// this easy to do)
|
// this easy to do)
|
||||||
// https://github.com/esp-rs/esp-hal/pull/3024
|
// https://github.com/esp-rs/esp-hal/pull/3024
|
||||||
.with_frequency(Rate::from_mhz(11)) // From Adafruit
|
//
|
||||||
|
// Adafruit would use 11 MHz.
|
||||||
|
// I had lowered the frequency, so that `DmaBounce` could keep up.
|
||||||
|
.with_frequency(Rate::from_mhz(8)) // From Adafruit
|
||||||
.with_clock_mode(ClockMode {
|
.with_clock_mode(ClockMode {
|
||||||
polarity: Polarity::IdleLow, // From Adafruit
|
polarity: Polarity::IdleLow, // From Adafruit
|
||||||
phase: Phase::ShiftHigh, // From Adafruit
|
phase: Phase::ShiftHigh, // From Adafruit
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ use embassy_sync::{
|
||||||
channel::{Channel, TrySendError},
|
channel::{Channel, TrySendError},
|
||||||
signal::Signal,
|
signal::Signal,
|
||||||
};
|
};
|
||||||
use embassy_time::Timer;
|
use embassy_time::{Instant, Timer};
|
||||||
use esp_alloc::MemoryCapability;
|
use esp_alloc::MemoryCapability;
|
||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
Blocking,
|
Blocking,
|
||||||
|
|
@ -38,7 +38,10 @@ use rmk::{
|
||||||
join_all,
|
join_all,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{PSRAM_ALLOCATOR, SIGNAL_LCD_SUBMIT, SIGNAL_UI_RENDER, peripherals::st7701s::St7701s};
|
use crate::{
|
||||||
|
PSRAM_ALLOCATOR, SIGNAL_LCD_SUBMIT, SIGNAL_UI_RENDER, peripherals::st7701s::St7701s,
|
||||||
|
util::DurationExt,
|
||||||
|
};
|
||||||
|
|
||||||
/// THIS IS TAKEN FROM https://github.com/esp-rs/esp-hal/blob/main/esp-hal/src/soc/esp32s3/mod.rs
|
/// THIS IS TAKEN FROM https://github.com/esp-rs/esp-hal/blob/main/esp-hal/src/soc/esp32s3/mod.rs
|
||||||
/// Write back a specific range of data in the cache.
|
/// Write back a specific range of data in the cache.
|
||||||
|
|
@ -82,7 +85,7 @@ pub struct DmaBounce {
|
||||||
|
|
||||||
// TODO: Consider having a separate burst config for the two transfers.
|
// TODO: Consider having a separate burst config for the two transfers.
|
||||||
burst_config: BurstConfig,
|
burst_config: BurstConfig,
|
||||||
// rx: DmaRxStreamBuf,
|
cyclic: bool,
|
||||||
/// The size of each window.
|
/// The size of each window.
|
||||||
window_size: usize,
|
window_size: usize,
|
||||||
/// The number of windows.
|
/// The number of windows.
|
||||||
|
|
@ -113,6 +116,7 @@ impl DmaBounce {
|
||||||
buffer_src: &'static mut [u8],
|
buffer_src: &'static mut [u8],
|
||||||
window_size: usize,
|
window_size: usize,
|
||||||
burst_config: BurstConfig,
|
burst_config: BurstConfig,
|
||||||
|
cyclic: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer_src.len() % window_size,
|
buffer_src.len() % window_size,
|
||||||
|
|
@ -120,6 +124,7 @@ impl DmaBounce {
|
||||||
"the size of a source buffer must be a multiple of the window size ({window_size} bytes), but it is {len} bytes large",
|
"the size of a source buffer must be a multiple of the window size ({window_size} bytes), but it is {len} bytes large",
|
||||||
len = buffer_src.len()
|
len = buffer_src.len()
|
||||||
);
|
);
|
||||||
|
let windows_len = buffer_src.len() / window_size;
|
||||||
let bounce_buffer_dst = Box::leak(allocate_dma_buffer_in(window_size, Global));
|
let bounce_buffer_dst = Box::leak(allocate_dma_buffer_in(window_size, Global));
|
||||||
let bounce_buffer_src = Box::leak(allocate_dma_buffer_in(window_size, Global));
|
let bounce_buffer_src = Box::leak(allocate_dma_buffer_in(window_size, Global));
|
||||||
let src_descs = Self::linear_descriptors_for_buffer(window_size, burst_config, |desc| {
|
let src_descs = Self::linear_descriptors_for_buffer(window_size, burst_config, |desc| {
|
||||||
|
|
@ -130,7 +135,9 @@ impl DmaBounce {
|
||||||
});
|
});
|
||||||
let bounce_dst_descs =
|
let bounce_dst_descs =
|
||||||
Self::linear_descriptors_for_buffer(window_size, burst_config, |_| {});
|
Self::linear_descriptors_for_buffer(window_size, burst_config, |_| {});
|
||||||
let bounce_src_descs = Self::bounce_descriptors_for_buffer(
|
let bounce_src_descs = if cyclic {
|
||||||
|
Self::bounce_descriptors_for_buffer_single(
|
||||||
|
windows_len,
|
||||||
unsafe {
|
unsafe {
|
||||||
(
|
(
|
||||||
&mut *(bounce_buffer_dst as *mut _),
|
&mut *(bounce_buffer_dst as *mut _),
|
||||||
|
|
@ -138,15 +145,27 @@ impl DmaBounce {
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
burst_config,
|
burst_config,
|
||||||
);
|
)
|
||||||
|
} else {
|
||||||
|
Self::bounce_descriptors_for_buffer_cyclic(
|
||||||
|
unsafe {
|
||||||
|
(
|
||||||
|
&mut *(bounce_buffer_dst as *mut _),
|
||||||
|
&mut *(bounce_buffer_src as *mut _),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
burst_config,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
channel,
|
channel,
|
||||||
peripheral_src,
|
peripheral_src,
|
||||||
peripheral_dst: Some(peripheral_dst),
|
peripheral_dst: Some(peripheral_dst),
|
||||||
burst_config,
|
burst_config,
|
||||||
|
cyclic,
|
||||||
window_size,
|
window_size,
|
||||||
windows_len: buffer_src.len() / window_size,
|
windows_len,
|
||||||
buffer_src,
|
buffer_src,
|
||||||
bounce_buffer_dst,
|
bounce_buffer_dst,
|
||||||
bounce_buffer_src,
|
bounce_buffer_src,
|
||||||
|
|
@ -190,7 +209,7 @@ impl DmaBounce {
|
||||||
descriptors
|
descriptors
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bounce_descriptors_for_buffer(
|
fn bounce_descriptors_for_buffer_cyclic(
|
||||||
bounce_buffers: (&'static mut [u8], &'static mut [u8]),
|
bounce_buffers: (&'static mut [u8], &'static mut [u8]),
|
||||||
burst_config: BurstConfig,
|
burst_config: BurstConfig,
|
||||||
) -> &'static mut [DmaDescriptor] {
|
) -> &'static mut [DmaDescriptor] {
|
||||||
|
|
@ -202,8 +221,13 @@ impl DmaBounce {
|
||||||
|
|
||||||
let buffer_len = bounce_buffers.0.len();
|
let buffer_len = bounce_buffers.0.len();
|
||||||
let max_chunk_size = burst_config.max_compatible_chunk_size();
|
let max_chunk_size = burst_config.max_compatible_chunk_size();
|
||||||
let descriptors_len = dma::descriptor_count(buffer_len, max_chunk_size, false);
|
let descriptors_len = dma::descriptor_count(
|
||||||
// TODO: This leaks memory. Ensure it's only called during setup.
|
buffer_len,
|
||||||
|
max_chunk_size,
|
||||||
|
// TODO: This might need to be set to true?
|
||||||
|
// I don't know why cyclic descriptor lists must be at least 3 descriptors long.
|
||||||
|
false,
|
||||||
|
);
|
||||||
let descriptors_combined =
|
let descriptors_combined =
|
||||||
Box::leak(vec![DmaDescriptor::EMPTY; 2 * descriptors_len].into_boxed_slice());
|
Box::leak(vec![DmaDescriptor::EMPTY; 2 * descriptors_len].into_boxed_slice());
|
||||||
let descriptors_pair = descriptors_combined.split_at_mut(descriptors_len);
|
let descriptors_pair = descriptors_combined.split_at_mut(descriptors_len);
|
||||||
|
|
@ -246,6 +270,58 @@ impl DmaBounce {
|
||||||
descriptors_combined
|
descriptors_combined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bounce_descriptors_for_buffer_single(
|
||||||
|
windows_len: usize,
|
||||||
|
bounce_buffers: (&'static mut [u8], &'static mut [u8]),
|
||||||
|
burst_config: BurstConfig,
|
||||||
|
) -> &'static mut [DmaDescriptor] {
|
||||||
|
assert_eq!(
|
||||||
|
bounce_buffers.0.len(),
|
||||||
|
bounce_buffers.1.len(),
|
||||||
|
"bounce buffers must be equal in size"
|
||||||
|
);
|
||||||
|
// If an odd number of windows were needed, two descriptor lists would be needed,
|
||||||
|
assert_eq!(windows_len % 2, 0, "the number of windows must be even");
|
||||||
|
|
||||||
|
let buffer_len = bounce_buffers.0.len();
|
||||||
|
let max_chunk_size = burst_config.max_compatible_chunk_size();
|
||||||
|
let descriptors_per_window = dma::descriptor_count(buffer_len, max_chunk_size, false);
|
||||||
|
let descriptors_frame = Box::leak(
|
||||||
|
vec![DmaDescriptor::EMPTY; descriptors_per_window * windows_len].into_boxed_slice(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Link up the descriptors.
|
||||||
|
let mut next = core::ptr::null_mut();
|
||||||
|
for desc in descriptors_frame.iter_mut().rev() {
|
||||||
|
desc.next = next;
|
||||||
|
next = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare each descriptor's buffer size.
|
||||||
|
let bounce_buffers = [bounce_buffers.0, bounce_buffers.1];
|
||||||
|
|
||||||
|
for (window_index, descriptors) in descriptors_frame
|
||||||
|
.chunks_mut(descriptors_per_window)
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
let mut descriptors_it = descriptors.iter_mut();
|
||||||
|
let mut remaining_bounce_buffer = &mut *bounce_buffers[window_index % 2];
|
||||||
|
|
||||||
|
while !remaining_bounce_buffer.is_empty() {
|
||||||
|
let chunk_size = core::cmp::min(max_chunk_size, remaining_bounce_buffer.len());
|
||||||
|
let desc = descriptors_it.next().unwrap();
|
||||||
|
desc.buffer = remaining_bounce_buffer.as_mut_ptr();
|
||||||
|
remaining_bounce_buffer = &mut remaining_bounce_buffer[chunk_size..];
|
||||||
|
let is_last = remaining_bounce_buffer.is_empty();
|
||||||
|
desc.set_size(chunk_size);
|
||||||
|
desc.set_length(chunk_size);
|
||||||
|
desc.reset_for_tx(is_last);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptors_frame
|
||||||
|
}
|
||||||
|
|
||||||
fn linear_descriptors_prepare(
|
fn linear_descriptors_prepare(
|
||||||
descriptors: &mut [DmaDescriptor],
|
descriptors: &mut [DmaDescriptor],
|
||||||
mut buffer: Option<&mut [u8]>,
|
mut buffer: Option<&mut [u8]>,
|
||||||
|
|
@ -274,55 +350,10 @@ impl DmaBounce {
|
||||||
|
|
||||||
// Enable interrupts for the peripheral
|
// Enable interrupts for the peripheral
|
||||||
interrupt::enable(interrupt, dma_interrupt_handler.priority()).unwrap();
|
interrupt::enable(interrupt, dma_interrupt_handler.priority()).unwrap();
|
||||||
// interrupt::enable(
|
|
||||||
// esp_hal::peripherals::Interrupt::DMA_OUT_CH0,
|
|
||||||
// dma_interrupt_handler.priority(),
|
|
||||||
// )
|
|
||||||
// .unwrap();
|
|
||||||
// interrupt::enable(
|
|
||||||
// esp_hal::peripherals::Interrupt::DMA_IN_CH0,
|
|
||||||
// dma_interrupt_handler.priority(),
|
|
||||||
// )
|
|
||||||
// .unwrap();
|
|
||||||
// interrupt::enable(
|
|
||||||
// esp_hal::peripherals::Interrupt::DMA_OUT_CH2,
|
|
||||||
// dma_interrupt_handler.priority(),
|
|
||||||
// )
|
|
||||||
// .unwrap();
|
|
||||||
// interrupt::enable(
|
|
||||||
// esp_hal::peripherals::Interrupt::DMA_IN_CH2,
|
|
||||||
// dma_interrupt_handler.priority(),
|
|
||||||
// )
|
|
||||||
// .unwrap();
|
|
||||||
// interrupt::enable(
|
|
||||||
// esp_hal::peripherals::Interrupt::SPI2_DMA,
|
|
||||||
// dma_interrupt_handler.priority(),
|
|
||||||
// )
|
|
||||||
// .unwrap();
|
|
||||||
|
|
||||||
// Bind the handler
|
// Bind the handler
|
||||||
unsafe {
|
unsafe {
|
||||||
interrupt::bind_interrupt(interrupt, dma_interrupt_handler.handler());
|
interrupt::bind_interrupt(interrupt, dma_interrupt_handler.handler());
|
||||||
// interrupt::bind_interrupt(
|
|
||||||
// esp_hal::peripherals::Interrupt::DMA_OUT_CH0,
|
|
||||||
// dma_interrupt_handler.handler(),
|
|
||||||
// );
|
|
||||||
// interrupt::bind_interrupt(
|
|
||||||
// esp_hal::peripherals::Interrupt::DMA_IN_CH0,
|
|
||||||
// dma_interrupt_handler.handler(),
|
|
||||||
// );
|
|
||||||
// interrupt::bind_interrupt(
|
|
||||||
// esp_hal::peripherals::Interrupt::DMA_OUT_CH2,
|
|
||||||
// dma_interrupt_handler.handler(),
|
|
||||||
// );
|
|
||||||
// interrupt::bind_interrupt(
|
|
||||||
// esp_hal::peripherals::Interrupt::DMA_IN_CH2,
|
|
||||||
// dma_interrupt_handler.handler(),
|
|
||||||
// );
|
|
||||||
// interrupt::bind_interrupt(
|
|
||||||
// esp_hal::peripherals::Interrupt::SPI2_DMA,
|
|
||||||
// dma_interrupt_handler.handler(),
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable interrupts in the peripheral.
|
// Enable interrupts in the peripheral.
|
||||||
|
|
@ -330,74 +361,19 @@ impl DmaBounce {
|
||||||
.ch(channel_number)
|
.ch(channel_number)
|
||||||
.out_int()
|
.out_int()
|
||||||
.ena()
|
.ena()
|
||||||
.modify(|_, w| {
|
.modify(|_, w| w.out_eof().bit(true));
|
||||||
// w.out_total_eof().bit(true);
|
|
||||||
w.out_eof().bit(true);
|
|
||||||
// w.out_done().bit(true);
|
|
||||||
w
|
|
||||||
});
|
|
||||||
// DMA::regs()
|
|
||||||
// .ch(channel_number)
|
|
||||||
// .in_int()
|
|
||||||
// .ena()
|
|
||||||
// .modify(|_, w| {
|
|
||||||
// w.in_suc_eof().bit(true);
|
|
||||||
// w.in_done().bit(true);
|
|
||||||
// w
|
|
||||||
// });
|
|
||||||
// SPI2::regs().dma_int_ena().modify(|_, w| {
|
|
||||||
// w.slv_rd_dma_done().bit(true);
|
|
||||||
// w.slv_wr_dma_done().bit(true);
|
|
||||||
// w.dma_seg_trans_done().bit(true);
|
|
||||||
// w.trans_done().bit(true);
|
|
||||||
// w
|
|
||||||
// });
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_regs() {
|
|
||||||
// TODO: Get from self.channel
|
|
||||||
for channel_number in [0, 2] {
|
|
||||||
let out_int_raw = DMA::regs()
|
|
||||||
.ch(channel_number as usize)
|
|
||||||
.out_int()
|
|
||||||
.st()
|
|
||||||
.read();
|
|
||||||
let in_int_raw = DMA::regs().ch(channel_number as usize).in_int().st().read();
|
|
||||||
log::error!(
|
|
||||||
indoc! {"
|
|
||||||
int_raw[{channel_number}]:
|
|
||||||
flag: {flag}
|
|
||||||
out:
|
|
||||||
total_eof: {out_total_eof}
|
|
||||||
eof: {out_eof}
|
|
||||||
done: {out_done}
|
|
||||||
in:
|
|
||||||
suc_eof: {in_suc_eof}
|
|
||||||
done: {in_done}
|
|
||||||
"},
|
|
||||||
channel_number = channel_number,
|
|
||||||
flag = FLAG.load(atomic::Ordering::SeqCst),
|
|
||||||
out_total_eof = out_int_raw.out_total_eof().bit_is_set(),
|
|
||||||
out_eof = out_int_raw.out_eof().bit_is_set(),
|
|
||||||
out_done = out_int_raw.out_done().bit_is_set(),
|
|
||||||
in_suc_eof = in_int_raw.in_suc_eof().bit_is_set(),
|
|
||||||
in_done = in_int_raw.in_done().bit_is_set(),
|
|
||||||
);
|
|
||||||
error!(
|
|
||||||
"int_raw_msg[{channel_number}]: 0x{:08x?}",
|
|
||||||
INT_CHANNEL.try_receive()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receive a window of bytes into the current dst bounce buffer.
|
/// Receive a window of bytes into the current dst bounce buffer.
|
||||||
/// Finally, swaps the bounce buffers.
|
/// Finally, swaps the bounce buffers.
|
||||||
async fn receive_window(&mut self) {
|
fn receive_window_blocking(&mut self) {
|
||||||
// Descriptors are initialized by `DmaTxBuf::new`.
|
// Descriptors are initialized by `DmaTxBuf::new`.
|
||||||
let buffer_src_window =
|
let buffer_src_window =
|
||||||
&mut self.buffer_src[self.window_index_next * self.window_size..][..self.window_size];
|
&mut self.buffer_src[self.window_index_next * self.window_size..][..self.window_size];
|
||||||
|
|
||||||
Self::linear_descriptors_prepare(self.src_descs, Some(buffer_src_window), |_| {});
|
Self::linear_descriptors_prepare(self.src_descs, Some(buffer_src_window), |desc| {
|
||||||
|
// desc.reset_for_tx(desc.next.is_null());
|
||||||
|
});
|
||||||
// TODO: Precompute a descriptor list for each buffer, then use `None` instead of `Some(&mut *self.bounce_buffer_dst)`.
|
// TODO: Precompute a descriptor list for each buffer, then use `None` instead of `Some(&mut *self.bounce_buffer_dst)`.
|
||||||
Self::linear_descriptors_prepare(
|
Self::linear_descriptors_prepare(
|
||||||
self.bounce_dst_descs,
|
self.bounce_dst_descs,
|
||||||
|
|
@ -425,15 +401,6 @@ impl DmaBounce {
|
||||||
transfer.wait().unwrap();
|
transfer.wait().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Get rid of this!
|
|
||||||
// unsafe {
|
|
||||||
// cache_invalidate_addr(
|
|
||||||
// self.bounce_buffer_dst.as_ptr() as u32,
|
|
||||||
// self.bounce_buffer_dst.len() as u32,
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// assert_eq!(self.bounce_buffer_dst, buffer_src_window);
|
|
||||||
|
|
||||||
self.increase_window_counter(1);
|
self.increase_window_counter(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -452,42 +419,22 @@ impl DmaBounce {
|
||||||
Self::enable_interrupts();
|
Self::enable_interrupts();
|
||||||
|
|
||||||
// Receive the first window, so that the outbound transfer can read valid data.
|
// Receive the first window, so that the outbound transfer can read valid data.
|
||||||
self.receive_window().await;
|
self.receive_window_blocking();
|
||||||
|
|
||||||
let mut dma_tx_buffer = self.get_dma_tx_buffer();
|
let mut dma_tx_buffer = self.get_dma_tx_buffer();
|
||||||
let transfer = match self
|
let mut transfer = self
|
||||||
.peripheral_dst
|
.peripheral_dst
|
||||||
.take()
|
.take()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.send(true /* Send perpetually */, dma_tx_buffer)
|
.send(self.cyclic /* Send perpetually */, dma_tx_buffer)
|
||||||
{
|
.unwrap_or_else(|(error, _, _)| {
|
||||||
Ok(transfer) => {
|
panic!("failed to begin the transmission of the first frame: {error:?}");
|
||||||
// let result;
|
});
|
||||||
// let peripheral_dst;
|
|
||||||
// (result, peripheral_dst, dma_tx_buffer) = transfer.wait();
|
|
||||||
// self.peripheral_dst = Some(peripheral_dst);
|
|
||||||
|
|
||||||
// if let Err(error) = result {
|
|
||||||
// error!("DPI error during sending: {error:?}");
|
|
||||||
// }
|
|
||||||
warn!("Sending data to DPI!");
|
|
||||||
transfer
|
|
||||||
}
|
|
||||||
Err(error_tuple) => {
|
|
||||||
let error;
|
|
||||||
let peripheral_dst;
|
|
||||||
(error, peripheral_dst, dma_tx_buffer) = error_tuple;
|
|
||||||
self.peripheral_dst = Some(peripheral_dst);
|
|
||||||
panic!("DPI error when starting transfer: {error:?}");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut windows_skipped_total = 0;
|
let mut windows_skipped_total = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// warn!("Iteration. Done = {}", transfer.is_done());
|
self.receive_window_blocking();
|
||||||
self.receive_window().await;
|
|
||||||
// let windows_sent = BOUNCE_BUFFER_SENT.receive().await;
|
|
||||||
let windows_skipped = WINDOWS_SKIPPED.wait().await;
|
let windows_skipped = WINDOWS_SKIPPED.wait().await;
|
||||||
|
|
||||||
if windows_skipped > 0 {
|
if windows_skipped > 0 {
|
||||||
|
|
@ -498,6 +445,38 @@ impl DmaBounce {
|
||||||
100.0 * windows_skipped_total as f32 / (self.frame_index_next + 1) as f32
|
100.0 * windows_skipped_total as f32 / (self.frame_index_next + 1) as f32
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.cyclic && self.window_index_next == 1 {
|
||||||
|
// TODO: Investigate why the DPI transfer isn't done at this point.
|
||||||
|
// The `DpiTransfer::wait()` below takes 0.001039 s.
|
||||||
|
// Perhaps it's the minimum screen refresh period?
|
||||||
|
//
|
||||||
|
// assert!(transfer.is_done());
|
||||||
|
// if !transfer.is_done() {
|
||||||
|
// error!(
|
||||||
|
// "transfer is not done yet. {} {}",
|
||||||
|
// self.frame_index_next, self.window_index_next
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
let result;
|
||||||
|
let peripheral_dst;
|
||||||
|
// let start = Instant::now();
|
||||||
|
(result, peripheral_dst, dma_tx_buffer) = transfer.wait();
|
||||||
|
// let duration = Instant::now().duration_since(start);
|
||||||
|
// warn!("Waited for {} seconds", duration.display_as_secs());
|
||||||
|
|
||||||
|
if let Err(error) = result {
|
||||||
|
error!("DPI error during sending: {error:?}");
|
||||||
|
}
|
||||||
|
|
||||||
|
transfer =
|
||||||
|
peripheral_dst
|
||||||
|
.send(false, dma_tx_buffer)
|
||||||
|
.unwrap_or_else(|(error, _, _)| {
|
||||||
|
panic!("failed to begin the transmission of a frame: {error:?}");
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// loop {
|
// loop {
|
||||||
|
|
@ -568,10 +547,6 @@ unsafe impl DmaTxBuffer for DmaTxBounceBuf {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static INT_CHANNEL: Channel<RawMutex, u32, 128> = Channel::new();
|
|
||||||
static FLAG: AtomicBool = AtomicBool::new(false);
|
|
||||||
// static WINDOWS_SENT: AtomicU32 = AtomicU32::new(0);
|
|
||||||
// static BOUNCE_BUFFER_SENT: Channel<RawMutex, usize, 1> = Channel::new();
|
|
||||||
static WINDOWS_SKIPPED: Signal<RawMutex, usize> = Signal::new();
|
static WINDOWS_SKIPPED: Signal<RawMutex, usize> = Signal::new();
|
||||||
|
|
||||||
#[handler(priority = Priority::Priority3)]
|
#[handler(priority = Priority::Priority3)]
|
||||||
|
|
@ -588,45 +563,7 @@ fn dma_interrupt_handler() {
|
||||||
.map(|windows_skipped| windows_skipped + 1)
|
.map(|windows_skipped| windows_skipped + 1)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
WINDOWS_SKIPPED.signal(windows_skipped);
|
WINDOWS_SKIPPED.signal(windows_skipped);
|
||||||
// let value = BOUNCE_BUFFER_SENT.try_receive().ok().unwrap_or_default() + 1;
|
|
||||||
// BOUNCE_BUFFER_SENT.try_send(value).expect(
|
|
||||||
// "failed to send bounce buffer signal, because the previous one wasn't processed yet",
|
|
||||||
// );
|
|
||||||
// let value = WINDOWS_SENT.fetch_add(1, atomic::Ordering::SeqCst);
|
|
||||||
// warn!("inner int {value}");
|
|
||||||
}
|
}
|
||||||
// FLAG.store(true, atomic::Ordering::SeqCst);
|
|
||||||
// let int_raw = DMA::regs()
|
|
||||||
// .ch(2)
|
|
||||||
// .out_int()
|
|
||||||
// .st()
|
|
||||||
// .read()
|
|
||||||
// .out_eof()
|
|
||||||
// .bit_is_set();
|
|
||||||
|
|
||||||
// INT_CHANNEL.try_send(int_raw.bits()).unwrap();
|
|
||||||
|
|
||||||
// let lcd_cam = unsafe { &*esp_hal::peripherals::LCD_CAM::PTR };
|
|
||||||
|
|
||||||
// // Check and clear VSYNC interrupt
|
|
||||||
// if lcd_cam
|
|
||||||
// .lc_dma_int_raw()
|
|
||||||
// .read()
|
|
||||||
// .lcd_vsync_int_raw()
|
|
||||||
// .bit_is_set()
|
|
||||||
// {
|
|
||||||
// lcd_cam
|
|
||||||
// .lc_dma_int_clr()
|
|
||||||
// .write(|w| w.lcd_vsync_int_clr().set_bit());
|
|
||||||
|
|
||||||
// INT_CHANNEL.send();
|
|
||||||
// // VSYNC_SIGNAL.signal(());
|
|
||||||
|
|
||||||
// // Signal the event
|
|
||||||
// // critical_section::with(|cs| {
|
|
||||||
// // *VSYNC_FLAG.borrow_ref_mut(cs) = true;
|
|
||||||
// // });
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_lcd(
|
pub async fn run_lcd(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue