mirror of
https://github.com/laanwj/k210-sdk-stuff.git
synced 2024-11-25 10:56:20 +04:00
rust: Improve DVP interface
Clean up interface a bit.
This commit is contained in:
parent
8cc5ff53f5
commit
cd7f72f03f
@ -5,6 +5,7 @@ use pac::dvp;
|
|||||||
use crate::soc::sleep::usleep;
|
use crate::soc::sleep::usleep;
|
||||||
use crate::soc::sysctl;
|
use crate::soc::sysctl;
|
||||||
|
|
||||||
|
/** Extension trait for adding constrain() to DVP peripheral */
|
||||||
pub trait DVPExt: Sized {
|
pub trait DVPExt: Sized {
|
||||||
/// Constrains DVP peripheral
|
/// Constrains DVP peripheral
|
||||||
fn constrain(self) -> DVP;
|
fn constrain(self) -> DVP;
|
||||||
@ -14,13 +15,6 @@ impl DVPExt for pac::DVP {
|
|||||||
fn constrain(self) -> DVP { DVP { dvp: self, sccb_addr_len: sccb_addr_len::W8 } }
|
fn constrain(self) -> DVP { DVP { dvp: self, sccb_addr_len: sccb_addr_len::W8 } }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Output mode (RGB565 for display, or for planar for AI) */
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub enum output_mode {
|
|
||||||
AI,
|
|
||||||
DISPLAY,
|
|
||||||
}
|
|
||||||
|
|
||||||
/** SCCB register address width */
|
/** SCCB register address width */
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum sccb_addr_len {
|
pub enum sccb_addr_len {
|
||||||
@ -28,18 +22,20 @@ pub enum sccb_addr_len {
|
|||||||
W16,
|
W16,
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Interrupt */
|
/** Enumeration for different DVP interrupts */
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone)]
|
||||||
pub enum interrupt {
|
pub enum interrupt {
|
||||||
frame_start,
|
frame_start,
|
||||||
frame_finish,
|
frame_finish,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** DVP peripheral abstraction */
|
||||||
pub struct DVP {
|
pub struct DVP {
|
||||||
dvp: pac::DVP,
|
dvp: pac::DVP,
|
||||||
sccb_addr_len: sccb_addr_len,
|
sccb_addr_len: sccb_addr_len,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Borrow image_format enum from pac */
|
||||||
pub type image_format = dvp::dvp_cfg::FORMATW;
|
pub type image_format = dvp::dvp_cfg::FORMATW;
|
||||||
|
|
||||||
impl DVP {
|
impl DVP {
|
||||||
@ -134,13 +130,13 @@ impl DVP {
|
|||||||
|
|
||||||
/** Reset DVP-connected device */
|
/** Reset DVP-connected device */
|
||||||
fn reset(&self) {
|
fn reset(&self) {
|
||||||
/* First power down */
|
// First power down
|
||||||
self.dvp.cmos_cfg.modify(|_,w| w.power_down().set_bit());
|
self.dvp.cmos_cfg.modify(|_,w| w.power_down().set_bit());
|
||||||
usleep(200_000);
|
usleep(200_000);
|
||||||
self.dvp.cmos_cfg.modify(|_,w| w.power_down().clear_bit());
|
self.dvp.cmos_cfg.modify(|_,w| w.power_down().clear_bit());
|
||||||
usleep(200_000);
|
usleep(200_000);
|
||||||
|
|
||||||
/* Second reset */
|
// Second reset
|
||||||
self.dvp.cmos_cfg.modify(|_,w| w.reset().clear_bit());
|
self.dvp.cmos_cfg.modify(|_,w| w.reset().clear_bit());
|
||||||
usleep(200_000);
|
usleep(200_000);
|
||||||
self.dvp.cmos_cfg.modify(|_,w| w.reset().set_bit());
|
self.dvp.cmos_cfg.modify(|_,w| w.reset().set_bit());
|
||||||
@ -183,29 +179,18 @@ impl DVP {
|
|||||||
self.dvp.dvp_cfg.modify(|_,w| w.format().variant(format));
|
self.dvp.dvp_cfg.modify(|_,w| w.format().variant(format));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not sure it's consistent interface to have two separate functions here, but just going with
|
/** Set image size and burst mode. If burst mode is enabled the maximum configurable size is
|
||||||
// the SDK for now... might even want to merge these into set_image_size, or force configuring
|
|
||||||
// the entire peripheral (register size, burst mode, image size) at once
|
|
||||||
/** Enable burst mode */
|
|
||||||
pub fn enable_burst(&self) {
|
|
||||||
self.dvp.dvp_cfg.modify(|_,w| w.burst_size_4beats().set_bit());
|
|
||||||
self.dvp.axi.modify(|_,w| w.gm_mlen().variant(dvp::axi::GM_MLENW::BYTE4));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Disable burst mode */
|
|
||||||
pub fn disable_burst(&self) {
|
|
||||||
self.dvp.dvp_cfg.modify(|_,w| w.burst_size_4beats().clear_bit());
|
|
||||||
self.dvp.axi.modify(|_,w| w.gm_mlen().variant(dvp::axi::GM_MLENW::BYTE1));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set image size. If burst mode is enabled the maximum configurable size is
|
|
||||||
* 8160x1023, without burst mode it is 2040x1023.
|
* 8160x1023, without burst mode it is 2040x1023.
|
||||||
*/
|
*/
|
||||||
pub fn set_image_size(&self, width: u16, height: u16) {
|
pub fn set_image_size(&self, burst_mode: bool, width: u16, height: u16) {
|
||||||
// Note: this uses state written in enable/disable_burst, so that needs to be configured before this
|
// Note: this uses state written in enable/disable_burst, so that needs to be configured before this
|
||||||
let burst_num = if self.dvp.dvp_cfg.read().burst_size_4beats().bit() {
|
let burst_num = if burst_mode {
|
||||||
|
self.dvp.dvp_cfg.modify(|_,w| w.burst_size_4beats().set_bit());
|
||||||
|
self.dvp.axi.modify(|_,w| w.gm_mlen().variant(dvp::axi::GM_MLENW::BYTE4));
|
||||||
width / 8 / 4
|
width / 8 / 4
|
||||||
} else {
|
} else {
|
||||||
|
self.dvp.dvp_cfg.modify(|_,w| w.burst_size_4beats().clear_bit());
|
||||||
|
self.dvp.axi.modify(|_,w| w.gm_mlen().variant(dvp::axi::GM_MLENW::BYTE1));
|
||||||
width / 8 / 1
|
width / 8 / 1
|
||||||
};
|
};
|
||||||
assert!(burst_num < 256);
|
assert!(burst_num < 256);
|
||||||
@ -216,8 +201,11 @@ impl DVP {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set address for planar RGB output */
|
/** Set address for planar RGB output for KPU
|
||||||
pub fn set_ai_addr(&self, r_addr: *mut u8, g_addr: *mut u8, b_addr: *mut u8) {
|
* `Option<(r_addr, g_addr, b_addr)>`
|
||||||
|
*/
|
||||||
|
pub fn set_ai_addr(&self, addr: Option<(*mut u8, *mut u8, *mut u8)>) {
|
||||||
|
if let Some((r_addr, g_addr, b_addr)) = addr {
|
||||||
// Makes use of the fact that
|
// Makes use of the fact that
|
||||||
// a) physical memory is the same as virtual memory on the K210
|
// a) physical memory is the same as virtual memory on the K210
|
||||||
// b) memory wraps around every 2^32
|
// b) memory wraps around every 2^32
|
||||||
@ -226,13 +214,22 @@ impl DVP {
|
|||||||
self.dvp.g_addr.write(|w| w.bits(((g_addr as usize) & 0xffffffff) as u32));
|
self.dvp.g_addr.write(|w| w.bits(((g_addr as usize) & 0xffffffff) as u32));
|
||||||
self.dvp.b_addr.write(|w| w.bits(((b_addr as usize) & 0xffffffff) as u32));
|
self.dvp.b_addr.write(|w| w.bits(((b_addr as usize) & 0xffffffff) as u32));
|
||||||
}
|
}
|
||||||
|
self.dvp.dvp_cfg.modify(|_,w| w.ai_output_enable().set_bit());
|
||||||
|
} else {
|
||||||
|
self.dvp.dvp_cfg.modify(|_,w| w.ai_output_enable().clear_bit());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set address for 16-bit R5G6B5 output */
|
/** Set address for 16-bit R5G6B5 output */
|
||||||
pub fn set_display_addr(&self, addr: *mut u16) {
|
pub fn set_display_addr(&self, addr: Option<*mut u16>) {
|
||||||
|
if let Some(addr) = addr {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.dvp.rgb_addr.write(|w| w.bits(((addr as usize) & 0xffffffff) as u32));
|
self.dvp.rgb_addr.write(|w| w.bits(((addr as usize) & 0xffffffff) as u32));
|
||||||
}
|
}
|
||||||
|
self.dvp.dvp_cfg.modify(|_,w| w.display_output_enable().set_bit());
|
||||||
|
} else {
|
||||||
|
self.dvp.dvp_cfg.modify(|_,w| w.display_output_enable().clear_bit());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Start a frame */
|
/** Start a frame */
|
||||||
@ -315,29 +312,9 @@ impl DVP {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Enable automatic frame mode */
|
/** Enable/disable automatic frame mode */
|
||||||
pub fn enable_auto(&self) {
|
pub fn set_auto(&self, enable: bool) {
|
||||||
self.dvp.dvp_cfg.modify(|_,w| w.auto_enable().set_bit());
|
self.dvp.dvp_cfg.modify(|_,w| w.auto_enable().bit(enable));
|
||||||
}
|
|
||||||
|
|
||||||
/** Disable automatic frame mode */
|
|
||||||
pub fn disable_auto(&self) {
|
|
||||||
self.dvp.dvp_cfg.modify(|_,w| w.auto_enable().clear_bit());
|
|
||||||
}
|
|
||||||
|
|
||||||
// The following function could be merged into setting the address?
|
|
||||||
// set_display_addr / set_ai_addr with an Option maybe?
|
|
||||||
/** Enable/disable an output */
|
|
||||||
pub fn set_output_enable(&self, index: output_mode, enable: bool) {
|
|
||||||
match index {
|
|
||||||
output_mode::AI => {
|
|
||||||
self.dvp.dvp_cfg.modify(|_,w| w.ai_output_enable().bit(enable));
|
|
||||||
}
|
|
||||||
output_mode::DISPLAY => {
|
|
||||||
self.dvp.dvp_cfg.modify(|_,w| w.display_output_enable().bit(enable));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user