From 6fedae8e7330f3029f1fc884a3b03eb3e6111fb2 Mon Sep 17 00:00:00 2001 From: bunnie Date: Fri, 4 Oct 2024 13:07:34 +0800 Subject: [PATCH] implement logo drawing for oled --- loader/src/platform/cramium/bootlogo.rs | 145 ++++++------------------ 1 file changed, 35 insertions(+), 110 deletions(-) diff --git a/loader/src/platform/cramium/bootlogo.rs b/loader/src/platform/cramium/bootlogo.rs index ab7d4c302..e5cbaa2f3 100644 --- a/loader/src/platform/cramium/bootlogo.rs +++ b/loader/src/platform/cramium/bootlogo.rs @@ -1,114 +1,39 @@ -use core::mem::size_of; +use cramium_hal::iox::{IoGpio, IoSetup}; +use cramium_hal::udma::UdmaGlobalConfig; -use cramium_hal::ifram::IframRange; -use cramium_hal::iox::{IoSetup, Iox}; -use cramium_hal::udma::{GlobalConfig, PeriphId}; -use cramium_hal::{iox, udma}; - -pub const FB_WIDTH_WORDS: usize = 11; -pub const FB_LINES: usize = 536; - -pub fn show_logo(pclk_freq: u32, udma_global: &mut GlobalConfig, iox: &mut Iox) { - let channel = { - const SPI_CS_PIN: u8 = 5; - const SPI_CLK_PIN: u8 = 4; - const SPI_DAT_PIN: u8 = 0; - const SPI_PORT: iox::IoxPort = iox::IoxPort::PD; - - // SPIM_CLK_A[0] - iox.setup_pin( - SPI_PORT, - SPI_CLK_PIN, - Some(iox::IoxDir::Output), - Some(iox::IoxFunction::AF1), - None, - None, - Some(iox::IoxEnable::Enable), - Some(iox::IoxDriveStrength::Drive2mA), - ); - // SPIM_SD0_A[0] - iox.setup_pin( - SPI_PORT, - SPI_DAT_PIN, - Some(iox::IoxDir::Output), - Some(iox::IoxFunction::AF1), - None, - None, - Some(iox::IoxEnable::Enable), - Some(iox::IoxDriveStrength::Drive2mA), - ); - // SPIM_CSN0_A[0] - // chip select toggle by UDMA has ~6 cycles setup and 1 cycles hold time, which - // meets the requirements for the display. - iox.setup_pin( - SPI_PORT, - SPI_CS_PIN, - Some(iox::IoxDir::Output), - Some(iox::IoxFunction::AF1), - None, - Some(iox::IoxEnable::Enable), - Some(iox::IoxEnable::Enable), - Some(iox::IoxDriveStrength::Drive2mA), - ); - // using bank SPIM_B[1] - udma_global.clock_on(PeriphId::Spim0); - udma::SpimChannel::Channel0 - }; - - // safety: this is safe because we remembered to set up the clock config; and, - // this binding should live for the lifetime of Xous so we don't have to worry about unmapping. - let mut spim = unsafe { - cramium_hal::udma::Spim::new_with_ifram( - channel, - 2_000_000, - pclk_freq, - udma::SpimClkPol::LeadingEdgeRise, - udma::SpimClkPha::CaptureOnLeading, - udma::SpimCs::Cs0, - 3, - 2, - None, - // one extra line for handling the addressing setup - (FB_LINES + 1) * FB_WIDTH_WORDS * size_of::(), - 0, - None, - None, - IframRange::from_raw_parts(utralib::HW_IFRAM0_MEM, utralib::HW_IFRAM0_MEM, 24576), - ) - }; - - let mut next_free_line = 0; - let hwfb = spim.tx_buf_mut(); - // safety: this is safe because `u32` has no invalid values - // set the mode and address - // the very first line is unused, except for the mode & address info - // this is done just to keep the math easy for computing strides & alignments - for src_line in 0..FB_LINES { - hwfb[(next_free_line + 1) * FB_WIDTH_WORDS - 1] = (hwfb[(next_free_line + 1) * FB_WIDTH_WORDS - 1] - & 0x0000_FFFF) - | (((src_line as u32) << 6) | 0b001) << 16; - // now copy the data - hwfb[(next_free_line + 1) * FB_WIDTH_WORDS..(next_free_line + 2) * FB_WIDTH_WORDS].copy_from_slice( - &crate::platform::cramium::poweron_bt::LOGO_MAP - [src_line * FB_WIDTH_WORDS..(src_line + 1) * FB_WIDTH_WORDS], - ); - - if next_free_line < FB_LINES as usize { - next_free_line += 1; +pub fn show_logo(pclk_freq: u32, udma_global: &dyn UdmaGlobalConfig, iox: &T) +where + T: IoSetup + IoGpio, +{ + // test the display SPI interface + // safety: this is called exactly once on boot + let mut sh1107 = cramium_hal::sh1107::Oled128x128::new(iox, udma_global); + sh1107.init(); + { + /* // pattern test for debugging pixel orientations - done with this now, I think? + let buf = sh1107.buffer_mut(); + crate::println!("oled test"); + for (i, chunk) in buf.chunks_mut(128).enumerate() { + for (j, pixel) in chunk.iter_mut().enumerate() { + // *pixel = (i as u8) << 5 + j as u8; + if j % 2 == 0 { + *pixel = 0x55 + i as u8; + } else { + *pixel = 0xAA + i as u8; + } + } + } + crate::println!("oled test end"); + */ + sh1107.buffer_mut().fill(0); + for (i, b) in crate::platform::cramium::poweron_bt::LOGO_MAP.iter().enumerate() { + for bit in 0..8 { + if (b & (1 << (7 - bit))) != 0 { + sh1107.put_pixel(((i % 16) * 8 + bit) as u8, (i / 16) as u8, true); + } + } } } - - // safety: this function is safe to call because: - // - `is_virtual` is `false` => data should be a physical buffer that is pre-populated with the transmit - // data this is done by `copy_line_to_dma()` - // - the `data` argument is a physical buffer slice, which is only used as a base/bounds argument - unsafe { - spim.tx_data_async_from_parts::( - FB_WIDTH_WORDS * 2 - 1, - // +1 for the trailing dummy bits - next_free_line * FB_WIDTH_WORDS * 2 + 1, - true, - false, - ); - } + sh1107.buffer_swap(); + sh1107.draw(); }