diff --git a/firmware/acid-firmware/src/ui/dpi.rs b/firmware/acid-firmware/src/ui/dpi.rs index ecdc402..be38a6e 100644 --- a/firmware/acid-firmware/src/ui/dpi.rs +++ b/firmware/acid-firmware/src/ui/dpi.rs @@ -185,6 +185,9 @@ impl DmaBounce { Self::linear_descriptors_for_buffer(window_size, burst_config, |_| {}); let bounce_src_descs = if cyclic { Self::bounce_descriptors_for_buffer_cyclic( + row_front_porch_bytes, + row_width_bytes, + window_size_rows, unsafe { ( &mut *(bounce_buffer_dst as *mut _), @@ -260,7 +263,105 @@ impl DmaBounce { descriptors } + fn prepare_descriptors_window( + bounce_buffer: &mut [u8], + descriptors_window: &mut [DmaDescriptor], + row_front_porch_bytes: usize, + row_width_bytes: usize, + window_size_rows: usize, + max_chunk_size: usize, + descriptors_per_row: usize, + descriptors_per_row_front_porch: usize, + ) { + for (row_index_in_window, descriptors_row) in descriptors_window + .chunks_mut(descriptors_per_row) + .enumerate() + { + // let row_index = row_index_in_window + window_index * window_size_rows; + let (descriptors_row_front_porch, descriptors_row_stored) = + descriptors_row.split_at_mut(descriptors_per_row_front_porch); + + // Prepare front porch descriptors. + { + let mut descriptors_it = descriptors_row_front_porch.iter_mut(); + let mut remaining_front_porch = row_front_porch_bytes; + + while remaining_front_porch > 0 { + let desc = descriptors_it.next().unwrap(); + let chunk_size = core::cmp::min(max_chunk_size, remaining_front_porch); + remaining_front_porch -= chunk_size; + // Just make it point at a bounce buffer. + // It is guaranteed to have enough bytes by `DmaBounce::new`. + desc.buffer = bounce_buffer.as_mut_ptr(); + desc.set_size(chunk_size); + desc.set_length(chunk_size); + desc.reset_for_tx(false); + } + + assert!( + descriptors_it.next().is_none(), + "front porch descriptors must be used up" + ); + assert_eq!( + descriptors_row_front_porch + .iter() + .map(|desc| desc.size()) + .sum::(), + row_front_porch_bytes + ); + } + + // Prepare window descriptors. + { + let mut remaining_bounce_buffer = + &mut bounce_buffer[row_index_in_window * row_width_bytes..][..row_width_bytes]; + + // if remaining_bounce_buffer.len() > row_width_bytes { + // remaining_bounce_buffer = &mut remaining_bounce_buffer[..row_width_bytes]; + // } + + for desc in &mut *descriptors_row_stored { + let chunk_size = core::cmp::min(max_chunk_size, remaining_bounce_buffer.len()); + desc.buffer = remaining_bounce_buffer.as_mut_ptr(); + remaining_bounce_buffer = &mut remaining_bounce_buffer[chunk_size..]; + desc.set_size(chunk_size); + desc.set_length(chunk_size); + desc.reset_for_tx(false); + } + + assert!( + remaining_bounce_buffer.is_empty(), + "bounce buffer must be used up" + ); + assert_eq!( + descriptors_row_stored + .iter() + .map(|desc| desc.size()) + .sum::(), + row_width_bytes + ); + } + } + + // Set EOF bit on the last descriptor of the window, to signal + // that the bounce buffer is done being read from. + if let Some(last_desc) = descriptors_window.last_mut() { + last_desc.reset_for_tx(true); + } + + assert_eq!( + descriptors_window + .iter() + .map(|desc| desc.size()) + .sum::(), + window_size_rows * (row_front_porch_bytes + row_width_bytes) + ); + } + fn bounce_descriptors_for_buffer_cyclic( + row_front_porch_bytes: usize, + row_width_bytes: usize, + window_size_rows: usize, bounce_buffers: (&'static mut [u8], &'static mut [u8]), burst_config: BurstConfig, ) -> &'static mut [DmaDescriptor] { @@ -271,17 +372,23 @@ impl DmaBounce { ); let buffer_len = bounce_buffers.0.len(); - let max_chunk_size = burst_config.max_compatible_chunk_size(); - let descriptors_len = dma::descriptor_count( + + assert_eq!( 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, + row_width_bytes * window_size_rows, + "the provided bounce buffers have an invalid size" ); + + let max_chunk_size = burst_config.max_compatible_chunk_size(); + let descriptors_per_row_front_porch = + dma::descriptor_count(row_front_porch_bytes, max_chunk_size, false); + let descriptors_per_row_stored = + dma::descriptor_count(row_width_bytes, max_chunk_size, false); + let descriptors_per_row = descriptors_per_row_stored + descriptors_per_row_front_porch; + let descriptors_per_window = window_size_rows * descriptors_per_row; let descriptors_combined = - Box::leak(vec![DmaDescriptor::EMPTY; 2 * descriptors_len].into_boxed_slice()); - let descriptors_pair = descriptors_combined.split_at_mut(descriptors_len); + Box::leak(vec![DmaDescriptor::EMPTY; 2 * descriptors_per_window].into_boxed_slice()); + let descriptors_pair = descriptors_combined.split_at_mut(descriptors_per_window); // Link up the descriptors. fn link_up_descriptors( @@ -303,19 +410,16 @@ impl DmaBounce { (bounce_buffers.0, descriptors_pair.0), (bounce_buffers.1, descriptors_pair.1), ] { - let mut descriptors_it = descriptors.iter_mut(); - let mut remaining_bounce_buffer = bounce_buffer; - - 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); - } + Self::prepare_descriptors_window( + bounce_buffer, + descriptors, + row_front_porch_bytes, + row_width_bytes, + window_size_rows, + max_chunk_size, + descriptors_per_row, + descriptors_per_row_front_porch, + ); } descriptors_combined @@ -345,10 +449,6 @@ impl DmaBounce { "the provided bounce buffers have an invalid size" ); - warn!( - "windows_len: {windows_len}\nrow_front_porch_bytes: {row_front_porch_bytes}\nrow_width_bytes: {row_width_bytes}\nwindow_size_rows: {window_size_rows}\nbuffer_len: {buffer_len}", - ); - let max_chunk_size = burst_config.max_compatible_chunk_size(); let descriptors_per_row_front_porch = dma::descriptor_count(row_front_porch_bytes, max_chunk_size, false); @@ -376,92 +476,16 @@ impl DmaBounce { { let bounce_buffer_index = window_index % 2; let bounce_buffer = &mut *bounce_buffers[bounce_buffer_index]; - // let bounce_buffer_ptr = bounce_buffers[bounce_buffer_index].as_mut_ptr(); - // let mut remaining_bounce_buffer = &mut *bounce_buffers[bounce_buffer_index]; - for (row_index_in_window, descriptors_row) in descriptors_window - .chunks_mut(descriptors_per_row) - .enumerate() - { - // let row_index = row_index_in_window + window_index * window_size_rows; - let (descriptors_row_front_porch, descriptors_row_stored) = - descriptors_row.split_at_mut(descriptors_per_row_front_porch); - - // Prepare front porch descriptors. - { - let mut descriptors_it = descriptors_row_front_porch.iter_mut(); - let mut remaining_front_porch = row_front_porch_bytes; - - while remaining_front_porch > 0 { - let desc = descriptors_it.next().unwrap(); - let chunk_size = core::cmp::min(max_chunk_size, remaining_front_porch); - remaining_front_porch -= chunk_size; - // Just make it point at a bounce buffer. - // It is guaranteed to have enough bytes by `DmaBounce::new`. - desc.buffer = bounce_buffer.as_mut_ptr(); - desc.set_size(chunk_size); - desc.set_length(chunk_size); - desc.reset_for_tx(false); - } - - assert!( - descriptors_it.next().is_none(), - "front porch descriptors must be used up" - ); - assert_eq!( - descriptors_row_front_porch - .iter() - .map(|desc| desc.size()) - .sum::(), - row_front_porch_bytes - ); - } - - // Prepare window descriptors. - { - let mut remaining_bounce_buffer = &mut bounce_buffer - [row_index_in_window * row_width_bytes..][..row_width_bytes]; - - // if remaining_bounce_buffer.len() > row_width_bytes { - // remaining_bounce_buffer = &mut remaining_bounce_buffer[..row_width_bytes]; - // } - - for desc in &mut *descriptors_row_stored { - let chunk_size = - core::cmp::min(max_chunk_size, remaining_bounce_buffer.len()); - desc.buffer = remaining_bounce_buffer.as_mut_ptr(); - remaining_bounce_buffer = &mut remaining_bounce_buffer[chunk_size..]; - desc.set_size(chunk_size); - desc.set_length(chunk_size); - desc.reset_for_tx(false); - } - - assert!( - remaining_bounce_buffer.is_empty(), - "bounce buffer must be used up" - ); - assert_eq!( - descriptors_row_stored - .iter() - .map(|desc| desc.size()) - .sum::(), - row_width_bytes - ); - } - } - - // Set EOF bit on the last descriptor of the window, to signal - // that the bounce buffer is done being read from. - if let Some(last_desc) = descriptors_window.last_mut() { - last_desc.reset_for_tx(true); - } - - assert_eq!( - descriptors_window - .iter() - .map(|desc| desc.size()) - .sum::(), - window_size_rows * (row_front_porch_bytes + row_width_bytes) + Self::prepare_descriptors_window( + bounce_buffer, + descriptors_window, + row_front_porch_bytes, + row_width_bytes, + window_size_rows, + max_chunk_size, + descriptors_per_row, + descriptors_per_row_front_porch, ); }