Closed mutantbob closed 2 years ago
Hmm, you mentioned your MCU before is usign usize < 32bit. I wonder if this has to do with the way pixel data is formatted prior to SPI push.
As for the init, the reason for splitting it away from the constructor is to avoid sending SPI signals on creation so you can have objects ready and move ownership before going into actual data sending phase.
I think you are on to something. This appears to do r5g6b5:
fn experimental_clear(monitor: &mut ST7789<DI, RST>, fill: u16) {
match 1 {
1 => {
let dim1 = 240;
let dim2 = 320;
let pixels = (0..(dim1 as u32 * dim2 as u32))
.map(|_| [(fill >> 8) as u8, fill as u8])
.flatten();
monitor.set_address_window(0, 0, dim1, dim2);
unsafe {
monitor.write_command1i(Instruction::RAMWR as u8, Some(pixels));
}
}
_ => {
monitor.clear(Rgb565::from(RawU16::new(fill)));
}
}
}
OK, now I think there are compiler bugs.
fn debug_check1(serial: &mut dyn uWrite<Error = Void>) {
use byte_slice_cast::AsByteSlice;
let pixels = [0xf800u16, 0x07e0, 0x001f];
let be0 = pixels[0].swap_bytes();
let _ = uwriteln!(
serial,
"wat {} {} {}",
pixels[0].to_be(),
pixels[1].to_be(),
pixels[2].to_be()
);
let mut buf = [0u16; 3];
{
let mut i = 0;
for pixel in pixels.map(u16::to_be) {
buf[i] = pixel;
i += 1;
}
let _ = uwriteln!(serial, "debug buf {:?} mapped", buf);
}
{
let mut i = 0;
for pixel in pixels {
buf[i] = pixel;
i += 1;
}
let _ = uwriteln!(serial, "debug buf {:?} copied", buf);
}
{
let mut i = 0;
for pixel in pixels {
buf[i] = pixel.to_be();
i += 1;
}
let _ = uwriteln!(serial, "debug buf {:?} in-loop", buf);
}
{
let mut i = 0;
for (i, pixel) in pixels.iter().enumerate() {
buf[i] = pixel.to_be();
}
let _ = uwriteln!(serial, "debug buf {:?} enumerate", buf);
}
let boo = buf.as_byte_slice();
let _ = uwriteln!(serial, "debug as_byte_slice() {:?}", boo);
}
gives me
wat 248 57351 7936
debug buf [0, 57568, 7967] mapped
debug buf [63488, 2016, 31] copied
debug buf [0, 57568, 7967] in-loop
debug buf [248, 57351, 7936] enumerate
debug as_byte_slice() [248, 0, 7, 224, 0, 31]
I have reduced it to a tiny app independent of the st7789 and submitted it as a possible rust bug: https://github.com/rust-lang/rust/issues/98167
Based on the fact that rust is mistakenly doubling the LSB, I think the reason I was tricked into thinking it was r3b2g3 is that 0xe0 becomes red=224, green=28, blue=0 0x18 becomes red=24, green=0, blue=24 0x07 becomes red=0, green=224, blue=7
Any chance you could get the assembly out of this? I'm not good at AVR assembly either but that's probably the only way we can get deeper. Preferably in combination with the working example from the rust issue you created.
I lack the knowledge to interpret these. The diffs between the good and bad assembly are rather large. I created the diffs using https://github.com/mutantbob/rust-avr-code-generation-bug/blob/main/compare-disassembly.sh
I think the nightly-2022-07-08
release of the compiler fixed the underlying bug. I can now display the Welsh flag correctly. It also sorted out some weird behavior in the ufmt crate.
I have been trying to port the pictureEmbed example from the ILI9341 Adafruit C++ examples for use with the https://www.adafruit.com/product/4311 that I purchased.
I have succeeded using the Adafruit_ST7789.h library. But when I try to create a rust version, the colors are all messed up. After a fair bit of experimentation I have determined that 0x00e0 is red, 0x0007 is green, 0x0018 is blue, and 0xff00 is black. I have been using the
clear()
andset_pixels()
functions in my experiments.monitor.clear(Rgb565::from(RawU16::new(0x0018)));
I have yet to figure out how to make the rust library work like the Adafruit C++ library, although I have experimented with making the initialization sequence for the rust
init()
function look more like theirs. This did not solve the problem. (The fact thatinit()
is a separate function that you can skip is suspicious).