Constructor consistency update (#2610)
* UART: only implement constructors with config, define ConfigError * UART: only implement interrupt functions for Blocking * I2C: fallible constructors * Lcd/Cam * SPI * Update tests and examples * Changelog * Add note about ConfigError * Fmt
This commit is contained in:
parent
1a2bee6f1f
commit
92910bf1cb
@ -30,12 +30,17 @@ In general, the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines
|
|||||||
- The peripheral instance type must default to a type that supports any of the peripheral instances.
|
- The peripheral instance type must default to a type that supports any of the peripheral instances.
|
||||||
- The author must to use `crate::any_peripheral` to define the "any" peripheral instance type.
|
- The author must to use `crate::any_peripheral` to define the "any" peripheral instance type.
|
||||||
- The driver must implement a `new` constructor that automatically converts the peripheral instance into the any type, and a `new_typed` that preserves the peripheral type.
|
- The driver must implement a `new` constructor that automatically converts the peripheral instance into the any type, and a `new_typed` that preserves the peripheral type.
|
||||||
|
- If a driver is configurable, configuration options should be implemented as a `Config` struct in the same module where the driver is located.
|
||||||
|
- The driver's constructor should take the config struct by value, and it should return `Result<Self, ConfigError>`.
|
||||||
|
- The `ConfigError` enum should be separate from other `Error` enums used by the driver.
|
||||||
|
- The driver should implement `fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError>`.
|
||||||
|
- In case the driver's configuration is infallible (all possible combinations of options are supported by the hardware), the `ConfigError` should be implemented as an empty `enum`.
|
||||||
- If a driver only supports a single peripheral instance, no instance type parameter is necessary.
|
- If a driver only supports a single peripheral instance, no instance type parameter is necessary.
|
||||||
- If a driver implements both blocking and async operations, or only implements blocking operations, but may support asynchronous ones in the future, the driver's type signature must include a `crate::Mode` type parameter.
|
- If a driver implements both blocking and async operations, or only implements blocking operations, but may support asynchronous ones in the future, the driver's type signature must include a `crate::Mode` type parameter.
|
||||||
- By default, constructors must configure the driver for blocking mode. The driver must implement `into_async` (and a matching `into_blocking`) function that reconfigures the driver.
|
- By default, constructors must configure the driver for blocking mode. The driver must implement `into_async` (and a matching `into_blocking`) function that reconfigures the driver.
|
||||||
- `into_async` must configure the driver and/or the associated DMA channels. This most often means enabling an interrupt handler.
|
- `into_async` must configure the driver and/or the associated DMA channels. This most often means enabling an interrupt handler.
|
||||||
- `into_blocking` must undo the configuration done by `into_async`.
|
- `into_blocking` must undo the configuration done by `into_async`.
|
||||||
- The asynchronous driver implemntation must also expose the blocking methods (except for interrupt related functions).
|
- The asynchronous driver implementation must also expose the blocking methods (except for interrupt related functions).
|
||||||
- Drivers must have a `Drop` implementation resetting the peripheral to idle state. There are some exceptions to this:
|
- Drivers must have a `Drop` implementation resetting the peripheral to idle state. There are some exceptions to this:
|
||||||
- GPIO where common usage is to "set and drop" so they can't be changed
|
- GPIO where common usage is to "set and drop" so they can't be changed
|
||||||
- Where we don't want to disable the peripheral as it's used internally, for example SYSTIMER is used by `time::now()` API. See `KEEP_ENABLED` in src/system.rs
|
- Where we don't want to disable the peripheral as it's used internally, for example SYSTIMER is used by `time::now()` API. See `KEEP_ENABLED` in src/system.rs
|
||||||
|
|||||||
@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- The timer drivers `OneShotTimer` & `PeriodicTimer` have `into_async` and `new_typed` methods (#2586)
|
- The timer drivers `OneShotTimer` & `PeriodicTimer` have `into_async` and `new_typed` methods (#2586)
|
||||||
- `timer::Timer` trait has three new methods, `wait`, `async_interrupt_handler` and `peripheral_interrupt` (#2586)
|
- `timer::Timer` trait has three new methods, `wait`, `async_interrupt_handler` and `peripheral_interrupt` (#2586)
|
||||||
- Configuration structs in the I2C, SPI, and UART drivers now implement the Builder Lite pattern (#2614)
|
- Configuration structs in the I2C, SPI, and UART drivers now implement the Builder Lite pattern (#2614)
|
||||||
|
- Added `I8080::apply_config`, `DPI::apply_config` and `Camera::apply_config` (#2610)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
@ -44,6 +45,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- `timer::Timer` has new trait requirements of `Into<AnyTimer>`, `'static` and `InterruptConfigurable` (#2586)
|
- `timer::Timer` has new trait requirements of `Into<AnyTimer>`, `'static` and `InterruptConfigurable` (#2586)
|
||||||
- `systimer::etm::Event` no longer borrows the alarm indefinitely (#2586)
|
- `systimer::etm::Event` no longer borrows the alarm indefinitely (#2586)
|
||||||
- A number of public enums and structs in the I2C, SPI, and UART drivers have been marked with `#[non_exhaustive]` (#2614)
|
- A number of public enums and structs in the I2C, SPI, and UART drivers have been marked with `#[non_exhaustive]` (#2614)
|
||||||
|
- Interrupt handling related functions are only provided for Blocking UART. (#2610)
|
||||||
|
- Changed how `Spi`, (split or unsplit) `Uart`, `LpUart`, `I8080`, `Camera`, `DPI` and `I2C` drivers are constructed (#2610)
|
||||||
|
- I8080, camera, DPI: The various standalone configuration options have been merged into `Config` (#2610)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
@ -58,7 +62,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- `FrozenUnit`, `AnyUnit`, `SpecificUnit`, `SpecificComparator`, `AnyComparator` have been removed from `systimer` (#2576)
|
- `FrozenUnit`, `AnyUnit`, `SpecificUnit`, `SpecificComparator`, `AnyComparator` have been removed from `systimer` (#2576)
|
||||||
- `esp_hal::psram::psram_range` (#2546)
|
- `esp_hal::psram::psram_range` (#2546)
|
||||||
- The `Dma` structure has been removed. (#2545)
|
- The `Dma` structure has been removed. (#2545)
|
||||||
- Remove `embedded-hal 0.2.x` impls and deps from `esp-hal` (#2593)
|
- Removed `embedded-hal 0.2.x` impls and deps from `esp-hal` (#2593)
|
||||||
|
- Removed `Camera::set_` functions (#2610)
|
||||||
|
|
||||||
## [0.22.0] - 2024-11-20
|
## [0.22.0] - 2024-11-20
|
||||||
|
|
||||||
|
|||||||
@ -188,7 +188,7 @@ is enabled. To retrieve the address and size of the initialized external memory,
|
|||||||
The usage of `esp_alloc::psram_allocator!` remains unchanged.
|
The usage of `esp_alloc::psram_allocator!` remains unchanged.
|
||||||
|
|
||||||
|
|
||||||
### embedded-hal 0.2.* is not supported anymore.
|
## embedded-hal 0.2.* is not supported anymore.
|
||||||
|
|
||||||
As per https://github.com/rust-embedded/embedded-hal/pull/640, our driver no longer implements traits from `embedded-hal 0.2.x`.
|
As per https://github.com/rust-embedded/embedded-hal/pull/640, our driver no longer implements traits from `embedded-hal 0.2.x`.
|
||||||
Analogs of all traits from the above mentioned version are available in `embedded-hal 1.x.x`
|
Analogs of all traits from the above mentioned version are available in `embedded-hal 1.x.x`
|
||||||
@ -221,3 +221,49 @@ https://github.com/rust-embedded/embedded-hal/blob/master/docs/migrating-from-0.
|
|||||||
+ use esp_hal::interrupt::InterruptConfigurable;
|
+ use esp_hal::interrupt::InterruptConfigurable;
|
||||||
+ use esp_hal::interrupt::DEFAULT_INTERRUPT_HANDLER;
|
+ use esp_hal::interrupt::DEFAULT_INTERRUPT_HANDLER;
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Driver constructors now take a configuration and are fallible
|
||||||
|
|
||||||
|
The old `new_with_config` constructor have been removed, and `new` constructors now always take
|
||||||
|
a configuration structure. They have also been updated to return a `ConfigError` if the configuration
|
||||||
|
is not compatible with the hardware.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
-let mut spi = Spi::new_with_config(
|
||||||
|
+let mut spi = Spi::new(
|
||||||
|
peripherals.SPI2,
|
||||||
|
Config {
|
||||||
|
frequency: 100.kHz(),
|
||||||
|
mode: SpiMode::Mode0,
|
||||||
|
..Config::default()
|
||||||
|
},
|
||||||
|
-);
|
||||||
|
+)
|
||||||
|
+.unwrap();
|
||||||
|
```
|
||||||
|
|
||||||
|
```diff
|
||||||
|
let mut spi = Spi::new(
|
||||||
|
peripherals.SPI2,
|
||||||
|
+ Config::default(),
|
||||||
|
-);
|
||||||
|
+)
|
||||||
|
+.unwrap();
|
||||||
|
```
|
||||||
|
|
||||||
|
### LCD_CAM configuration changes
|
||||||
|
|
||||||
|
- `cam` now has a `Config` strurct that contains frequency, bit/byte order, VSync filter options.
|
||||||
|
- DPI, I8080: `frequency` has been moved into `Config`.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
+let mut cam_config = cam::Config::default();
|
||||||
|
+cam_config.frequency = 1u32.MHz();
|
||||||
|
cam::Camera::new(
|
||||||
|
lcd_cam.cam,
|
||||||
|
dma_rx_channel,
|
||||||
|
pins,
|
||||||
|
- 1u32.MHz(),
|
||||||
|
+ cam_config,
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|||||||
@ -26,10 +26,11 @@
|
|||||||
//! let mosi = peripherals.GPIO4;
|
//! let mosi = peripherals.GPIO4;
|
||||||
//! let cs = peripherals.GPIO5;
|
//! let cs = peripherals.GPIO5;
|
||||||
//!
|
//!
|
||||||
//! let mut spi = Spi::new_with_config(
|
//! let mut spi = Spi::new(
|
||||||
//! peripherals.SPI2,
|
//! peripherals.SPI2,
|
||||||
//! Config::default().with_frequency(100.kHz()).with_mode(SpiMode::Mode0)
|
//! Config::default().with_frequency(100.kHz()).with_mode(SpiMode::Mode0)
|
||||||
//! )
|
//! )
|
||||||
|
//! .unwrap()
|
||||||
//! .with_sck(sclk)
|
//! .with_sck(sclk)
|
||||||
//! .with_mosi(mosi)
|
//! .with_mosi(mosi)
|
||||||
//! .with_miso(miso)
|
//! .with_miso(miso)
|
||||||
@ -1688,10 +1689,11 @@ impl<DEG: DmaChannel> DmaChannelConvert<DEG> for DEG {
|
|||||||
#[cfg_attr(pdma, doc = "let dma_channel = peripherals.DMA_SPI2;")]
|
#[cfg_attr(pdma, doc = "let dma_channel = peripherals.DMA_SPI2;")]
|
||||||
#[cfg_attr(gdma, doc = "let dma_channel = peripherals.DMA_CH0;")]
|
#[cfg_attr(gdma, doc = "let dma_channel = peripherals.DMA_CH0;")]
|
||||||
#[doc = ""]
|
#[doc = ""]
|
||||||
/// let spi = Spi::new_with_config(
|
/// let spi = Spi::new(
|
||||||
/// peripherals.SPI2,
|
/// peripherals.SPI2,
|
||||||
/// Config::default(),
|
/// Config::default(),
|
||||||
/// );
|
/// )
|
||||||
|
/// .unwrap();
|
||||||
///
|
///
|
||||||
/// let spi_dma = configures_spi_dma(spi, dma_channel);
|
/// let spi_dma = configures_spi_dma(spi, dma_channel);
|
||||||
/// # }
|
/// # }
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
//! peripherals.I2C0,
|
//! peripherals.I2C0,
|
||||||
//! Config::default(),
|
//! Config::default(),
|
||||||
//! )
|
//! )
|
||||||
|
//! .unwrap()
|
||||||
//! .with_sda(peripherals.GPIO1)
|
//! .with_sda(peripherals.GPIO1)
|
||||||
//! .with_scl(peripherals.GPIO2);
|
//! .with_scl(peripherals.GPIO2);
|
||||||
//!
|
//!
|
||||||
@ -421,7 +422,10 @@ impl<'d> I2c<'d, Blocking> {
|
|||||||
/// Create a new I2C instance
|
/// Create a new I2C instance
|
||||||
/// This will enable the peripheral but the peripheral won't get
|
/// This will enable the peripheral but the peripheral won't get
|
||||||
/// automatically disabled when this gets dropped.
|
/// automatically disabled when this gets dropped.
|
||||||
pub fn new(i2c: impl Peripheral<P = impl Instance> + 'd, config: Config) -> Self {
|
pub fn new(
|
||||||
|
i2c: impl Peripheral<P = impl Instance> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Result<Self, ConfigError> {
|
||||||
Self::new_typed(i2c.map_into(), config)
|
Self::new_typed(i2c.map_into(), config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -433,7 +437,10 @@ where
|
|||||||
/// Create a new I2C instance
|
/// Create a new I2C instance
|
||||||
/// This will enable the peripheral but the peripheral won't get
|
/// This will enable the peripheral but the peripheral won't get
|
||||||
/// automatically disabled when this gets dropped.
|
/// automatically disabled when this gets dropped.
|
||||||
pub fn new_typed(i2c: impl Peripheral<P = T> + 'd, config: Config) -> Self {
|
pub fn new_typed(
|
||||||
|
i2c: impl Peripheral<P = T> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Result<Self, ConfigError> {
|
||||||
crate::into_ref!(i2c);
|
crate::into_ref!(i2c);
|
||||||
|
|
||||||
let guard = PeripheralGuard::new(i2c.info().peripheral);
|
let guard = PeripheralGuard::new(i2c.info().peripheral);
|
||||||
@ -445,8 +452,9 @@ where
|
|||||||
guard,
|
guard,
|
||||||
};
|
};
|
||||||
|
|
||||||
unwrap!(i2c.driver().setup(&i2c.config));
|
i2c.driver().setup(&i2c.config)?;
|
||||||
i2c
|
|
||||||
|
Ok(i2c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: missing interrupt APIs
|
// TODO: missing interrupt APIs
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
//! master mode.
|
//! master mode.
|
||||||
//! ```rust, no_run
|
//! ```rust, no_run
|
||||||
#![doc = crate::before_snippet!()]
|
#![doc = crate::before_snippet!()]
|
||||||
//! # use esp_hal::lcd_cam::{cam::{Camera, RxEightBits}, LcdCam};
|
//! # use esp_hal::lcd_cam::{cam::{Camera, Config, RxEightBits}, LcdCam};
|
||||||
//! # use fugit::RateExtU32;
|
//! # use fugit::RateExtU32;
|
||||||
//! # use esp_hal::dma_rx_stream_buffer;
|
//! # use esp_hal::dma_rx_stream_buffer;
|
||||||
//!
|
//!
|
||||||
@ -37,15 +37,18 @@
|
|||||||
//! peripherals.GPIO16,
|
//! peripherals.GPIO16,
|
||||||
//! );
|
//! );
|
||||||
//!
|
//!
|
||||||
|
//! let mut config = Config::default();
|
||||||
|
//! config.frequency = 20.MHz();
|
||||||
|
//!
|
||||||
//! let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
|
//! let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
|
||||||
//! let mut camera = Camera::new(
|
//! let mut camera = Camera::new(
|
||||||
//! lcd_cam.cam,
|
//! lcd_cam.cam,
|
||||||
//! peripherals.DMA_CH0,
|
//! peripherals.DMA_CH0,
|
||||||
//! data_pins,
|
//! data_pins,
|
||||||
//! 20u32.MHz(),
|
//! config,
|
||||||
//! )
|
//! )
|
||||||
//! // Remove this for slave mode.
|
//! .unwrap()
|
||||||
//! .with_master_clock(mclk_pin)
|
//! .with_master_clock(mclk_pin) // Remove this for slave mode
|
||||||
//! .with_pixel_clock(pclk_pin)
|
//! .with_pixel_clock(pclk_pin)
|
||||||
//! .with_ctrl_pins(vsync_pin, href_pin);
|
//! .with_ctrl_pins(vsync_pin, href_pin);
|
||||||
//!
|
//!
|
||||||
@ -59,7 +62,7 @@ use core::{
|
|||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use fugit::HertzU32;
|
use fugit::{HertzU32, RateExtU32};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
clock::Clocks,
|
clock::Clocks,
|
||||||
@ -70,7 +73,7 @@ use crate::{
|
|||||||
OutputSignal,
|
OutputSignal,
|
||||||
Pull,
|
Pull,
|
||||||
},
|
},
|
||||||
lcd_cam::{calculate_clkm, BitOrder, ByteOrder},
|
lcd_cam::{calculate_clkm, BitOrder, ByteOrder, ClockError},
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::LCD_CAM,
|
peripherals::LCD_CAM,
|
||||||
system::{self, GenericPeripheralGuard},
|
system::{self, GenericPeripheralGuard},
|
||||||
@ -109,6 +112,14 @@ pub enum VsyncFilterThreshold {
|
|||||||
Eight,
|
Eight,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Vsync Filter Threshold
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum ConfigError {
|
||||||
|
/// The frequency is out of range.
|
||||||
|
Clock(ClockError),
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents the camera interface.
|
/// Represents the camera interface.
|
||||||
pub struct Cam<'d> {
|
pub struct Cam<'d> {
|
||||||
/// The LCD_CAM peripheral reference for managing the camera functionality.
|
/// The LCD_CAM peripheral reference for managing the camera functionality.
|
||||||
@ -129,109 +140,86 @@ impl<'d> Camera<'d> {
|
|||||||
cam: Cam<'d>,
|
cam: Cam<'d>,
|
||||||
channel: impl Peripheral<P = CH> + 'd,
|
channel: impl Peripheral<P = CH> + 'd,
|
||||||
_pins: P,
|
_pins: P,
|
||||||
frequency: HertzU32,
|
config: Config,
|
||||||
) -> Self
|
) -> Result<Self, ConfigError>
|
||||||
where
|
where
|
||||||
CH: RxChannelFor<LCD_CAM>,
|
CH: RxChannelFor<LCD_CAM>,
|
||||||
P: RxPins,
|
P: RxPins,
|
||||||
{
|
{
|
||||||
let rx_channel = ChannelRx::new(channel.map(|ch| ch.degrade()));
|
let rx_channel = ChannelRx::new(channel.map(|ch| ch.degrade()));
|
||||||
let lcd_cam = cam.lcd_cam;
|
|
||||||
|
|
||||||
|
let mut this = Self {
|
||||||
|
lcd_cam: cam.lcd_cam,
|
||||||
|
rx_channel,
|
||||||
|
_guard: cam._guard,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.lcd_cam
|
||||||
|
.cam_ctrl1()
|
||||||
|
.modify(|_, w| w.cam_2byte_en().bit(P::BUS_WIDTH == 2));
|
||||||
|
|
||||||
|
this.apply_config(&config)?;
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies the configuration to the camera interface.
|
||||||
|
pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
let clocks = Clocks::get();
|
let clocks = Clocks::get();
|
||||||
let (i, divider) = calculate_clkm(
|
let (i, divider) = calculate_clkm(
|
||||||
frequency.to_Hz() as _,
|
config.frequency.to_Hz() as _,
|
||||||
&[
|
&[
|
||||||
clocks.xtal_clock.to_Hz() as _,
|
clocks.xtal_clock.to_Hz() as _,
|
||||||
clocks.cpu_clock.to_Hz() as _,
|
clocks.cpu_clock.to_Hz() as _,
|
||||||
clocks.crypto_pwm_clock.to_Hz() as _,
|
clocks.crypto_pwm_clock.to_Hz() as _,
|
||||||
],
|
],
|
||||||
);
|
)
|
||||||
|
.map_err(ConfigError::Clock)?;
|
||||||
|
|
||||||
lcd_cam.cam_ctrl().write(|w| {
|
self.lcd_cam.cam_ctrl().write(|w| {
|
||||||
// Force enable the clock for all configuration registers.
|
// Force enable the clock for all configuration registers.
|
||||||
unsafe {
|
unsafe {
|
||||||
w.cam_clk_sel().bits((i + 1) as _);
|
w.cam_clk_sel().bits((i + 1) as _);
|
||||||
w.cam_clkm_div_num().bits(divider.div_num as _);
|
w.cam_clkm_div_num().bits(divider.div_num as _);
|
||||||
w.cam_clkm_div_b().bits(divider.div_b as _);
|
w.cam_clkm_div_b().bits(divider.div_b as _);
|
||||||
w.cam_clkm_div_a().bits(divider.div_a as _);
|
w.cam_clkm_div_a().bits(divider.div_a as _);
|
||||||
w.cam_vsync_filter_thres().bits(0);
|
if let Some(threshold) = config.vsync_filter_threshold {
|
||||||
|
w.cam_vsync_filter_thres().bits(threshold as _);
|
||||||
|
}
|
||||||
|
w.cam_byte_order()
|
||||||
|
.bit(config.byte_order != ByteOrder::default());
|
||||||
|
w.cam_bit_order()
|
||||||
|
.bit(config.bit_order != BitOrder::default());
|
||||||
w.cam_vs_eof_en().set_bit();
|
w.cam_vs_eof_en().set_bit();
|
||||||
w.cam_line_int_en().clear_bit();
|
w.cam_line_int_en().clear_bit();
|
||||||
w.cam_stop_en().clear_bit()
|
w.cam_stop_en().clear_bit()
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
lcd_cam.cam_ctrl1().write(|w| unsafe {
|
self.lcd_cam.cam_ctrl1().modify(|_, w| unsafe {
|
||||||
w.cam_vh_de_mode_en().set_bit();
|
w.cam_vh_de_mode_en().set_bit();
|
||||||
w.cam_rec_data_bytelen().bits(0);
|
w.cam_rec_data_bytelen().bits(0);
|
||||||
w.cam_line_int_num().bits(0);
|
w.cam_line_int_num().bits(0);
|
||||||
w.cam_vsync_filter_en().clear_bit();
|
w.cam_vsync_filter_en()
|
||||||
w.cam_2byte_en().bit(P::BUS_WIDTH == 2);
|
.bit(config.vsync_filter_threshold.is_some());
|
||||||
w.cam_clk_inv().clear_bit();
|
w.cam_clk_inv().clear_bit();
|
||||||
w.cam_de_inv().clear_bit();
|
w.cam_de_inv().clear_bit();
|
||||||
w.cam_hsync_inv().clear_bit();
|
w.cam_hsync_inv().clear_bit();
|
||||||
w.cam_vsync_inv().clear_bit()
|
w.cam_vsync_inv().clear_bit()
|
||||||
});
|
});
|
||||||
|
|
||||||
lcd_cam
|
self.lcd_cam
|
||||||
.cam_rgb_yuv()
|
.cam_rgb_yuv()
|
||||||
.write(|w| w.cam_conv_bypass().clear_bit());
|
.write(|w| w.cam_conv_bypass().clear_bit());
|
||||||
|
|
||||||
lcd_cam.cam_ctrl().modify(|_, w| w.cam_update().set_bit());
|
self.lcd_cam
|
||||||
|
.cam_ctrl()
|
||||||
|
.modify(|_, w| w.cam_update().set_bit());
|
||||||
|
|
||||||
Self {
|
Ok(())
|
||||||
lcd_cam,
|
|
||||||
rx_channel,
|
|
||||||
_guard: cam._guard,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d> Camera<'d> {
|
impl<'d> Camera<'d> {
|
||||||
/// Configures the byte order for the camera data.
|
|
||||||
pub fn set_byte_order(&mut self, byte_order: ByteOrder) -> &mut Self {
|
|
||||||
self.lcd_cam
|
|
||||||
.cam_ctrl()
|
|
||||||
.modify(|_, w| w.cam_byte_order().bit(byte_order != ByteOrder::default()));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Configures the bit order for the camera data.
|
|
||||||
pub fn set_bit_order(&mut self, bit_order: BitOrder) -> &mut Self {
|
|
||||||
self.lcd_cam
|
|
||||||
.cam_ctrl()
|
|
||||||
.modify(|_, w| w.cam_bit_order().bit(bit_order != BitOrder::default()));
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Configures the VSYNC filter threshold.
|
|
||||||
pub fn set_vsync_filter(&mut self, threshold: Option<VsyncFilterThreshold>) -> &mut Self {
|
|
||||||
if let Some(threshold) = threshold {
|
|
||||||
let value = match threshold {
|
|
||||||
VsyncFilterThreshold::One => 0,
|
|
||||||
VsyncFilterThreshold::Two => 1,
|
|
||||||
VsyncFilterThreshold::Three => 2,
|
|
||||||
VsyncFilterThreshold::Four => 3,
|
|
||||||
VsyncFilterThreshold::Five => 4,
|
|
||||||
VsyncFilterThreshold::Six => 5,
|
|
||||||
VsyncFilterThreshold::Seven => 6,
|
|
||||||
VsyncFilterThreshold::Eight => 7,
|
|
||||||
};
|
|
||||||
|
|
||||||
self.lcd_cam
|
|
||||||
.cam_ctrl()
|
|
||||||
.modify(|_, w| unsafe { w.cam_vsync_filter_thres().bits(value) });
|
|
||||||
self.lcd_cam
|
|
||||||
.cam_ctrl1()
|
|
||||||
.modify(|_, w| w.cam_vsync_filter_en().set_bit());
|
|
||||||
} else {
|
|
||||||
self.lcd_cam
|
|
||||||
.cam_ctrl1()
|
|
||||||
.modify(|_, w| w.cam_vsync_filter_en().clear_bit());
|
|
||||||
}
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Configures the master clock (MCLK) pin for the camera interface.
|
/// Configures the master clock (MCLK) pin for the camera interface.
|
||||||
pub fn with_master_clock<MCLK: PeripheralOutput>(
|
pub fn with_master_clock<MCLK: PeripheralOutput>(
|
||||||
self,
|
self,
|
||||||
@ -605,3 +593,31 @@ impl RxPins for RxSixteenBits {
|
|||||||
pub trait RxPins {
|
pub trait RxPins {
|
||||||
const BUS_WIDTH: usize;
|
const BUS_WIDTH: usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
/// Configuration settings for the Camera interface.
|
||||||
|
pub struct Config {
|
||||||
|
/// The pixel clock frequency for the camera interface.
|
||||||
|
pub frequency: HertzU32,
|
||||||
|
|
||||||
|
/// The byte order for the camera data.
|
||||||
|
pub byte_order: ByteOrder,
|
||||||
|
|
||||||
|
/// The bit order for the camera data.
|
||||||
|
pub bit_order: BitOrder,
|
||||||
|
|
||||||
|
/// The Vsync filter threshold.
|
||||||
|
pub vsync_filter_threshold: Option<VsyncFilterThreshold>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
frequency: 20.MHz(),
|
||||||
|
byte_order: Default::default(),
|
||||||
|
bit_order: Default::default(),
|
||||||
|
vsync_filter_threshold: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
//! let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
|
//! let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
|
||||||
//!
|
//!
|
||||||
//! let mut config = dpi::Config::default();
|
//! let mut config = dpi::Config::default();
|
||||||
|
//! config.frequency = 1.MHz();
|
||||||
//! config.clock_mode = ClockMode {
|
//! config.clock_mode = ClockMode {
|
||||||
//! polarity: Polarity::IdleLow,
|
//! polarity: Polarity::IdleLow,
|
||||||
//! phase: Phase::ShiftLow,
|
//! phase: Phase::ShiftLow,
|
||||||
@ -58,7 +59,7 @@
|
|||||||
//! config.de_idle_level = Level::Low;
|
//! config.de_idle_level = Level::Low;
|
||||||
//! config.disable_black_region = false;
|
//! config.disable_black_region = false;
|
||||||
//!
|
//!
|
||||||
//! let mut dpi = Dpi::new(lcd_cam.lcd, channel, 1.MHz(), config)
|
//! let mut dpi = Dpi::new(lcd_cam.lcd, channel, config).unwrap()
|
||||||
//! .with_vsync(peripherals.GPIO3)
|
//! .with_vsync(peripherals.GPIO3)
|
||||||
//! .with_hsync(peripherals.GPIO46)
|
//! .with_hsync(peripherals.GPIO46)
|
||||||
//! .with_de(peripherals.GPIO17)
|
//! .with_de(peripherals.GPIO17)
|
||||||
@ -99,7 +100,7 @@ use core::{
|
|||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use fugit::HertzU32;
|
use fugit::{HertzU32, RateExtU32};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
clock::Clocks,
|
clock::Clocks,
|
||||||
@ -110,6 +111,7 @@ use crate::{
|
|||||||
lcd::{ClockMode, DelayMode, Lcd, Phase, Polarity},
|
lcd::{ClockMode, DelayMode, Lcd, Phase, Polarity},
|
||||||
BitOrder,
|
BitOrder,
|
||||||
ByteOrder,
|
ByteOrder,
|
||||||
|
ClockError,
|
||||||
},
|
},
|
||||||
peripheral::{Peripheral, PeripheralRef},
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
peripherals::LCD_CAM,
|
peripherals::LCD_CAM,
|
||||||
@ -117,6 +119,14 @@ use crate::{
|
|||||||
Mode,
|
Mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Errors that can occur when configuring the DPI peripheral.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum ConfigError {
|
||||||
|
/// Clock configuration error.
|
||||||
|
Clock(ClockError),
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents the RGB LCD interface.
|
/// Represents the RGB LCD interface.
|
||||||
pub struct Dpi<'d, DM: Mode> {
|
pub struct Dpi<'d, DM: Mode> {
|
||||||
lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
||||||
@ -132,29 +142,41 @@ where
|
|||||||
pub fn new<CH>(
|
pub fn new<CH>(
|
||||||
lcd: Lcd<'d, DM>,
|
lcd: Lcd<'d, DM>,
|
||||||
channel: impl Peripheral<P = CH> + 'd,
|
channel: impl Peripheral<P = CH> + 'd,
|
||||||
frequency: HertzU32,
|
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self
|
) -> Result<Self, ConfigError>
|
||||||
where
|
where
|
||||||
CH: TxChannelFor<LCD_CAM>,
|
CH: TxChannelFor<LCD_CAM>,
|
||||||
{
|
{
|
||||||
let tx_channel = ChannelTx::new(channel.map(|ch| ch.degrade()));
|
let tx_channel = ChannelTx::new(channel.map(|ch| ch.degrade()));
|
||||||
let lcd_cam = lcd.lcd_cam;
|
|
||||||
|
|
||||||
|
let mut this = Self {
|
||||||
|
lcd_cam: lcd.lcd_cam,
|
||||||
|
tx_channel,
|
||||||
|
_mode: PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.apply_config(&config)?;
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies the configuration to the peripheral.
|
||||||
|
pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
let clocks = Clocks::get();
|
let clocks = Clocks::get();
|
||||||
// Due to https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_en.pdf
|
// Due to https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_en.pdf
|
||||||
// the LCD_PCLK divider must be at least 2. To make up for this the user
|
// the LCD_PCLK divider must be at least 2. To make up for this the user
|
||||||
// provided frequency is doubled to match.
|
// provided frequency is doubled to match.
|
||||||
let (i, divider) = calculate_clkm(
|
let (i, divider) = calculate_clkm(
|
||||||
(frequency.to_Hz() * 2) as _,
|
(config.frequency.to_Hz() * 2) as _,
|
||||||
&[
|
&[
|
||||||
clocks.xtal_clock.to_Hz() as _,
|
clocks.xtal_clock.to_Hz() as _,
|
||||||
clocks.cpu_clock.to_Hz() as _,
|
clocks.cpu_clock.to_Hz() as _,
|
||||||
clocks.crypto_pwm_clock.to_Hz() as _,
|
clocks.crypto_pwm_clock.to_Hz() as _,
|
||||||
],
|
],
|
||||||
);
|
)
|
||||||
|
.map_err(ConfigError::Clock)?;
|
||||||
|
|
||||||
lcd_cam.lcd_clock().write(|w| unsafe {
|
self.lcd_cam.lcd_clock().write(|w| unsafe {
|
||||||
// Force enable the clock for all configuration registers.
|
// Force enable the clock for all configuration registers.
|
||||||
w.clk_en().set_bit();
|
w.clk_en().set_bit();
|
||||||
w.lcd_clk_sel().bits((i + 1) as _);
|
w.lcd_clk_sel().bits((i + 1) as _);
|
||||||
@ -168,13 +190,15 @@ where
|
|||||||
w.lcd_ck_out_edge()
|
w.lcd_ck_out_edge()
|
||||||
.bit(config.clock_mode.phase == Phase::ShiftHigh)
|
.bit(config.clock_mode.phase == Phase::ShiftHigh)
|
||||||
});
|
});
|
||||||
lcd_cam.lcd_user().modify(|_, w| w.lcd_reset().set_bit());
|
self.lcd_cam
|
||||||
|
.lcd_user()
|
||||||
|
.modify(|_, w| w.lcd_reset().set_bit());
|
||||||
|
|
||||||
lcd_cam
|
self.lcd_cam
|
||||||
.lcd_rgb_yuv()
|
.lcd_rgb_yuv()
|
||||||
.write(|w| w.lcd_conv_bypass().clear_bit());
|
.write(|w| w.lcd_conv_bypass().clear_bit());
|
||||||
|
|
||||||
lcd_cam.lcd_user().modify(|_, w| {
|
self.lcd_cam.lcd_user().modify(|_, w| {
|
||||||
if config.format.enable_2byte_mode {
|
if config.format.enable_2byte_mode {
|
||||||
w.lcd_8bits_order().bit(false);
|
w.lcd_8bits_order().bit(false);
|
||||||
w.lcd_byte_order()
|
w.lcd_byte_order()
|
||||||
@ -197,7 +221,7 @@ where
|
|||||||
});
|
});
|
||||||
|
|
||||||
let timing = &config.timing;
|
let timing = &config.timing;
|
||||||
lcd_cam.lcd_ctrl().modify(|_, w| unsafe {
|
self.lcd_cam.lcd_ctrl().modify(|_, w| unsafe {
|
||||||
// Enable RGB mode, and input VSYNC, HSYNC, and DE signals.
|
// Enable RGB mode, and input VSYNC, HSYNC, and DE signals.
|
||||||
w.lcd_rgb_mode_en().set_bit();
|
w.lcd_rgb_mode_en().set_bit();
|
||||||
|
|
||||||
@ -208,7 +232,7 @@ where
|
|||||||
w.lcd_vt_height()
|
w.lcd_vt_height()
|
||||||
.bits((timing.vertical_total_height as u16).saturating_sub(1))
|
.bits((timing.vertical_total_height as u16).saturating_sub(1))
|
||||||
});
|
});
|
||||||
lcd_cam.lcd_ctrl1().modify(|_, w| unsafe {
|
self.lcd_cam.lcd_ctrl1().modify(|_, w| unsafe {
|
||||||
w.lcd_vb_front()
|
w.lcd_vb_front()
|
||||||
.bits((timing.vertical_blank_front_porch as u8).saturating_sub(1));
|
.bits((timing.vertical_blank_front_porch as u8).saturating_sub(1));
|
||||||
w.lcd_ha_width()
|
w.lcd_ha_width()
|
||||||
@ -216,7 +240,7 @@ where
|
|||||||
w.lcd_ht_width()
|
w.lcd_ht_width()
|
||||||
.bits((timing.horizontal_total_width as u16).saturating_sub(1))
|
.bits((timing.horizontal_total_width as u16).saturating_sub(1))
|
||||||
});
|
});
|
||||||
lcd_cam.lcd_ctrl2().modify(|_, w| unsafe {
|
self.lcd_cam.lcd_ctrl2().modify(|_, w| unsafe {
|
||||||
w.lcd_vsync_width()
|
w.lcd_vsync_width()
|
||||||
.bits((timing.vsync_width as u8).saturating_sub(1));
|
.bits((timing.vsync_width as u8).saturating_sub(1));
|
||||||
w.lcd_vsync_idle_pol().bit(config.vsync_idle_level.into());
|
w.lcd_vsync_idle_pol().bit(config.vsync_idle_level.into());
|
||||||
@ -228,7 +252,7 @@ where
|
|||||||
w.lcd_hsync_position().bits(timing.hsync_position as u8)
|
w.lcd_hsync_position().bits(timing.hsync_position as u8)
|
||||||
});
|
});
|
||||||
|
|
||||||
lcd_cam.lcd_misc().modify(|_, w| unsafe {
|
self.lcd_cam.lcd_misc().modify(|_, w| unsafe {
|
||||||
// TODO: Find out what this field actually does.
|
// TODO: Find out what this field actually does.
|
||||||
// Set the threshold for Async Tx FIFO full event. (5 bits)
|
// Set the threshold for Async Tx FIFO full event. (5 bits)
|
||||||
w.lcd_afifo_threshold_num().bits((1 << 5) - 1);
|
w.lcd_afifo_threshold_num().bits((1 << 5) - 1);
|
||||||
@ -244,13 +268,13 @@ where
|
|||||||
// Enable blank region when LCD sends data out.
|
// Enable blank region when LCD sends data out.
|
||||||
w.lcd_bk_en().bit(!config.disable_black_region)
|
w.lcd_bk_en().bit(!config.disable_black_region)
|
||||||
});
|
});
|
||||||
lcd_cam.lcd_dly_mode().modify(|_, w| unsafe {
|
self.lcd_cam.lcd_dly_mode().modify(|_, w| unsafe {
|
||||||
w.lcd_de_mode().bits(config.de_mode as u8);
|
w.lcd_de_mode().bits(config.de_mode as u8);
|
||||||
w.lcd_hsync_mode().bits(config.hsync_mode as u8);
|
w.lcd_hsync_mode().bits(config.hsync_mode as u8);
|
||||||
w.lcd_vsync_mode().bits(config.vsync_mode as u8);
|
w.lcd_vsync_mode().bits(config.vsync_mode as u8);
|
||||||
w
|
w
|
||||||
});
|
});
|
||||||
lcd_cam.lcd_data_dout_mode().modify(|_, w| unsafe {
|
self.lcd_cam.lcd_data_dout_mode().modify(|_, w| unsafe {
|
||||||
w.dout0_mode().bits(config.output_bit_mode as u8);
|
w.dout0_mode().bits(config.output_bit_mode as u8);
|
||||||
w.dout1_mode().bits(config.output_bit_mode as u8);
|
w.dout1_mode().bits(config.output_bit_mode as u8);
|
||||||
w.dout2_mode().bits(config.output_bit_mode as u8);
|
w.dout2_mode().bits(config.output_bit_mode as u8);
|
||||||
@ -269,13 +293,11 @@ where
|
|||||||
w.dout15_mode().bits(config.output_bit_mode as u8)
|
w.dout15_mode().bits(config.output_bit_mode as u8)
|
||||||
});
|
});
|
||||||
|
|
||||||
lcd_cam.lcd_user().modify(|_, w| w.lcd_update().set_bit());
|
self.lcd_cam
|
||||||
|
.lcd_user()
|
||||||
|
.modify(|_, w| w.lcd_update().set_bit());
|
||||||
|
|
||||||
Self {
|
Ok(())
|
||||||
lcd_cam,
|
|
||||||
tx_channel,
|
|
||||||
_mode: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assign the VSYNC pin for the LCD_CAM.
|
/// Assign the VSYNC pin for the LCD_CAM.
|
||||||
@ -675,6 +697,9 @@ pub struct Config {
|
|||||||
/// Specifies the clock mode, including polarity and phase settings.
|
/// Specifies the clock mode, including polarity and phase settings.
|
||||||
pub clock_mode: ClockMode,
|
pub clock_mode: ClockMode,
|
||||||
|
|
||||||
|
/// The frequency of the pixel clock.
|
||||||
|
pub frequency: HertzU32,
|
||||||
|
|
||||||
/// Format of the byte data sent out.
|
/// Format of the byte data sent out.
|
||||||
pub format: Format,
|
pub format: Format,
|
||||||
|
|
||||||
@ -712,6 +737,7 @@ impl Default for Config {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Config {
|
Config {
|
||||||
clock_mode: Default::default(),
|
clock_mode: Default::default(),
|
||||||
|
frequency: 1.MHz(),
|
||||||
format: Default::default(),
|
format: Default::default(),
|
||||||
timing: Default::default(),
|
timing: Default::default(),
|
||||||
vsync_idle_level: Level::Low,
|
vsync_idle_level: Level::Low,
|
||||||
|
|||||||
@ -33,13 +33,16 @@
|
|||||||
//! );
|
//! );
|
||||||
//! let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
|
//! let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
|
||||||
//!
|
//!
|
||||||
|
//! let mut config = Config::default();
|
||||||
|
//! config.frequency = 20.MHz();
|
||||||
|
//!
|
||||||
//! let mut i8080 = I8080::new(
|
//! let mut i8080 = I8080::new(
|
||||||
//! lcd_cam.lcd,
|
//! lcd_cam.lcd,
|
||||||
//! peripherals.DMA_CH0,
|
//! peripherals.DMA_CH0,
|
||||||
//! tx_pins,
|
//! tx_pins,
|
||||||
//! 20.MHz(),
|
//! config,
|
||||||
//! Config::default(),
|
|
||||||
//! )
|
//! )
|
||||||
|
//! .unwrap()
|
||||||
//! .with_ctrl_pins(peripherals.GPIO0, peripherals.GPIO47);
|
//! .with_ctrl_pins(peripherals.GPIO0, peripherals.GPIO47);
|
||||||
//!
|
//!
|
||||||
//! dma_buf.fill(&[0x55]);
|
//! dma_buf.fill(&[0x55]);
|
||||||
@ -55,7 +58,7 @@ use core::{
|
|||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
|
|
||||||
use fugit::HertzU32;
|
use fugit::{HertzU32, RateExtU32};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
clock::Clocks,
|
clock::Clocks,
|
||||||
@ -69,6 +72,7 @@ use crate::{
|
|||||||
lcd::{ClockMode, DelayMode, Phase, Polarity},
|
lcd::{ClockMode, DelayMode, Phase, Polarity},
|
||||||
BitOrder,
|
BitOrder,
|
||||||
ByteOrder,
|
ByteOrder,
|
||||||
|
ClockError,
|
||||||
Instance,
|
Instance,
|
||||||
Lcd,
|
Lcd,
|
||||||
LCD_DONE_WAKER,
|
LCD_DONE_WAKER,
|
||||||
@ -79,6 +83,14 @@ use crate::{
|
|||||||
Mode,
|
Mode,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A configuration error.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum ConfigError {
|
||||||
|
/// Clock configuration error.
|
||||||
|
Clock(ClockError),
|
||||||
|
}
|
||||||
|
|
||||||
/// Represents the I8080 LCD interface.
|
/// Represents the I8080 LCD interface.
|
||||||
pub struct I8080<'d, DM: Mode> {
|
pub struct I8080<'d, DM: Mode> {
|
||||||
lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
||||||
@ -95,30 +107,43 @@ where
|
|||||||
lcd: Lcd<'d, DM>,
|
lcd: Lcd<'d, DM>,
|
||||||
channel: impl Peripheral<P = CH> + 'd,
|
channel: impl Peripheral<P = CH> + 'd,
|
||||||
mut pins: P,
|
mut pins: P,
|
||||||
frequency: HertzU32,
|
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Self
|
) -> Result<Self, ConfigError>
|
||||||
where
|
where
|
||||||
CH: TxChannelFor<LCD_CAM>,
|
CH: TxChannelFor<LCD_CAM>,
|
||||||
P: TxPins,
|
P: TxPins,
|
||||||
{
|
{
|
||||||
let tx_channel = ChannelTx::new(channel.map(|ch| ch.degrade()));
|
let tx_channel = ChannelTx::new(channel.map(|ch| ch.degrade()));
|
||||||
let lcd_cam = lcd.lcd_cam;
|
|
||||||
|
|
||||||
|
let mut this = Self {
|
||||||
|
lcd_cam: lcd.lcd_cam,
|
||||||
|
tx_channel,
|
||||||
|
_mode: PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.apply_config(&config)?;
|
||||||
|
pins.configure();
|
||||||
|
|
||||||
|
Ok(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Applies configuration.
|
||||||
|
pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
let clocks = Clocks::get();
|
let clocks = Clocks::get();
|
||||||
// Due to https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_en.pdf
|
// Due to https://www.espressif.com/sites/default/files/documentation/esp32-s3_errata_en.pdf
|
||||||
// the LCD_PCLK divider must be at least 2. To make up for this the user
|
// the LCD_PCLK divider must be at least 2. To make up for this the user
|
||||||
// provided frequency is doubled to match.
|
// provided frequency is doubled to match.
|
||||||
let (i, divider) = calculate_clkm(
|
let (i, divider) = calculate_clkm(
|
||||||
(frequency.to_Hz() * 2) as _,
|
(config.frequency.to_Hz() * 2) as _,
|
||||||
&[
|
&[
|
||||||
clocks.xtal_clock.to_Hz() as _,
|
clocks.xtal_clock.to_Hz() as _,
|
||||||
clocks.cpu_clock.to_Hz() as _,
|
clocks.cpu_clock.to_Hz() as _,
|
||||||
clocks.crypto_pwm_clock.to_Hz() as _,
|
clocks.crypto_pwm_clock.to_Hz() as _,
|
||||||
],
|
],
|
||||||
);
|
)
|
||||||
|
.map_err(ConfigError::Clock)?;
|
||||||
|
|
||||||
lcd_cam.lcd_clock().write(|w| unsafe {
|
self.lcd_cam.lcd_clock().write(|w| unsafe {
|
||||||
// Force enable the clock for all configuration registers.
|
// Force enable the clock for all configuration registers.
|
||||||
w.clk_en().set_bit();
|
w.clk_en().set_bit();
|
||||||
w.lcd_clk_sel().bits((i + 1) as _);
|
w.lcd_clk_sel().bits((i + 1) as _);
|
||||||
@ -133,20 +158,20 @@ where
|
|||||||
.bit(config.clock_mode.phase == Phase::ShiftHigh)
|
.bit(config.clock_mode.phase == Phase::ShiftHigh)
|
||||||
});
|
});
|
||||||
|
|
||||||
lcd_cam
|
self.lcd_cam
|
||||||
.lcd_ctrl()
|
.lcd_ctrl()
|
||||||
.write(|w| w.lcd_rgb_mode_en().clear_bit());
|
.write(|w| w.lcd_rgb_mode_en().clear_bit());
|
||||||
lcd_cam
|
self.lcd_cam
|
||||||
.lcd_rgb_yuv()
|
.lcd_rgb_yuv()
|
||||||
.write(|w| w.lcd_conv_bypass().clear_bit());
|
.write(|w| w.lcd_conv_bypass().clear_bit());
|
||||||
|
|
||||||
lcd_cam.lcd_user().modify(|_, w| {
|
self.lcd_cam.lcd_user().modify(|_, w| {
|
||||||
w.lcd_8bits_order().bit(false);
|
w.lcd_8bits_order().bit(false);
|
||||||
w.lcd_bit_order().bit(false);
|
w.lcd_bit_order().bit(false);
|
||||||
w.lcd_byte_order().bit(false);
|
w.lcd_byte_order().bit(false);
|
||||||
w.lcd_2byte_en().bit(false)
|
w.lcd_2byte_en().bit(false)
|
||||||
});
|
});
|
||||||
lcd_cam.lcd_misc().write(|w| unsafe {
|
self.lcd_cam.lcd_misc().write(|w| unsafe {
|
||||||
// Set the threshold for Async Tx FIFO full event. (5 bits)
|
// Set the threshold for Async Tx FIFO full event. (5 bits)
|
||||||
w.lcd_afifo_threshold_num().bits(0);
|
w.lcd_afifo_threshold_num().bits(0);
|
||||||
// Configure the setup cycles in LCD non-RGB mode. Setup cycles
|
// Configure the setup cycles in LCD non-RGB mode. Setup cycles
|
||||||
@ -177,10 +202,10 @@ where
|
|||||||
// The default value of LCD_CD
|
// The default value of LCD_CD
|
||||||
w.lcd_cd_idle_edge().bit(config.cd_idle_edge)
|
w.lcd_cd_idle_edge().bit(config.cd_idle_edge)
|
||||||
});
|
});
|
||||||
lcd_cam
|
self.lcd_cam
|
||||||
.lcd_dly_mode()
|
.lcd_dly_mode()
|
||||||
.write(|w| unsafe { w.lcd_cd_mode().bits(config.cd_mode as u8) });
|
.write(|w| unsafe { w.lcd_cd_mode().bits(config.cd_mode as u8) });
|
||||||
lcd_cam.lcd_data_dout_mode().write(|w| unsafe {
|
self.lcd_cam.lcd_data_dout_mode().write(|w| unsafe {
|
||||||
w.dout0_mode().bits(config.output_bit_mode as u8);
|
w.dout0_mode().bits(config.output_bit_mode as u8);
|
||||||
w.dout1_mode().bits(config.output_bit_mode as u8);
|
w.dout1_mode().bits(config.output_bit_mode as u8);
|
||||||
w.dout2_mode().bits(config.output_bit_mode as u8);
|
w.dout2_mode().bits(config.output_bit_mode as u8);
|
||||||
@ -199,15 +224,11 @@ where
|
|||||||
w.dout15_mode().bits(config.output_bit_mode as u8)
|
w.dout15_mode().bits(config.output_bit_mode as u8)
|
||||||
});
|
});
|
||||||
|
|
||||||
lcd_cam.lcd_user().modify(|_, w| w.lcd_update().set_bit());
|
self.lcd_cam
|
||||||
|
.lcd_user()
|
||||||
|
.modify(|_, w| w.lcd_update().set_bit());
|
||||||
|
|
||||||
pins.configure();
|
Ok(())
|
||||||
|
|
||||||
Self {
|
|
||||||
lcd_cam,
|
|
||||||
tx_channel,
|
|
||||||
_mode: PhantomData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Configures the byte order for data transmission in 16-bit mode.
|
/// Configures the byte order for data transmission in 16-bit mode.
|
||||||
@ -523,6 +544,9 @@ pub struct Config {
|
|||||||
/// Specifies the clock mode, including polarity and phase settings.
|
/// Specifies the clock mode, including polarity and phase settings.
|
||||||
pub clock_mode: ClockMode,
|
pub clock_mode: ClockMode,
|
||||||
|
|
||||||
|
/// The frequency of the pixel clock.
|
||||||
|
pub frequency: HertzU32,
|
||||||
|
|
||||||
/// Setup cycles expected, must be at least 1. (6 bits)
|
/// Setup cycles expected, must be at least 1. (6 bits)
|
||||||
pub setup_cycles: usize,
|
pub setup_cycles: usize,
|
||||||
|
|
||||||
@ -548,6 +572,7 @@ impl Default for Config {
|
|||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
clock_mode: Default::default(),
|
clock_mode: Default::default(),
|
||||||
|
frequency: 20.MHz(),
|
||||||
setup_cycles: 1,
|
setup_cycles: 1,
|
||||||
hold_cycles: 1,
|
hold_cycles: 1,
|
||||||
cd_idle_edge: false,
|
cd_idle_edge: false,
|
||||||
|
|||||||
@ -11,11 +11,7 @@
|
|||||||
//! - RGB is not supported yet
|
//! - RGB is not supported yet
|
||||||
|
|
||||||
use super::GenericPeripheralGuard;
|
use super::GenericPeripheralGuard;
|
||||||
use crate::{
|
use crate::{peripheral::PeripheralRef, peripherals::LCD_CAM, system};
|
||||||
peripheral::PeripheralRef,
|
|
||||||
peripherals::LCD_CAM,
|
|
||||||
system::{self},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub mod dpi;
|
pub mod dpi;
|
||||||
pub mod i8080;
|
pub mod i8080;
|
||||||
|
|||||||
@ -173,10 +173,18 @@ pub(crate) struct ClockDivider {
|
|||||||
pub div_a: usize,
|
pub div_a: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Clock configuration errors.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum ClockError {
|
||||||
|
/// Desired frequency was too low for the dividers to divide to
|
||||||
|
FrequencyTooLow,
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn calculate_clkm(
|
pub(crate) fn calculate_clkm(
|
||||||
desired_frequency: usize,
|
desired_frequency: usize,
|
||||||
source_frequencies: &[usize],
|
source_frequencies: &[usize],
|
||||||
) -> (usize, ClockDivider) {
|
) -> Result<(usize, ClockDivider), ClockError> {
|
||||||
let mut result_freq = 0;
|
let mut result_freq = 0;
|
||||||
let mut result = None;
|
let mut result = None;
|
||||||
|
|
||||||
@ -191,7 +199,7 @@ pub(crate) fn calculate_clkm(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result.expect("Desired frequency was too low for the dividers to divide to")
|
result.ok_or(ClockError::FrequencyTooLow)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_output_frequency(source_frequency: usize, divider: &ClockDivider) -> usize {
|
fn calculate_output_frequency(source_frequency: usize, divider: &ClockDivider) -> usize {
|
||||||
@ -257,15 +265,15 @@ fn calculate_closest_divider(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let target = div_fraction;
|
let target = div_fraction;
|
||||||
let closest = farey_sequence(63)
|
let closest = farey_sequence(63).find(|curr| {
|
||||||
.find(|curr| {
|
// https://en.wikipedia.org/wiki/Fraction#Adding_unlike_quantities
|
||||||
// https://en.wikipedia.org/wiki/Fraction#Adding_unlike_quantities
|
|
||||||
|
|
||||||
let new_curr_num = curr.numerator * target.denominator;
|
let new_curr_num = curr.numerator * target.denominator;
|
||||||
let new_target_num = target.numerator * curr.denominator;
|
let new_target_num = target.numerator * curr.denominator;
|
||||||
new_curr_num >= new_target_num
|
new_curr_num >= new_target_num
|
||||||
})
|
});
|
||||||
.expect("The fraction must be between 0 and 1");
|
|
||||||
|
let closest = unwrap!(closest, "The fraction must be between 0 and 1");
|
||||||
|
|
||||||
ClockDivider {
|
ClockDivider {
|
||||||
div_num,
|
div_num,
|
||||||
|
|||||||
@ -43,10 +43,11 @@
|
|||||||
//! let mosi = peripherals.GPIO1;
|
//! let mosi = peripherals.GPIO1;
|
||||||
//! let cs = peripherals.GPIO5;
|
//! let cs = peripherals.GPIO5;
|
||||||
//!
|
//!
|
||||||
//! let mut spi = Spi::new_with_config(
|
//! let mut spi = Spi::new(
|
||||||
//! peripherals.SPI2,
|
//! peripherals.SPI2,
|
||||||
//! Config::default().with_frequency(100.kHz()).with_mode(SpiMode::Mode0)
|
//! Config::default().with_frequency(100.kHz()).with_mode(SpiMode::Mode0)
|
||||||
//! )
|
//! )
|
||||||
|
//! .unwrap()
|
||||||
//! .with_sck(sclk)
|
//! .with_sck(sclk)
|
||||||
//! .with_mosi(mosi)
|
//! .with_mosi(mosi)
|
||||||
//! .with_miso(miso)
|
//! .with_miso(miso)
|
||||||
@ -503,16 +504,11 @@ where
|
|||||||
|
|
||||||
impl<'d> Spi<'d, Blocking> {
|
impl<'d> Spi<'d, Blocking> {
|
||||||
/// Constructs an SPI instance in 8bit dataframe mode.
|
/// Constructs an SPI instance in 8bit dataframe mode.
|
||||||
pub fn new(spi: impl Peripheral<P = impl Instance> + 'd) -> Spi<'d, Blocking> {
|
pub fn new(
|
||||||
Self::new_with_config(spi, Config::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constructs an SPI instance in 8bit dataframe mode.
|
|
||||||
pub fn new_with_config(
|
|
||||||
spi: impl Peripheral<P = impl Instance> + 'd,
|
spi: impl Peripheral<P = impl Instance> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Spi<'d, Blocking> {
|
) -> Result<Self, ConfigError> {
|
||||||
Self::new_typed_with_config(spi.map_into(), config)
|
Self::new_typed(spi.map_into(), config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts the SPI instance into async mode.
|
/// Converts the SPI instance into async mode.
|
||||||
@ -558,15 +554,10 @@ where
|
|||||||
T: Instance,
|
T: Instance,
|
||||||
{
|
{
|
||||||
/// Constructs an SPI instance in 8bit dataframe mode.
|
/// Constructs an SPI instance in 8bit dataframe mode.
|
||||||
pub fn new_typed(spi: impl Peripheral<P = T> + 'd) -> Spi<'d, M, T> {
|
pub fn new_typed(
|
||||||
Self::new_typed_with_config(spi, Config::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Constructs an SPI instance in 8bit dataframe mode.
|
|
||||||
pub fn new_typed_with_config(
|
|
||||||
spi: impl Peripheral<P = T> + 'd,
|
spi: impl Peripheral<P = T> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
) -> Spi<'d, M, T> {
|
) -> Result<Self, ConfigError> {
|
||||||
crate::into_ref!(spi);
|
crate::into_ref!(spi);
|
||||||
|
|
||||||
let guard = PeripheralGuard::new(spi.info().peripheral);
|
let guard = PeripheralGuard::new(spi.info().peripheral);
|
||||||
@ -578,7 +569,7 @@ where
|
|||||||
};
|
};
|
||||||
|
|
||||||
this.driver().init();
|
this.driver().init();
|
||||||
unwrap!(this.apply_config(&config)); // FIXME: update based on the resolution of https://github.com/esp-rs/esp-hal/issues/2416
|
this.apply_config(&config)?;
|
||||||
|
|
||||||
let this = this
|
let this = this
|
||||||
.with_mosi(NoPin)
|
.with_mosi(NoPin)
|
||||||
@ -594,7 +585,7 @@ where
|
|||||||
unwrap!(this.driver().sio3_output).connect_to(NoPin);
|
unwrap!(this.driver().sio3_output).connect_to(NoPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
this
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assign the MOSI (Master Out Slave In) pin for the SPI instance.
|
/// Assign the MOSI (Master Out Slave In) pin for the SPI instance.
|
||||||
|
|||||||
@ -22,10 +22,11 @@
|
|||||||
//!
|
//!
|
||||||
//! ```rust, no_run
|
//! ```rust, no_run
|
||||||
#![doc = crate::before_snippet!()]
|
#![doc = crate::before_snippet!()]
|
||||||
//! # use esp_hal::uart::Uart;
|
//! # use esp_hal::uart::{Config, Uart};
|
||||||
//!
|
//!
|
||||||
//! let mut uart1 = Uart::new(
|
//! let mut uart1 = Uart::new(
|
||||||
//! peripherals.UART1,
|
//! peripherals.UART1,
|
||||||
|
//! Config::default(),
|
||||||
//! peripherals.GPIO1,
|
//! peripherals.GPIO1,
|
||||||
//! peripherals.GPIO2,
|
//! peripherals.GPIO2,
|
||||||
//! ).unwrap();
|
//! ).unwrap();
|
||||||
@ -53,7 +54,7 @@
|
|||||||
//! ```rust, no_run
|
//! ```rust, no_run
|
||||||
#![doc = crate::before_snippet!()]
|
#![doc = crate::before_snippet!()]
|
||||||
//! # use esp_hal::uart::{Config, Uart};
|
//! # use esp_hal::uart::{Config, Uart};
|
||||||
//! # let mut uart1 = Uart::new_with_config(
|
//! # let mut uart1 = Uart::new(
|
||||||
//! # peripherals.UART1,
|
//! # peripherals.UART1,
|
||||||
//! # Config::default(),
|
//! # Config::default(),
|
||||||
//! # peripherals.GPIO1,
|
//! # peripherals.GPIO1,
|
||||||
@ -68,7 +69,7 @@
|
|||||||
//! ```rust, no_run
|
//! ```rust, no_run
|
||||||
#![doc = crate::before_snippet!()]
|
#![doc = crate::before_snippet!()]
|
||||||
//! # use esp_hal::uart::{Config, Uart};
|
//! # use esp_hal::uart::{Config, Uart};
|
||||||
//! # let mut uart1 = Uart::new_with_config(
|
//! # let mut uart1 = Uart::new(
|
||||||
//! # peripherals.UART1,
|
//! # peripherals.UART1,
|
||||||
//! # Config::default(),
|
//! # Config::default(),
|
||||||
//! # peripherals.GPIO1,
|
//! # peripherals.GPIO1,
|
||||||
@ -86,12 +87,13 @@
|
|||||||
//! ### Inverting RX and TX Pins
|
//! ### Inverting RX and TX Pins
|
||||||
//! ```rust, no_run
|
//! ```rust, no_run
|
||||||
#![doc = crate::before_snippet!()]
|
#![doc = crate::before_snippet!()]
|
||||||
//! # use esp_hal::uart::Uart;
|
//! # use esp_hal::uart::{Config, Uart};
|
||||||
//!
|
//!
|
||||||
//! let (rx, _) = peripherals.GPIO2.split();
|
//! let (rx, _) = peripherals.GPIO2.split();
|
||||||
//! let (_, tx) = peripherals.GPIO1.split();
|
//! let (_, tx) = peripherals.GPIO1.split();
|
||||||
//! let mut uart1 = Uart::new(
|
//! let mut uart1 = Uart::new(
|
||||||
//! peripherals.UART1,
|
//! peripherals.UART1,
|
||||||
|
//! Config::default(),
|
||||||
//! rx.inverted(),
|
//! rx.inverted(),
|
||||||
//! tx.inverted(),
|
//! tx.inverted(),
|
||||||
//! ).unwrap();
|
//! ).unwrap();
|
||||||
@ -101,10 +103,18 @@
|
|||||||
//! ### Constructing RX and TX Components
|
//! ### Constructing RX and TX Components
|
||||||
//! ```rust, no_run
|
//! ```rust, no_run
|
||||||
#![doc = crate::before_snippet!()]
|
#![doc = crate::before_snippet!()]
|
||||||
//! # use esp_hal::uart::{UartTx, UartRx};
|
//! # use esp_hal::uart::{Config, UartTx, UartRx};
|
||||||
//!
|
//!
|
||||||
//! let tx = UartTx::new(peripherals.UART0, peripherals.GPIO1).unwrap();
|
//! let tx = UartTx::new(
|
||||||
//! let rx = UartRx::new(peripherals.UART1, peripherals.GPIO2).unwrap();
|
//! peripherals.UART0,
|
||||||
|
//! Config::default(),
|
||||||
|
//! peripherals.GPIO1,
|
||||||
|
//! ).unwrap();
|
||||||
|
//! let rx = UartRx::new(
|
||||||
|
//! peripherals.UART1,
|
||||||
|
//! Config::default(),
|
||||||
|
//! peripherals.GPIO2,
|
||||||
|
//! ).unwrap();
|
||||||
//! # }
|
//! # }
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
@ -145,7 +155,7 @@
|
|||||||
)]
|
)]
|
||||||
//! let config = Config::default().rx_fifo_full_threshold(30);
|
//! let config = Config::default().rx_fifo_full_threshold(30);
|
||||||
//!
|
//!
|
||||||
//! let mut uart0 = Uart::new_with_config(
|
//! let mut uart0 = Uart::new(
|
||||||
//! peripherals.UART0,
|
//! peripherals.UART0,
|
||||||
//! config,
|
//! config,
|
||||||
//! tx_pin,
|
//! tx_pin,
|
||||||
@ -560,7 +570,7 @@ where
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(self, config: Config) -> Result<Uart<'d, M, T>, Error> {
|
fn init(self, config: Config) -> Result<Uart<'d, M, T>, ConfigError> {
|
||||||
let rx_guard = PeripheralGuard::new(self.uart.parts().0.peripheral);
|
let rx_guard = PeripheralGuard::new(self.uart.parts().0.peripheral);
|
||||||
let tx_guard = PeripheralGuard::new(self.uart.parts().0.peripheral);
|
let tx_guard = PeripheralGuard::new(self.uart.parts().0.peripheral);
|
||||||
|
|
||||||
@ -602,13 +612,23 @@ pub struct UartRx<'d, M, T = AnyUart> {
|
|||||||
guard: PeripheralGuard,
|
guard: PeripheralGuard,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A configuration error.
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
pub enum ConfigError {
|
||||||
|
/// The requested timeout is not supported.
|
||||||
|
UnsupportedTimeout,
|
||||||
|
/// The requested fifo threshold is not supported.
|
||||||
|
UnsupportedFifoThreshold,
|
||||||
|
}
|
||||||
|
|
||||||
impl<M, T> SetConfig for Uart<'_, M, T>
|
impl<M, T> SetConfig for Uart<'_, M, T>
|
||||||
where
|
where
|
||||||
T: Instance,
|
T: Instance,
|
||||||
M: Mode,
|
M: Mode,
|
||||||
{
|
{
|
||||||
type Config = Config;
|
type Config = Config;
|
||||||
type ConfigError = Error;
|
type ConfigError = ConfigError;
|
||||||
|
|
||||||
fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
|
fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
|
||||||
self.apply_config(config)
|
self.apply_config(config)
|
||||||
@ -621,7 +641,7 @@ where
|
|||||||
M: Mode,
|
M: Mode,
|
||||||
{
|
{
|
||||||
type Config = Config;
|
type Config = Config;
|
||||||
type ConfigError = Error;
|
type ConfigError = ConfigError;
|
||||||
|
|
||||||
fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
|
fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
|
||||||
self.apply_config(config)
|
self.apply_config(config)
|
||||||
@ -634,7 +654,7 @@ where
|
|||||||
M: Mode,
|
M: Mode,
|
||||||
{
|
{
|
||||||
type Config = Config;
|
type Config = Config;
|
||||||
type ConfigError = Error;
|
type ConfigError = ConfigError;
|
||||||
|
|
||||||
fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
|
fn set_config(&mut self, config: &Self::Config) -> Result<(), Self::ConfigError> {
|
||||||
self.apply_config(config)
|
self.apply_config(config)
|
||||||
@ -658,9 +678,8 @@ where
|
|||||||
/// Change the configuration.
|
/// Change the configuration.
|
||||||
///
|
///
|
||||||
/// Note that this also changes the configuration of the RX half.
|
/// Note that this also changes the configuration of the RX half.
|
||||||
pub fn apply_config(&mut self, config: &Config) -> Result<(), Error> {
|
pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
self.uart.info().apply_config(config)?;
|
self.uart.info().apply_config(config)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes bytes
|
/// Writes bytes
|
||||||
@ -748,20 +767,11 @@ where
|
|||||||
impl<'d> UartTx<'d, Blocking> {
|
impl<'d> UartTx<'d, Blocking> {
|
||||||
/// Create a new UART TX instance in [`Blocking`] mode.
|
/// Create a new UART TX instance in [`Blocking`] mode.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
uart: impl Peripheral<P = impl Instance> + 'd,
|
|
||||||
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
Self::new_typed(uart.map_into(), tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new UART TX instance with configuration options in
|
|
||||||
/// [`Blocking`] mode.
|
|
||||||
pub fn new_with_config(
|
|
||||||
uart: impl Peripheral<P = impl Instance> + 'd,
|
uart: impl Peripheral<P = impl Instance> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, ConfigError> {
|
||||||
Self::new_with_config_typed(uart.map_into(), config, tx)
|
Self::new_typed(uart.map_into(), config, tx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,19 +781,10 @@ where
|
|||||||
{
|
{
|
||||||
/// Create a new UART TX instance in [`Blocking`] mode.
|
/// Create a new UART TX instance in [`Blocking`] mode.
|
||||||
pub fn new_typed(
|
pub fn new_typed(
|
||||||
uart: impl Peripheral<P = T> + 'd,
|
|
||||||
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
Self::new_with_config_typed(uart, Config::default(), tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new UART TX instance with configuration options in
|
|
||||||
/// [`Blocking`] mode.
|
|
||||||
pub fn new_with_config_typed(
|
|
||||||
uart: impl Peripheral<P = T> + 'd,
|
uart: impl Peripheral<P = T> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, ConfigError> {
|
||||||
let (_, uart_tx) = UartBuilder::<'d, Blocking, T>::new(uart)
|
let (_, uart_tx) = UartBuilder::<'d, Blocking, T>::new(uart)
|
||||||
.with_tx(tx)
|
.with_tx(tx)
|
||||||
.init(config)?
|
.init(config)?
|
||||||
@ -868,9 +869,8 @@ where
|
|||||||
/// Change the configuration.
|
/// Change the configuration.
|
||||||
///
|
///
|
||||||
/// Note that this also changes the configuration of the TX half.
|
/// Note that this also changes the configuration of the TX half.
|
||||||
pub fn apply_config(&mut self, config: &Config) -> Result<(), Error> {
|
pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
self.uart.info().apply_config(config)?;
|
self.uart.info().apply_config(config)
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Fill a buffer with received bytes
|
/// Fill a buffer with received bytes
|
||||||
@ -1006,20 +1006,11 @@ where
|
|||||||
impl<'d> UartRx<'d, Blocking> {
|
impl<'d> UartRx<'d, Blocking> {
|
||||||
/// Create a new UART RX instance in [`Blocking`] mode.
|
/// Create a new UART RX instance in [`Blocking`] mode.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
uart: impl Peripheral<P = impl Instance> + 'd,
|
|
||||||
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
UartRx::new_typed(uart.map_into(), rx)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new UART RX instance with configuration options in
|
|
||||||
/// [`Blocking`] mode.
|
|
||||||
pub fn new_with_config(
|
|
||||||
uart: impl Peripheral<P = impl Instance> + 'd,
|
uart: impl Peripheral<P = impl Instance> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, ConfigError> {
|
||||||
UartRx::new_with_config_typed(uart.map_into(), config, rx)
|
UartRx::new_typed(uart.map_into(), config, rx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1029,19 +1020,10 @@ where
|
|||||||
{
|
{
|
||||||
/// Create a new UART RX instance in [`Blocking`] mode.
|
/// Create a new UART RX instance in [`Blocking`] mode.
|
||||||
pub fn new_typed(
|
pub fn new_typed(
|
||||||
uart: impl Peripheral<P = T> + 'd,
|
|
||||||
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
Self::new_with_config_typed(uart, Config::default(), rx)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new UART RX instance with configuration options in
|
|
||||||
/// [`Blocking`] mode.
|
|
||||||
pub fn new_with_config_typed(
|
|
||||||
uart: impl Peripheral<P = T> + 'd,
|
uart: impl Peripheral<P = T> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, ConfigError> {
|
||||||
let (uart_rx, _) = UartBuilder::new(uart).with_rx(rx).init(config)?.split();
|
let (uart_rx, _) = UartBuilder::new(uart).with_rx(rx).init(config)?.split();
|
||||||
|
|
||||||
Ok(uart_rx)
|
Ok(uart_rx)
|
||||||
@ -1089,22 +1071,12 @@ where
|
|||||||
impl<'d> Uart<'d, Blocking> {
|
impl<'d> Uart<'d, Blocking> {
|
||||||
/// Create a new UART instance in [`Blocking`] mode.
|
/// Create a new UART instance in [`Blocking`] mode.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
uart: impl Peripheral<P = impl Instance> + 'd,
|
|
||||||
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
|
||||||
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
Self::new_typed(uart.map_into(), rx, tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new UART instance with configuration options in
|
|
||||||
/// [`Blocking`] mode.
|
|
||||||
pub fn new_with_config(
|
|
||||||
uart: impl Peripheral<P = impl Instance> + 'd,
|
uart: impl Peripheral<P = impl Instance> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
||||||
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, ConfigError> {
|
||||||
Self::new_with_config_typed(uart.map_into(), config, rx, tx)
|
Self::new_typed(uart.map_into(), config, rx, tx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1114,21 +1086,11 @@ where
|
|||||||
{
|
{
|
||||||
/// Create a new UART instance in [`Blocking`] mode.
|
/// Create a new UART instance in [`Blocking`] mode.
|
||||||
pub fn new_typed(
|
pub fn new_typed(
|
||||||
uart: impl Peripheral<P = T> + 'd,
|
|
||||||
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
|
||||||
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
Self::new_with_config_typed(uart, Config::default(), rx, tx)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a new UART instance with configuration options in
|
|
||||||
/// [`Blocking`] mode.
|
|
||||||
pub fn new_with_config_typed(
|
|
||||||
uart: impl Peripheral<P = T> + 'd,
|
uart: impl Peripheral<P = T> + 'd,
|
||||||
config: Config,
|
config: Config,
|
||||||
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
rx: impl Peripheral<P = impl PeripheralInput> + 'd,
|
||||||
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
tx: impl Peripheral<P = impl PeripheralOutput> + 'd,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, ConfigError> {
|
||||||
UartBuilder::new(uart).with_tx(tx).with_rx(rx).init(config)
|
UartBuilder::new(uart).with_tx(tx).with_rx(rx).init(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1251,26 +1213,6 @@ where
|
|||||||
sync_regs(register_block);
|
sync_regs(register_block);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Listen for the given interrupts
|
|
||||||
pub fn listen(&mut self, interrupts: impl Into<EnumSet<UartInterrupt>>) {
|
|
||||||
self.tx.uart.info().enable_listen(interrupts.into(), true)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Unlisten the given interrupts
|
|
||||||
pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<UartInterrupt>>) {
|
|
||||||
self.tx.uart.info().enable_listen(interrupts.into(), false)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Gets asserted interrupts
|
|
||||||
pub fn interrupts(&mut self) -> EnumSet<UartInterrupt> {
|
|
||||||
self.tx.uart.info().interrupts()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Resets asserted interrupts
|
|
||||||
pub fn clear_interrupts(&mut self, interrupts: EnumSet<UartInterrupt>) {
|
|
||||||
self.tx.uart.info().clear_interrupts(interrupts)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write a byte out over the UART
|
/// Write a byte out over the UART
|
||||||
pub fn write_byte(&mut self, word: u8) -> nb::Result<(), Error> {
|
pub fn write_byte(&mut self, word: u8) -> nb::Result<(), Error> {
|
||||||
self.tx.write_byte(word)
|
self.tx.write_byte(word)
|
||||||
@ -1287,13 +1229,13 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Change the configuration.
|
/// Change the configuration.
|
||||||
pub fn apply_config(&mut self, config: &Config) -> Result<(), Error> {
|
pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> {
|
||||||
self.rx.apply_config(config)?;
|
self.rx.apply_config(config)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn init(&mut self, config: Config) -> Result<(), Error> {
|
fn init(&mut self, config: Config) -> Result<(), ConfigError> {
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(any(esp32, esp32s2))] {
|
if #[cfg(any(esp32, esp32s2))] {
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
@ -1377,6 +1319,31 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> Uart<'_, Blocking, T>
|
||||||
|
where
|
||||||
|
T: Instance,
|
||||||
|
{
|
||||||
|
/// Listen for the given interrupts
|
||||||
|
pub fn listen(&mut self, interrupts: impl Into<EnumSet<UartInterrupt>>) {
|
||||||
|
self.tx.uart.info().enable_listen(interrupts.into(), true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Unlisten the given interrupts
|
||||||
|
pub fn unlisten(&mut self, interrupts: impl Into<EnumSet<UartInterrupt>>) {
|
||||||
|
self.tx.uart.info().enable_listen(interrupts.into(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets asserted interrupts
|
||||||
|
pub fn interrupts(&mut self) -> EnumSet<UartInterrupt> {
|
||||||
|
self.tx.uart.info().interrupts()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resets asserted interrupts
|
||||||
|
pub fn clear_interrupts(&mut self, interrupts: EnumSet<UartInterrupt>) {
|
||||||
|
self.tx.uart.info().clear_interrupts(interrupts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, M> ufmt_write::uWrite for Uart<'_, M, T>
|
impl<T, M> ufmt_write::uWrite for Uart<'_, M, T>
|
||||||
where
|
where
|
||||||
T: Instance,
|
T: Instance,
|
||||||
@ -2020,9 +1987,14 @@ pub mod lp_uart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LpUart {
|
impl LpUart {
|
||||||
/// Initialize the UART driver using the default configuration
|
/// Initialize the UART driver using the provided configuration
|
||||||
// TODO: CTS and RTS pins
|
// TODO: CTS and RTS pins
|
||||||
pub fn new(uart: LP_UART, _tx: LowPowerOutput<'_, 5>, _rx: LowPowerInput<'_, 4>) -> Self {
|
pub fn new(
|
||||||
|
uart: LP_UART,
|
||||||
|
config: Config,
|
||||||
|
_tx: LowPowerOutput<'_, 5>,
|
||||||
|
_rx: LowPowerInput<'_, 4>,
|
||||||
|
) -> Self {
|
||||||
let lp_io = unsafe { crate::peripherals::LP_IO::steal() };
|
let lp_io = unsafe { crate::peripherals::LP_IO::steal() };
|
||||||
let lp_aon = unsafe { crate::peripherals::LP_AON::steal() };
|
let lp_aon = unsafe { crate::peripherals::LP_AON::steal() };
|
||||||
|
|
||||||
@ -2037,11 +2009,6 @@ pub mod lp_uart {
|
|||||||
lp_io.gpio(4).modify(|_, w| unsafe { w.mcu_sel().bits(1) });
|
lp_io.gpio(4).modify(|_, w| unsafe { w.mcu_sel().bits(1) });
|
||||||
lp_io.gpio(5).modify(|_, w| unsafe { w.mcu_sel().bits(1) });
|
lp_io.gpio(5).modify(|_, w| unsafe { w.mcu_sel().bits(1) });
|
||||||
|
|
||||||
Self::new_with_config(uart, Config::default())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Initialize the UART driver using the provided configuration
|
|
||||||
pub fn new_with_config(uart: LP_UART, config: Config) -> Self {
|
|
||||||
let mut me = Self { uart };
|
let mut me = Self { uart };
|
||||||
|
|
||||||
// Set UART mode - do nothing for LP
|
// Set UART mode - do nothing for LP
|
||||||
@ -2332,7 +2299,7 @@ impl Info {
|
|||||||
crate::interrupt::disable(crate::Cpu::current(), self.interrupt);
|
crate::interrupt::disable(crate::Cpu::current(), self.interrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_config(&self, config: &Config) -> Result<(), Error> {
|
fn apply_config(&self, config: &Config) -> Result<(), ConfigError> {
|
||||||
self.set_rx_fifo_full_threshold(config.rx_fifo_full_threshold)?;
|
self.set_rx_fifo_full_threshold(config.rx_fifo_full_threshold)?;
|
||||||
self.set_rx_timeout(config.rx_timeout, config.symbol_length())?;
|
self.set_rx_timeout(config.rx_timeout, config.symbol_length())?;
|
||||||
self.change_baud(config.baudrate, config.clock_source);
|
self.change_baud(config.baudrate, config.clock_source);
|
||||||
@ -2350,13 +2317,13 @@ impl Info {
|
|||||||
/// Configures the RX-FIFO threshold
|
/// Configures the RX-FIFO threshold
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// `Err(Error::InvalidArgument)` if provided value exceeds maximum value
|
/// [`Err(ConfigError::UnsupportedFifoThreshold)`][ConfigError::UnsupportedFifoThreshold] if provided value exceeds maximum value
|
||||||
/// for SOC :
|
/// for SOC :
|
||||||
/// - `esp32` **0x7F**
|
/// - `esp32` **0x7F**
|
||||||
/// - `esp32c6`, `esp32h2` **0xFF**
|
/// - `esp32c6`, `esp32h2` **0xFF**
|
||||||
/// - `esp32c3`, `esp32c2`, `esp32s2` **0x1FF**
|
/// - `esp32c3`, `esp32c2`, `esp32s2` **0x1FF**
|
||||||
/// - `esp32s3` **0x3FF**
|
/// - `esp32s3` **0x3FF**
|
||||||
fn set_rx_fifo_full_threshold(&self, threshold: u16) -> Result<(), Error> {
|
fn set_rx_fifo_full_threshold(&self, threshold: u16) -> Result<(), ConfigError> {
|
||||||
#[cfg(esp32)]
|
#[cfg(esp32)]
|
||||||
const MAX_THRHD: u16 = 0x7F;
|
const MAX_THRHD: u16 = 0x7F;
|
||||||
#[cfg(any(esp32c6, esp32h2))]
|
#[cfg(any(esp32c6, esp32h2))]
|
||||||
@ -2367,7 +2334,7 @@ impl Info {
|
|||||||
const MAX_THRHD: u16 = 0x3FF;
|
const MAX_THRHD: u16 = 0x3FF;
|
||||||
|
|
||||||
if threshold > MAX_THRHD {
|
if threshold > MAX_THRHD {
|
||||||
return Err(Error::InvalidArgument);
|
return Err(ConfigError::UnsupportedFifoThreshold);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.register_block()
|
self.register_block()
|
||||||
@ -2384,12 +2351,13 @@ impl Info {
|
|||||||
/// triggering a timeout. Pass None to disable the timeout.
|
/// triggering a timeout. Pass None to disable the timeout.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
/// `Err(Error::InvalidArgument)` if the provided value exceeds the maximum
|
/// [`Err(ConfigError::UnsupportedTimeout)`][ConfigError::UnsupportedTimeout] if the provided value exceeds
|
||||||
/// value for SOC :
|
/// the maximum value for SOC :
|
||||||
/// - `esp32`: Symbol size is fixed to 8, do not pass a value > **0x7F**.
|
/// - `esp32`: Symbol size is fixed to 8, do not pass a value > **0x7F**.
|
||||||
/// - `esp32c2`, `esp32c3`, `esp32c6`, `esp32h2`, esp32s2`, esp32s3`: The
|
/// - `esp32c2`, `esp32c3`, `esp32c6`, `esp32h2`, esp32s2`, esp32s3`: The
|
||||||
/// value you pass times the symbol size must be <= **0x3FF**
|
/// value you pass times the symbol size must be <= **0x3FF**
|
||||||
fn set_rx_timeout(&self, timeout: Option<u8>, _symbol_len: u8) -> Result<(), Error> {
|
// TODO: the above should be a per-chip doc line.
|
||||||
|
fn set_rx_timeout(&self, timeout: Option<u8>, _symbol_len: u8) -> Result<(), ConfigError> {
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(esp32)] {
|
if #[cfg(esp32)] {
|
||||||
const MAX_THRHD: u8 = 0x7F; // 7 bits
|
const MAX_THRHD: u8 = 0x7F; // 7 bits
|
||||||
@ -2409,7 +2377,7 @@ impl Info {
|
|||||||
let timeout_reg = timeout as u16 * _symbol_len as u16;
|
let timeout_reg = timeout as u16 * _symbol_len as u16;
|
||||||
|
|
||||||
if timeout_reg > MAX_THRHD {
|
if timeout_reg > MAX_THRHD {
|
||||||
return Err(Error::InvalidArgument);
|
return Err(ConfigError::UnsupportedTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
|
|||||||
@ -89,7 +89,7 @@ async fn main(spawner: Spawner) {
|
|||||||
|
|
||||||
let config = Config::default().rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
let config = Config::default().rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||||
|
|
||||||
let mut uart0 = Uart::new_with_config(peripherals.UART0, config, rx_pin, tx_pin)
|
let mut uart0 = Uart::new(peripherals.UART0, config, rx_pin, tx_pin)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.into_async();
|
.into_async();
|
||||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||||
|
|||||||
@ -57,12 +57,13 @@ async fn main(_spawner: Spawner) {
|
|||||||
let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
|
let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
|
||||||
let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap();
|
let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap();
|
||||||
|
|
||||||
let mut spi = Spi::new_with_config(
|
let mut spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(100.kHz())
|
.with_frequency(100.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_sck(sclk)
|
.with_sck(sclk)
|
||||||
.with_mosi(mosi)
|
.with_mosi(mosi)
|
||||||
.with_miso(miso)
|
.with_miso(miso)
|
||||||
|
|||||||
@ -8,7 +8,11 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp_backtrace as _;
|
use esp_backtrace as _;
|
||||||
use esp_hal::{prelude::*, reset::software_reset, uart::Uart};
|
use esp_hal::{
|
||||||
|
prelude::*,
|
||||||
|
reset::software_reset,
|
||||||
|
uart::{self, Uart},
|
||||||
|
};
|
||||||
use esp_ieee802154::{Config, Ieee802154};
|
use esp_ieee802154::{Config, Ieee802154};
|
||||||
use esp_println::println;
|
use esp_println::println;
|
||||||
|
|
||||||
@ -25,7 +29,13 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut uart0 = Uart::new(peripherals.UART0, &mut rx_pin, &mut tx_pin).unwrap();
|
let mut uart0 = Uart::new(
|
||||||
|
peripherals.UART0,
|
||||||
|
uart::Config::default(),
|
||||||
|
&mut rx_pin,
|
||||||
|
&mut tx_pin,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// read two characters which get parsed as the channel
|
// read two characters which get parsed as the channel
|
||||||
let mut cnt = 0;
|
let mut cnt = 0;
|
||||||
|
|||||||
@ -37,12 +37,13 @@ fn main() -> ! {
|
|||||||
|
|
||||||
let miso = unsafe { miso_mosi.clone_unchecked() };
|
let miso = unsafe { miso_mosi.clone_unchecked() };
|
||||||
|
|
||||||
let mut spi = Spi::new_with_config(
|
let mut spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(100.kHz())
|
.with_frequency(100.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_sck(sclk)
|
.with_sck(sclk)
|
||||||
.with_miso(miso) // order matters
|
.with_miso(miso) // order matters
|
||||||
.with_mosi(miso_mosi) // order matters
|
.with_mosi(miso_mosi) // order matters
|
||||||
|
|||||||
@ -88,12 +88,13 @@ fn main() -> ! {
|
|||||||
let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
|
let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
|
||||||
// Need to set miso first so that mosi can overwrite the
|
// Need to set miso first so that mosi can overwrite the
|
||||||
// output connection (because we are using the same pin to loop back)
|
// output connection (because we are using the same pin to loop back)
|
||||||
let mut spi = Spi::new_with_config(
|
let mut spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(100.kHz())
|
.with_frequency(100.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_sck(sclk)
|
.with_sck(sclk)
|
||||||
.with_miso(miso)
|
.with_miso(miso)
|
||||||
.with_mosi(mosi)
|
.with_mosi(mosi)
|
||||||
|
|||||||
@ -118,12 +118,13 @@ mod test {
|
|||||||
|
|
||||||
let (_, mosi) = hil_test::common_test_pins!(peripherals);
|
let (_, mosi) = hil_test::common_test_pins!(peripherals);
|
||||||
|
|
||||||
let mut spi = Spi::new_with_config(
|
let mut spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(10000.kHz())
|
.with_frequency(10000.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_miso(unsafe { mosi.clone_unchecked() })
|
.with_miso(unsafe { mosi.clone_unchecked() })
|
||||||
.with_mosi(mosi)
|
.with_mosi(mosi)
|
||||||
.with_dma(dma_channel1)
|
.with_dma(dma_channel1)
|
||||||
@ -131,12 +132,13 @@ mod test {
|
|||||||
.into_async();
|
.into_async();
|
||||||
|
|
||||||
#[cfg(any(esp32, esp32s2, esp32s3))]
|
#[cfg(any(esp32, esp32s2, esp32s3))]
|
||||||
let other_peripheral = Spi::new_with_config(
|
let other_peripheral = Spi::new(
|
||||||
peripherals.SPI3,
|
peripherals.SPI3,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(10000.kHz())
|
.with_frequency(10000.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_dma(dma_channel2)
|
.with_dma(dma_channel2)
|
||||||
.into_async();
|
.into_async();
|
||||||
|
|
||||||
@ -225,12 +227,13 @@ mod test {
|
|||||||
let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
|
let dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
|
||||||
let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap();
|
let dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap();
|
||||||
|
|
||||||
let mut spi = Spi::new_with_config(
|
let mut spi = Spi::new(
|
||||||
peripherals.spi,
|
peripherals.spi,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(100.kHz())
|
.with_frequency(100.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_dma(peripherals.dma_channel)
|
.with_dma(peripherals.dma_channel)
|
||||||
.with_buffers(dma_rx_buf, dma_tx_buf)
|
.with_buffers(dma_rx_buf, dma_tx_buf)
|
||||||
.into_async();
|
.into_async();
|
||||||
|
|||||||
@ -41,6 +41,7 @@ mod tests {
|
|||||||
// Create a new peripheral object with the described wiring and standard
|
// Create a new peripheral object with the described wiring and standard
|
||||||
// I2C clock speed:
|
// I2C clock speed:
|
||||||
let i2c = I2c::new(peripherals.I2C0, Config::default())
|
let i2c = I2c::new(peripherals.I2C0, Config::default())
|
||||||
|
.unwrap()
|
||||||
.with_sda(sda)
|
.with_sda(sda)
|
||||||
.with_scl(scl);
|
.with_scl(scl);
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@ use esp_hal::{
|
|||||||
dma_buffers,
|
dma_buffers,
|
||||||
gpio::Level,
|
gpio::Level,
|
||||||
lcd_cam::{
|
lcd_cam::{
|
||||||
cam::{Camera, RxEightBits},
|
cam::{self, Camera, RxEightBits},
|
||||||
lcd::{
|
lcd::{
|
||||||
dpi,
|
dpi,
|
||||||
dpi::{Dpi, Format, FrameTiming},
|
dpi::{Dpi, Format, FrameTiming},
|
||||||
@ -77,6 +77,7 @@ mod tests {
|
|||||||
polarity: Polarity::IdleHigh,
|
polarity: Polarity::IdleHigh,
|
||||||
phase: Phase::ShiftLow,
|
phase: Phase::ShiftLow,
|
||||||
};
|
};
|
||||||
|
config.frequency = 500u32.kHz();
|
||||||
config.format = Format {
|
config.format = Format {
|
||||||
enable_2byte_mode: false,
|
enable_2byte_mode: false,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -100,7 +101,8 @@ mod tests {
|
|||||||
config.de_idle_level = Level::Low;
|
config.de_idle_level = Level::Low;
|
||||||
config.disable_black_region = false;
|
config.disable_black_region = false;
|
||||||
|
|
||||||
let dpi = Dpi::new(lcd_cam.lcd, tx_channel, 500u32.kHz(), config)
|
let dpi = Dpi::new(lcd_cam.lcd, tx_channel, config)
|
||||||
|
.unwrap()
|
||||||
.with_vsync(vsync_out)
|
.with_vsync(vsync_out)
|
||||||
.with_hsync(hsync_out)
|
.with_hsync(hsync_out)
|
||||||
.with_de(de_out)
|
.with_de(de_out)
|
||||||
@ -114,12 +116,16 @@ mod tests {
|
|||||||
.with_data6(d6_out)
|
.with_data6(d6_out)
|
||||||
.with_data7(d7_out);
|
.with_data7(d7_out);
|
||||||
|
|
||||||
|
let mut cam_config = cam::Config::default();
|
||||||
|
cam_config.frequency = 1u32.MHz();
|
||||||
|
|
||||||
let camera = Camera::new(
|
let camera = Camera::new(
|
||||||
lcd_cam.cam,
|
lcd_cam.cam,
|
||||||
rx_channel,
|
rx_channel,
|
||||||
RxEightBits::new(d0_in, d1_in, d2_in, d3_in, d4_in, d5_in, d6_in, d7_in),
|
RxEightBits::new(d0_in, d1_in, d2_in, d3_in, d4_in, d5_in, d6_in, d7_in),
|
||||||
1u32.MHz(),
|
cam_config,
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_ctrl_pins_and_de(vsync_in, hsync_in, de_in)
|
.with_ctrl_pins_and_de(vsync_in, hsync_in, de_in)
|
||||||
.with_pixel_clock(pclk_in);
|
.with_pixel_clock(pclk_in);
|
||||||
|
|
||||||
|
|||||||
@ -75,7 +75,12 @@ mod tests {
|
|||||||
fn test_i8080_8bit(ctx: Context<'static>) {
|
fn test_i8080_8bit(ctx: Context<'static>) {
|
||||||
let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin);
|
let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin);
|
||||||
|
|
||||||
let i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, 20.MHz(), Config::default());
|
let i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, {
|
||||||
|
let mut config = Config::default();
|
||||||
|
config.frequency = 20.MHz();
|
||||||
|
config
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let xfer = i8080.send(Command::<u8>::None, 0, ctx.dma_buf).unwrap();
|
let xfer = i8080.send(Command::<u8>::None, 0, ctx.dma_buf).unwrap();
|
||||||
xfer.wait().0.unwrap();
|
xfer.wait().0.unwrap();
|
||||||
@ -132,9 +137,14 @@ mod tests {
|
|||||||
NoPin,
|
NoPin,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, 20.MHz(), Config::default())
|
let mut i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, {
|
||||||
.with_cs(cs_signal)
|
let mut config = Config::default();
|
||||||
.with_ctrl_pins(NoPin, NoPin);
|
config.frequency = 20.MHz();
|
||||||
|
config
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.with_cs(cs_signal)
|
||||||
|
.with_ctrl_pins(NoPin, NoPin);
|
||||||
|
|
||||||
// This is to make the test values look more intuitive.
|
// This is to make the test values look more intuitive.
|
||||||
i8080.set_bit_order(BitOrder::Inverted);
|
i8080.set_bit_order(BitOrder::Inverted);
|
||||||
@ -244,9 +254,14 @@ mod tests {
|
|||||||
unit3_signal,
|
unit3_signal,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, 20.MHz(), Config::default())
|
let mut i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, {
|
||||||
.with_cs(cs_signal)
|
let mut config = Config::default();
|
||||||
.with_ctrl_pins(NoPin, NoPin);
|
config.frequency = 20.MHz();
|
||||||
|
config
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
.with_cs(cs_signal)
|
||||||
|
.with_ctrl_pins(NoPin, NoPin);
|
||||||
|
|
||||||
// This is to make the test values look more intuitive.
|
// This is to make the test values look more intuitive.
|
||||||
i8080.set_bit_order(BitOrder::Inverted);
|
i8080.set_bit_order(BitOrder::Inverted);
|
||||||
|
|||||||
@ -51,7 +51,12 @@ mod tests {
|
|||||||
async fn test_i8080_8bit(ctx: Context<'static>) {
|
async fn test_i8080_8bit(ctx: Context<'static>) {
|
||||||
let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin);
|
let pins = TxEightBits::new(NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin, NoPin);
|
||||||
|
|
||||||
let i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, 20.MHz(), Config::default());
|
let i8080 = I8080::new(ctx.lcd_cam.lcd, ctx.dma, pins, {
|
||||||
|
let mut config = Config::default();
|
||||||
|
config.frequency = 20.MHz();
|
||||||
|
config
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut transfer = i8080.send(Command::<u8>::None, 0, ctx.dma_buf).unwrap();
|
let mut transfer = i8080.send(Command::<u8>::None, 0, ctx.dma_buf).unwrap();
|
||||||
|
|
||||||
|
|||||||
@ -200,12 +200,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let spi = Spi::new_with_config(
|
let spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(100.kHz())
|
.with_frequency(100.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
);
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
Context {
|
Context {
|
||||||
spi,
|
spi,
|
||||||
|
|||||||
@ -73,11 +73,11 @@ mod tests {
|
|||||||
let (mosi_loopback_pcnt, mosi) = mosi.split();
|
let (mosi_loopback_pcnt, mosi) = mosi.split();
|
||||||
// Need to set miso first so that mosi can overwrite the
|
// Need to set miso first so that mosi can overwrite the
|
||||||
// output connection (because we are using the same pin to loop back)
|
// output connection (because we are using the same pin to loop back)
|
||||||
let spi =
|
let spi = Spi::new(peripherals.SPI2, Config::default().with_frequency(10.MHz()))
|
||||||
Spi::new_with_config(peripherals.SPI2, Config::default().with_frequency(10.MHz()))
|
.unwrap()
|
||||||
.with_sck(sclk)
|
.with_sck(sclk)
|
||||||
.with_miso(unsafe { mosi.clone_unchecked() })
|
.with_miso(unsafe { mosi.clone_unchecked() })
|
||||||
.with_mosi(mosi);
|
.with_mosi(mosi);
|
||||||
|
|
||||||
let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000);
|
let (rx_buffer, rx_descriptors, tx_buffer, tx_descriptors) = dma_buffers!(32000);
|
||||||
|
|
||||||
|
|||||||
@ -46,12 +46,13 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let spi = Spi::new_with_config(
|
let spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(100.kHz())
|
.with_frequency(100.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_sck(sclk)
|
.with_sck(sclk)
|
||||||
.with_miso(miso)
|
.with_miso(miso)
|
||||||
.with_dma(dma_channel);
|
.with_dma(dma_channel);
|
||||||
|
|||||||
@ -50,12 +50,13 @@ mod tests {
|
|||||||
|
|
||||||
let (mosi_loopback, mosi) = mosi.split();
|
let (mosi_loopback, mosi) = mosi.split();
|
||||||
|
|
||||||
let spi = Spi::new_with_config(
|
let spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(100.kHz())
|
.with_frequency(100.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_sck(sclk)
|
.with_sck(sclk)
|
||||||
.with_mosi(mosi)
|
.with_mosi(mosi)
|
||||||
.with_dma(dma_channel);
|
.with_dma(dma_channel);
|
||||||
|
|||||||
@ -62,12 +62,13 @@ mod tests {
|
|||||||
|
|
||||||
let (mosi_loopback, mosi) = mosi.split();
|
let (mosi_loopback, mosi) = mosi.split();
|
||||||
|
|
||||||
let spi = Spi::new_with_config(
|
let spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(100.kHz())
|
.with_frequency(100.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_sck(sclk)
|
.with_sck(sclk)
|
||||||
.with_mosi(mosi)
|
.with_mosi(mosi)
|
||||||
.with_dma(dma_channel);
|
.with_dma(dma_channel);
|
||||||
|
|||||||
@ -31,7 +31,7 @@ mod tests {
|
|||||||
|
|
||||||
let (rx, tx) = pin.split();
|
let (rx, tx) = pin.split();
|
||||||
|
|
||||||
let uart = Uart::new(peripherals.UART1, rx, tx).unwrap();
|
let uart = Uart::new(peripherals.UART1, uart::Config::default(), rx, tx).unwrap();
|
||||||
|
|
||||||
Context { uart }
|
Context { uart }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,7 +6,10 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp_hal::{uart::Uart, Async};
|
use esp_hal::{
|
||||||
|
uart::{self, Uart},
|
||||||
|
Async,
|
||||||
|
};
|
||||||
use hil_test as _;
|
use hil_test as _;
|
||||||
|
|
||||||
struct Context {
|
struct Context {
|
||||||
@ -24,7 +27,9 @@ mod tests {
|
|||||||
|
|
||||||
let (rx, tx) = hil_test::common_test_pins!(peripherals);
|
let (rx, tx) = hil_test::common_test_pins!(peripherals);
|
||||||
|
|
||||||
let uart = Uart::new(peripherals.UART0, rx, tx).unwrap().into_async();
|
let uart = Uart::new(peripherals.UART0, uart::Config::default(), rx, tx)
|
||||||
|
.unwrap()
|
||||||
|
.into_async();
|
||||||
|
|
||||||
Context { uart }
|
Context { uart }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ mod tests {
|
|||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
gpio::OutputPin,
|
gpio::OutputPin,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
uart::{UartRx, UartTx},
|
uart::{self, UartRx, UartTx},
|
||||||
};
|
};
|
||||||
use hil_test as _;
|
use hil_test as _;
|
||||||
use nb::block;
|
use nb::block;
|
||||||
@ -23,7 +23,7 @@ mod tests {
|
|||||||
|
|
||||||
let (rx, mut tx) = hil_test::common_test_pins!(peripherals);
|
let (rx, mut tx) = hil_test::common_test_pins!(peripherals);
|
||||||
|
|
||||||
let mut rx = UartRx::new(peripherals.UART1, rx).unwrap();
|
let mut rx = UartRx::new(peripherals.UART1, uart::Config::default(), rx).unwrap();
|
||||||
|
|
||||||
// start reception
|
// start reception
|
||||||
_ = rx.read_byte(); // this will just return WouldBlock
|
_ = rx.read_byte(); // this will just return WouldBlock
|
||||||
@ -31,7 +31,7 @@ mod tests {
|
|||||||
unsafe { tx.set_output_high(false, esp_hal::Internal::conjure()) };
|
unsafe { tx.set_output_high(false, esp_hal::Internal::conjure()) };
|
||||||
|
|
||||||
// set up TX and send a byte
|
// set up TX and send a byte
|
||||||
let mut tx = UartTx::new(peripherals.UART0, tx).unwrap();
|
let mut tx = UartTx::new(peripherals.UART0, uart::Config::default(), tx).unwrap();
|
||||||
|
|
||||||
tx.flush_tx().unwrap();
|
tx.flush_tx().unwrap();
|
||||||
tx.write_bytes(&[0x42]).unwrap();
|
tx.write_bytes(&[0x42]).unwrap();
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
uart::{UartRx, UartTx},
|
uart::{self, UartRx, UartTx},
|
||||||
Blocking,
|
Blocking,
|
||||||
};
|
};
|
||||||
use hil_test as _;
|
use hil_test as _;
|
||||||
@ -29,8 +29,8 @@ mod tests {
|
|||||||
|
|
||||||
let (rx, tx) = hil_test::common_test_pins!(peripherals);
|
let (rx, tx) = hil_test::common_test_pins!(peripherals);
|
||||||
|
|
||||||
let tx = UartTx::new(peripherals.UART0, tx).unwrap();
|
let tx = UartTx::new(peripherals.UART0, uart::Config::default(), tx).unwrap();
|
||||||
let rx = UartRx::new(peripherals.UART1, rx).unwrap();
|
let rx = UartRx::new(peripherals.UART1, uart::Config::default(), rx).unwrap();
|
||||||
|
|
||||||
Context { rx, tx }
|
Context { rx, tx }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
uart::{UartRx, UartTx},
|
uart::{self, UartRx, UartTx},
|
||||||
Async,
|
Async,
|
||||||
};
|
};
|
||||||
use hil_test as _;
|
use hil_test as _;
|
||||||
@ -28,8 +28,12 @@ mod tests {
|
|||||||
|
|
||||||
let (rx, tx) = hil_test::common_test_pins!(peripherals);
|
let (rx, tx) = hil_test::common_test_pins!(peripherals);
|
||||||
|
|
||||||
let tx = UartTx::new(peripherals.UART0, tx).unwrap().into_async();
|
let tx = UartTx::new(peripherals.UART0, uart::Config::default(), tx)
|
||||||
let rx = UartRx::new(peripherals.UART1, rx).unwrap().into_async();
|
.unwrap()
|
||||||
|
.into_async();
|
||||||
|
let rx = UartRx::new(peripherals.UART1, uart::Config::default(), rx)
|
||||||
|
.unwrap()
|
||||||
|
.into_async();
|
||||||
|
|
||||||
Context { rx, tx }
|
Context { rx, tx }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.frequency = 400.kHz();
|
config.frequency = 400.kHz();
|
||||||
config
|
config
|
||||||
})
|
})
|
||||||
|
.unwrap()
|
||||||
.with_sda(peripherals.GPIO4)
|
.with_sda(peripherals.GPIO4)
|
||||||
.with_scl(peripherals.GPIO5)
|
.with_scl(peripherals.GPIO5)
|
||||||
.into_async();
|
.into_async();
|
||||||
|
|||||||
@ -37,6 +37,7 @@ async fn main(_spawner: Spawner) {
|
|||||||
config.frequency = 400.kHz();
|
config.frequency = 400.kHz();
|
||||||
config
|
config
|
||||||
})
|
})
|
||||||
|
.unwrap()
|
||||||
.with_sda(peripherals.GPIO4)
|
.with_sda(peripherals.GPIO4)
|
||||||
.with_scl(peripherals.GPIO5)
|
.with_scl(peripherals.GPIO5)
|
||||||
.into_async();
|
.into_async();
|
||||||
|
|||||||
@ -25,6 +25,7 @@ fn main() -> ! {
|
|||||||
// Create a new peripheral object with the described wiring and standard
|
// Create a new peripheral object with the described wiring and standard
|
||||||
// I2C clock speed:
|
// I2C clock speed:
|
||||||
let mut i2c = I2c::new(peripherals.I2C0, Config::default())
|
let mut i2c = I2c::new(peripherals.I2C0, Config::default())
|
||||||
|
.unwrap()
|
||||||
.with_sda(peripherals.GPIO4)
|
.with_sda(peripherals.GPIO4)
|
||||||
.with_scl(peripherals.GPIO5);
|
.with_scl(peripherals.GPIO5);
|
||||||
|
|
||||||
|
|||||||
@ -38,6 +38,7 @@ fn main() -> ! {
|
|||||||
// Create a new peripheral object with the described wiring
|
// Create a new peripheral object with the described wiring
|
||||||
// and standard I2C clock speed
|
// and standard I2C clock speed
|
||||||
let i2c = I2c::new(peripherals.I2C0, Config::default())
|
let i2c = I2c::new(peripherals.I2C0, Config::default())
|
||||||
|
.unwrap()
|
||||||
.with_sda(peripherals.GPIO4)
|
.with_sda(peripherals.GPIO4)
|
||||||
.with_scl(peripherals.GPIO5);
|
.with_scl(peripherals.GPIO5);
|
||||||
|
|
||||||
|
|||||||
@ -34,7 +34,7 @@ use esp_hal::{
|
|||||||
master::{Config, I2c},
|
master::{Config, I2c},
|
||||||
},
|
},
|
||||||
lcd_cam::{
|
lcd_cam::{
|
||||||
cam::{Camera, RxEightBits},
|
cam::{self, Camera, RxEightBits},
|
||||||
LcdCam,
|
LcdCam,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
@ -65,8 +65,12 @@ fn main() -> ! {
|
|||||||
peripherals.GPIO16,
|
peripherals.GPIO16,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut cam_config = cam::Config::default();
|
||||||
|
cam_config.frequency = 20u32.MHz();
|
||||||
|
|
||||||
let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
|
let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
|
||||||
let camera = Camera::new(lcd_cam.cam, peripherals.DMA_CH0, cam_data_pins, 20u32.MHz())
|
let camera = Camera::new(lcd_cam.cam, peripherals.DMA_CH0, cam_data_pins, cam_config)
|
||||||
|
.unwrap()
|
||||||
.with_master_clock(cam_xclk)
|
.with_master_clock(cam_xclk)
|
||||||
.with_pixel_clock(cam_pclk)
|
.with_pixel_clock(cam_pclk)
|
||||||
.with_ctrl_pins(cam_vsync, cam_href);
|
.with_ctrl_pins(cam_vsync, cam_href);
|
||||||
@ -76,6 +80,7 @@ fn main() -> ! {
|
|||||||
delay.delay_millis(500u32);
|
delay.delay_millis(500u32);
|
||||||
|
|
||||||
let i2c = I2c::new(peripherals.I2C0, Config::default())
|
let i2c = I2c::new(peripherals.I2C0, Config::default())
|
||||||
|
.unwrap()
|
||||||
.with_sda(cam_siod)
|
.with_sda(cam_siod)
|
||||||
.with_scl(cam_sioc);
|
.with_scl(cam_sioc);
|
||||||
|
|
||||||
|
|||||||
@ -62,6 +62,7 @@ fn main() -> ! {
|
|||||||
peripherals.I2C0,
|
peripherals.I2C0,
|
||||||
i2c::master::Config::default().with_frequency(400.kHz()),
|
i2c::master::Config::default().with_frequency(400.kHz()),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_sda(peripherals.GPIO47)
|
.with_sda(peripherals.GPIO47)
|
||||||
.with_scl(peripherals.GPIO48);
|
.with_scl(peripherals.GPIO48);
|
||||||
|
|
||||||
@ -137,6 +138,7 @@ fn main() -> ! {
|
|||||||
polarity: Polarity::IdleLow,
|
polarity: Polarity::IdleLow,
|
||||||
phase: Phase::ShiftLow,
|
phase: Phase::ShiftLow,
|
||||||
};
|
};
|
||||||
|
config.frequency = 16.MHz();
|
||||||
config.format = Format {
|
config.format = Format {
|
||||||
enable_2byte_mode: true,
|
enable_2byte_mode: true,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@ -160,7 +162,8 @@ fn main() -> ! {
|
|||||||
config.de_idle_level = Level::Low;
|
config.de_idle_level = Level::Low;
|
||||||
config.disable_black_region = false;
|
config.disable_black_region = false;
|
||||||
|
|
||||||
let mut dpi = Dpi::new(lcd_cam.lcd, tx_channel, 16.MHz(), config)
|
let mut dpi = Dpi::new(lcd_cam.lcd, tx_channel, config)
|
||||||
|
.unwrap()
|
||||||
.with_vsync(vsync_pin)
|
.with_vsync(vsync_pin)
|
||||||
.with_hsync(peripherals.GPIO46)
|
.with_hsync(peripherals.GPIO46)
|
||||||
.with_de(peripherals.GPIO17)
|
.with_de(peripherals.GPIO17)
|
||||||
|
|||||||
@ -67,14 +67,11 @@ fn main() -> ! {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
|
let lcd_cam = LcdCam::new(peripherals.LCD_CAM);
|
||||||
let i8080 = I8080::new(
|
let mut i8080_config = Config::default();
|
||||||
lcd_cam.lcd,
|
i8080_config.frequency = 20.MHz();
|
||||||
peripherals.DMA_CH0,
|
let i8080 = I8080::new(lcd_cam.lcd, peripherals.DMA_CH0, tx_pins, i8080_config)
|
||||||
tx_pins,
|
.unwrap()
|
||||||
20.MHz(),
|
.with_ctrl_pins(lcd_rs, lcd_wr);
|
||||||
Config::default(),
|
|
||||||
)
|
|
||||||
.with_ctrl_pins(lcd_rs, lcd_wr);
|
|
||||||
|
|
||||||
// Note: This isn't provided in the HAL since different drivers may require
|
// Note: This isn't provided in the HAL since different drivers may require
|
||||||
// different considerations, like how to manage the CS pin, the CD pin,
|
// different considerations, like how to manage the CS pin, the CD pin,
|
||||||
|
|||||||
@ -75,12 +75,13 @@ fn main() -> ! {
|
|||||||
let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
|
let mut dma_rx_buf = DmaRxBuf::new(rx_descriptors, rx_buffer).unwrap();
|
||||||
let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap();
|
let mut dma_tx_buf = DmaTxBuf::new(tx_descriptors, tx_buffer).unwrap();
|
||||||
|
|
||||||
let mut spi = Spi::new_with_config(
|
let mut spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(100.kHz())
|
.with_frequency(100.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_sck(sclk)
|
.with_sck(sclk)
|
||||||
.with_mosi(mosi)
|
.with_mosi(mosi)
|
||||||
.with_miso(miso)
|
.with_miso(miso)
|
||||||
|
|||||||
@ -61,12 +61,13 @@ fn main() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut spi = Spi::new_with_config(
|
let mut spi = Spi::new(
|
||||||
peripherals.SPI2,
|
peripherals.SPI2,
|
||||||
Config::default()
|
Config::default()
|
||||||
.with_frequency(100.kHz())
|
.with_frequency(100.kHz())
|
||||||
.with_mode(SpiMode::Mode0),
|
.with_mode(SpiMode::Mode0),
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
.with_sck(sclk)
|
.with_sck(sclk)
|
||||||
.with_mosi(mosi)
|
.with_mosi(mosi)
|
||||||
.with_miso(miso)
|
.with_miso(miso)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user