Closed milewski closed 1 year ago
By the way, these questions belong to the forum - you might want to join it.
Oh, I did not realize that your board has the LCD hard-wired, so you cannot confuse the wirings. Besides the frequency advice which is still valid, are you sure you are using the right SPI, and the right pins?
Im not sure if I wired the pin correctly, I don't really know which pin corresponds to sclk
and sdo
I think I can only say "confidently" that these are correct: BL
, CS
, DC
and RES
For the other 2 I have tried a combination of various other pins but none seems to work, Only the backlight lights on...
This is what I have currently:
fn main() -> anyhow::Result<()> {
esp_idf_sys::link_patches();
let peripherals = Peripherals::take().unwrap();
let backlight = peripherals.pins.gpio38;
let dc = peripherals.pins.gpio7;
let rst = peripherals.pins.gpio5;
let cs = peripherals.pins.gpio6;
let spi = peripherals.spi2;
let sclk = peripherals.pins.gpio12; // these 2 pins doesn't seem to be marked on the pin diagram of my board :(
let sdo = peripherals.pins.gpio13;
let mut backlight = PinDriver::input_output_od(backlight)?;
backlight.set_high()?;
let di = SPIInterfaceNoCS::new(
spi::SpiDeviceDriver::new_single(
spi,
sclk,
sdo,
Option::<gpio::AnyIOPin>::None,
Some(cs),
&spi::SpiDriverConfig::new().dma(spi::Dma::Disabled),
&spi::SpiConfig::new().baudrate(40.MHz().into()),
)?,
gpio::PinDriver::output(dc)?,
);
let mut display = mipidsi::Builder::st7789(di)
.init(&mut delay::Ets, Some(gpio::PinDriver::output(rst)?))
.map_err(|e| anyhow::anyhow!("Display error: {:?}", e))?;
display
.clear(RgbColor::RED)
.map_err(|e| anyhow::anyhow!("Display error: {:?}", e))?;
loop {
}
}
If you look at the picture, and what is written here, this board is not using SPI at all, but I8080 (parallel IO) instead.
Closing. Feel free to open an issue for support for I8080 in esp-idf-hal
. Ot better yet - contribute a PR for it.
Ah okay, I see so the examples on this project are not applicable .. okay I will try to figure out what to do, first time touching microcontrollers so I'm not really familiar with any of the terms yet..
What we need is to wrap - in Rust - in esp-idf-hal
- bits and pieces of this ESP IDF C component that implements the I8080 interface: https://github.com/espressif/esp-idf/tree/master/components/esp_lcd
It is documented here.
You can actually use this component (even if with unsafe API calls into C which we can easily expose in esp-idf-sys
).
But then again - join the Matrix chat and we can discuss there: https://matrix.to/#/#esp-rs:matrix.org
Hi thanks for the tip, I was able to figure it out after you mentioned that my board uses parallel io here was the solution:
fn main() -> anyhow::Result<()> {
esp_idf_sys::link_patches();
let peripherals = Peripherals::take().unwrap();
let mut backlight = PinDriver::output(peripherals.pins.gpio38)?;
let dc = PinDriver::output(peripherals.pins.gpio7)?;
let mut cs = PinDriver::output(peripherals.pins.gpio6)?;
let mut rst = PinDriver::output(peripherals.pins.gpio5)?;
let wr = PinDriver::output(peripherals.pins.gpio8)?;
let mut rd = PinDriver::output(peripherals.pins.gpio9)?;
backlight.set_high()?;
// set to low to enable display
cs.set_low()?;
// set to high when not in use
rd.set_high()?;
let mut d0 = PinDriver::output(peripherals.pins.gpio39)?;
let mut d1 = PinDriver::output(peripherals.pins.gpio40)?;
let mut d2 = PinDriver::output(peripherals.pins.gpio41)?;
let mut d3 = PinDriver::output(peripherals.pins.gpio42)?;
let mut d4 = PinDriver::output(peripherals.pins.gpio45)?;
let mut d5 = PinDriver::output(peripherals.pins.gpio46)?;
let mut d6 = PinDriver::output(peripherals.pins.gpio47)?;
let mut d7 = PinDriver::output(peripherals.pins.gpio48)?;
let bus = Generic8BitBus::new((d0, d1, d2, d3, d4, d5, d6, d7))
.map_err(|e| anyhow::anyhow!("Display error: {:?}", e))?;
let di = PGPIO8BitInterface::new(bus, dc, wr);
let mut display = mipidsi::Builder::st7789(di)
.with_display_size(170, 320)
.with_invert_colors(ColorInversion::Inverted)
.init(&mut delay::FreeRtos, Some(rst))
.map_err(|e| anyhow::anyhow!("Display error: {:?}", e))?;
display.clear(RgbColor::RED)
.map_err(|e| anyhow::anyhow!("Display error: {:?}", e))?;
loop {
}
}
I joined the matrix chat!
Hi thanks for the tip, I was able to figure it out after you mentioned that my board uses parallel io here was the solution:
fn main() -> anyhow::Result<()> { esp_idf_sys::link_patches(); let peripherals = Peripherals::take().unwrap(); let mut backlight = PinDriver::output(peripherals.pins.gpio38)?; let dc = PinDriver::output(peripherals.pins.gpio7)?; let mut cs = PinDriver::output(peripherals.pins.gpio6)?; let mut rst = PinDriver::output(peripherals.pins.gpio5)?; let wr = PinDriver::output(peripherals.pins.gpio8)?; let mut rd = PinDriver::output(peripherals.pins.gpio9)?; backlight.set_high()?; // set to low to enable display cs.set_low()?; // set to high when not in use rd.set_high()?; let mut d0 = PinDriver::output(peripherals.pins.gpio39)?; let mut d1 = PinDriver::output(peripherals.pins.gpio40)?; let mut d2 = PinDriver::output(peripherals.pins.gpio41)?; let mut d3 = PinDriver::output(peripherals.pins.gpio42)?; let mut d4 = PinDriver::output(peripherals.pins.gpio45)?; let mut d5 = PinDriver::output(peripherals.pins.gpio46)?; let mut d6 = PinDriver::output(peripherals.pins.gpio47)?; let mut d7 = PinDriver::output(peripherals.pins.gpio48)?; let bus = Generic8BitBus::new((d0, d1, d2, d3, d4, d5, d6, d7)) .map_err(|e| anyhow::anyhow!("Display error: {:?}", e))?; let di = PGPIO8BitInterface::new(bus, dc, wr); let mut display = mipidsi::Builder::st7789(di) .with_display_size(170, 320) .with_invert_colors(ColorInversion::Inverted) .init(&mut delay::FreeRtos, Some(rst)) .map_err(|e| anyhow::anyhow!("Display error: {:?}", e))?; display.clear(RgbColor::RED) .map_err(|e| anyhow::anyhow!("Display error: {:?}", e))?; loop { } }
Nothing wrong with this solution per se, but have in mind that it uses (if I'm not mistaken) bit-banging to send the data to the screen. In other words, it'll keep your CPU busy while the data is being transferred. Which might or might not be a problem for you. Maybe not - initially - and for "playing with stuff".
The C drivers I was pointing you at are wrapping the native ESP32-S3 LED/CAM peripheral, which can utilize DMA for pushing the pixels to the screen. During that time your CPU is free to do something else more useful. This is specific for the S3 MCU though. And hence why hardware folks started bundling I8080-based LED screens with this MCU. Your pure-Rust solution is generic though and would work on any MCU that has a bunch of output pins available.
I joined the matrix chat!
Welcome!
Btw I'm surprised that this works at all:
.init(&mut delay::FreeRtos, Some(rst))
The FreeRtos
"delayer" is only useful for delays >= 10ms as that's its minimal resolution. I was expecting the I8080 bitbanging to use much smaller delays (for which you should use Ets
instead). Oh well.
The difference between FreeRtos
and Ets
is that with FreeRtos
your thread will properly sleep during the delay, so the CPU can be scheduled to do something else. Ets
will do a busyloop, but is more precise.
Uhm I tried to switch it to delay:Ets
but I don't see any difference, however, I do have an issue, the example software that came flashed into the board had a nice smooth intro animation, which I guess is done by drawing a sequence of images frame by frame... I'm trying to do the same but each frame takes so long to render, I can see each frame being drawn line by line ...
I'm now trying to figure out the DMA thing you mentioned to see if that solves this issue, thanks again!
Hi there .. I try to make the same "Hello World" but even in this simple code I have a problem.
it works fine with ttgo-display with SPI, but with ttgo S3 - it return display.clear(RgbColor::RED) | ^^^^^ method not found in
Display<PGPIO8BitInterface<Generic8BitBus<`
so backlight works, logig works but I can do anythinc with display (( any advice ?
upd: adding use embedded_graphics::draw_target::DrawTarget;
. resolve this issue but this is strange..
upd: adding
use embedded_graphics::draw_target::DrawTarget;
. resolve this issue but this is strange..
Nothing strange, this is how Rust works. Display<PGPIO8BitInterface<Generic8BitBus<...
does implement embedded_graphics::draw_target::DrawTarget
(and the clear
method is a method on the DrawTarget
trait), HOWEVER, to use methods from a trait, you DO need to import ("use") that trait. It is not enough to have just the implementing struct in scope.
To improve the performance by a lot you need to start the code with 'cargo espflash flash --monitor --release', or add
[profile.dev]
opt-level = 1 # a number in the range of 1-3
to your Cargo.toml file. The optimization level makes a huge difference in the execution performance.
Hi, I have a Lilygo Display S3, and I'm trying to run your
esp32s3_usb_otg
example in it, it runs fine, however, the display part is not working, (it compiles fine but nothing shows on the screen, it is all black) https://github.com/ivmarkov/rust-esp32-std-demo/blob/50ab64ed4bf51f02807864458e096c595b94cc1c/src/main.rs#L1045-L1071, I have tried to re-map the pins but no success, any idea of what I could be doing wrong?