use std::error::Error; use std::thread; use std::time::Duration; use rppal::gpio::{Gpio, OutputPin}; use rppal::spi::{Bus, Mode, SlaveSelect, Spi}; use image::RgbImage; pub struct IliDisplay { spi: Spi, dc_pin: OutputPin, reset_pin: OutputPin, led_pin: OutputPin, } // Gpio uses BCM pin numbering. BCM GPIO 23 is tied to physical pin 16. const GPIO_LED: u8 = 23; const GPIO_DC: u8 = 24; const GPIO_RESET: u8 = 25; impl IliDisplay { // Initialize an IliDisplay struct with defaults pub fn init() -> Result> { let gpio = Gpio::new()?; let dc_pin = gpio.get(GPIO_DC)?.into_output(); let led_pin = gpio.get(GPIO_LED)?.into_output(); let reset_pin = gpio.get(GPIO_RESET)?.into_output(); let spi = Spi::new(Bus::Spi0, SlaveSelect::Ss0, 10_000_000, Mode::Mode0)?; return Ok(IliDisplay { spi, dc_pin, reset_pin, led_pin }); } pub fn print_id (&mut self) { self.dc_pin.set_low(); let cmdv = [0x04, 0xFF, 0xFF, 0xFF, 0xFF]; let mut readv = [0 as u8; 5]; self.spi.transfer(&mut readv, &cmdv).map_err(|err| println!("SPI transfer error in print_id: {}", err.to_string())).unwrap(); self.dc_pin.set_high(); println!("{:#X} {:#X} {:#X} {:#X} {:#X}", readv[0], readv[1], readv[2], readv[3], readv[4]); } pub fn send_command (&mut self, command: u8, data: &[u8]) { // set DC low for byte one self.dc_pin.set_low(); let mut cmdr = [0]; self.spi.transfer(&mut cmdr, &[command]).map_err(|err| println!("SPI transfer error in send_command (command): {}", err.to_string())).unwrap(); self.dc_pin.set_high(); if data.len() > 0 { let mut full_readv = [0 as u8; 4096]; // let mut readv = array_ref![full_readv, 0, data.len()]; self.spi.transfer(&mut full_readv, &data).map_err(|err| println!("SPI transfer error in send_command (data): {}", err.to_string())).unwrap(); } } // Send initialization sequence to Ili9488 pub fn init_chip(&mut self) { self.dc_pin.set_high(); // drop the reset pin to low and set it high again to fully reset the display self.reset_pin.set_high(); thread::sleep(Duration::from_millis(50)); self.reset_pin.set_low(); thread::sleep(Duration::from_millis(50)); self.reset_pin.set_high(); thread::sleep(Duration::from_millis(150)); self.send_command(0x01, &[]); thread::sleep(Duration::from_millis(50)); self.send_command(0x28, &[]); // gamma setup self.send_command(0xE0, &[0x00, 0x03, 0x09, 0x08, 0x16, 0x0A, 0x3F, 0x78, 0x4C, 0x09, 0x0A, 0x08, 0x16, 0x1A, 0x0F]); self.send_command(0xE1, &[0x00, 0x16, 0x19, 0x03, 0x0F, 0x05, 0x32, 0x45, 0x46, 0x04, 0x0E, 0x0D, 0x35, 0x37, 0x0F]); // self.send_command(0xC0, &[0x17, 0x15]); self.send_command(0xC1, &[0x41]); self.send_command(0x36, &[0xE8]); self.send_command(0x3A, &[0x66]); //self.send_command(0xB0, &[0x80]); self.send_command(0xB1, &[0xA0]); self.send_command(0xB4, &[0x02]); // Display Function Control self.send_command(0xB6, &[0x02, 0x02]); // 0x3B self.send_command(0xE9, &[0x00]); self.send_command(0xF7, &[0xA9, 0x51, 0x2C, 0x82]); self.send_command(0x11, &[]); thread::sleep(Duration::from_millis(100)); self.send_command(0x29, &[]); thread::sleep(Duration::from_millis(20)); } pub fn turn_on (&mut self) { self.led_pin.set_high(); } pub fn turn_off (&mut self) { self.led_pin.set_low(); } pub fn put_image(&mut self, image: &RgbImage, (x, y): (u32, u32)) -> () { let (w, h) = image.dimensions(); let x_extent = (x+w-1) as u16; let y_extent = (y+h-1) as u16; self.send_command(0x2A, &[(x >> 8) as u8, (x & 0xFF) as u8, (x_extent >> 8) as u8, (x_extent & 0xFF) as u8]); self.send_command(0x2B, &[(y >> 8) as u8, (y & 0xFF) as u8, (y_extent >> 8) as u8, (y_extent & 0xFF) as u8]); self.send_command(0x2C, &[]); // let image_data = image.into_raw(); for c in image.chunks(4096) { self.spi.write(&c).map_err(|err| println!("SPI error in put_image: {}", err.to_string())).unwrap(); } /* let image_data = image.as_ptr(); // we can send 4096 byte at a time let to_send = image_data.len(); let full_blocks = to_send / 4096; let mut pointer = 0; for i in 0..full_blocks { self.spi.write(&image_data[pointer .. (pointer+4096) ]).map_err(|err| println!("SPI error in put_image (4096): {}", err.to_string())).unwrap(); pointer = pointer + 4096; } let remains = to_send - pointer; if remains > 0 { self.spi.write(&image_data[pointer .. (pointer+remains)]).map_err(|err| println!("SPI error in put_imnage (remains): {}", err.to_string())).unwrap(); } */ } // send one image to the display pub fn send_image(&mut self, image: RgbImage) -> () { // assume 480x320 for both image and screen self.send_command(0x2A, &[0, 0, (480 >> 8) as u8, (480 & 0xFF) as u8]); self.send_command(0x2B, &[0, 0, (320 >> 8) as u8, (320 & 0xFF) as u8]); self.send_command(0x2C, &[]); let imagedata = image.into_raw(); // let imagedata_ref = array_ref![imagedata, 0, 480*320*3]; // self.spi.write(imagedata_ref); for y in 0..320 { let imagedata_ref = array_ref![imagedata, y*480*3, 480*3]; self.spi.write(imagedata_ref).map_err(|err| println!("SPI error in send_image: {}", err.to_string())).unwrap(); } } pub fn update(&mut self) -> () { } }