diff --git a/Cargo.lock b/Cargo.lock index eb43295e1..6b469c2a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -936,6 +936,7 @@ version = "0.1.0" dependencies = [ "bitfield", "bitflags 1.3.2", + "either", "log", "num-derive 0.3.3", "num-traits", diff --git a/imports/getrandom/Cargo.lock b/imports/getrandom/Cargo.lock index 1b10fe4d4..73a6523c9 100644 --- a/imports/getrandom/Cargo.lock +++ b/imports/getrandom/Cargo.lock @@ -160,28 +160,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rkyv" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70de01b38fe7baba4ecdd33b777096d2b326993d8ea99bc5b6ede691883d3010" -dependencies = [ - "memoffset", - "ptr_meta", - "rkyv_derive", -] - -[[package]] -name = "rkyv_derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a169f6bc5a81033e86ed39d0f4150e2608160b73d2b93c6e8e6a3efa873f14" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "rustc-std-workspace-alloc" version = "1.0.0" diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index c2ce63cac..2c2a1a07e 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -46,6 +46,10 @@ unexpected_cfgs = { level = "warn", check-cfg = ['cfg(ci)', 'cfg(baremetal)'] } [features] cramium-soc = ["utralib/cramium-soc", "cramium-hal", "rand_chacha", "raw-trng"] cramium-fpga = ["utralib/cramium-fpga"] +board-baosec = ["cramium-hal/board-baosec"] +board-baosor = ["cramium-hal/board-baosor"] +board-dabao = ["cramium-hal/board-dabao"] + atsama5d27 = ["utralib/atsama5d27"] precursor = ["utralib/precursor"] hosted = ["utralib/hosted"] diff --git a/libs/cramium-hal/Cargo.toml b/libs/cramium-hal/Cargo.toml index 8954d2183..0c332d808 100644 --- a/libs/cramium-hal/Cargo.toml +++ b/libs/cramium-hal/Cargo.toml @@ -21,13 +21,18 @@ num-traits = { version = "0.2.14", default-features = false } riscv = { version = "0.5.6", package = "xous-riscv" } usb-device = { version = "0.2.8", features = ["log"], optional = true } bitfield = "0.13.2" +either = { version = "1.9.0", default-features = false } # [target.'cfg(target_os = "xous")'.dependencies] xous = { version = "0.9.64", features = ["v2p"] } [features] +board-baosec = [] # USB form factor token +board-baosor = [] # Precursor form factor +board-dabao = [] # Dev board form factor + compress-entropy = [] magic-manual = [] std = ["log", "xous-api-names", "usb-device"] derive-rkyv = ["rkyv"] -default = [] +default = ["board-baosec"] diff --git a/libs/cramium-hal/src/board/baosec.rs b/libs/cramium-hal/src/board/baosec.rs new file mode 100644 index 000000000..879edb584 --- /dev/null +++ b/libs/cramium-hal/src/board/baosec.rs @@ -0,0 +1,138 @@ +// Constants that define pin locations, RAM offsets, etc. for the BaoSec board +use crate::iox; +use crate::iox::IoSetup; +use crate::iox::*; + +// console uart buffer +pub const UART_DMA_TX_BUF_PHYS: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 4096; + +// RAM needs two buffers of 1k + 16 bytes = 2048 + 16 = 2064 bytes; round up to one page +pub const SPIM_RAM_IFRAM_ADDR: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 2 * 4096; + +// app uart buffer +pub const APP_UART_IFRAM_ADDR: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 3 * 4096; + +// display buffer: 1 page for double-buffering, rounded up to 1 page for commands +pub const DISPLAY_IFRAM_ADDR: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 5 * 4096; + +// Flash needs 4096 bytes for Rx, and 0 bytes for Tx + 16 bytes for cmd for 2 pages total. This is released +// after boot. +pub const SPIM_FLASH_IFRAM_ADDR: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 7 * 4096; + +// USB pages - USB subsystem is a hog, needs a lot of pages +pub const CRG_IFRAM_PAGES: usize = 22; +pub const CRG_UDC_MEMBASE: usize = + utralib::HW_IFRAM1_MEM + utralib::HW_IFRAM1_MEM_LEN - CRG_IFRAM_PAGES * 0x1000; + +// MANUALLY SYNCED TO ALLOCATIONS ABOVE +// inclusive numbering - we allocate pages from the top-down, so the last number should generally be 31 +pub const IFRAM0_RESERVED_PAGE_RANGE: [usize; 2] = [31 - 7, 31]; +pub const IFRAM1_RESERVED_PAGE_RANGE: [usize; 2] = [31 - CRG_IFRAM_PAGES, 31]; + +/// Setup pins for the baosec display +/// Returns a spi channel object and descriptor for the C/D + CS pins as a (port, c/d pin, cs pin) tuple +pub fn setup_display_pins(iox: &dyn IoSetup) -> (crate::udma::SpimChannel, iox::IoxPort, u8, u8) { + const SPI_CS_PIN: u8 = 3; + const SPI_CLK_PIN: u8 = 0; + const SPI_DAT_PIN: u8 = 1; + const SPI_CD_PIN: u8 = 2; + const SPI_PORT: iox::IoxPort = iox::IoxPort::PC; + + // SPIM_CLK_B[2] + iox.setup_pin( + SPI_PORT, + SPI_CLK_PIN, + Some(iox::IoxDir::Output), + Some(iox::IoxFunction::AF2), + None, + None, + Some(iox::IoxEnable::Enable), + Some(iox::IoxDriveStrength::Drive2mA), + ); + // SPIM_SD0_B[2] + iox.setup_pin( + SPI_PORT, + SPI_DAT_PIN, + Some(iox::IoxDir::Output), + Some(iox::IoxFunction::AF2), + None, + None, + Some(iox::IoxEnable::Enable), + Some(iox::IoxDriveStrength::Drive2mA), + ); + // SPIM_CSN0_B[2] + iox.setup_pin( + SPI_PORT, + SPI_CS_PIN, + Some(iox::IoxDir::Output), + Some(iox::IoxFunction::AF2), + None, + Some(iox::IoxEnable::Enable), + Some(iox::IoxEnable::Enable), + Some(iox::IoxDriveStrength::Drive2mA), + ); + // C/D pin is a gpio direct-drive + iox.setup_pin( + SPI_PORT, + SPI_CD_PIN, + Some(iox::IoxDir::Output), + Some(IoxFunction::Gpio), + None, + None, + Some(IoxEnable::Enable), + Some(iox::IoxDriveStrength::Drive2mA), + ); + // using bank SPIM_B[2] + (crate::udma::SpimChannel::Channel2, SPI_PORT, SPI_CD_PIN, SPI_CS_PIN) +} + +pub fn setup_memory_pins(iox: &dyn IoSetup) -> crate::udma::SpimChannel { + // JPC7_13 + // SPIM_CLK_A[1] + iox.setup_pin( + IoxPort::PC, + 11, + Some(IoxDir::Output), + Some(IoxFunction::AF1), + None, + None, + Some(IoxEnable::Enable), + Some(IoxDriveStrength::Drive4mA), + ); + // SPIM_SD[0-3]_A[1] + for i in 7..11 { + iox.setup_pin( + IoxPort::PC, + i, + None, + Some(IoxFunction::AF1), + None, + None, + Some(IoxEnable::Enable), + Some(IoxDriveStrength::Drive2mA), + ); + } + // SPIM_CSN0_A[1] + iox.setup_pin( + IoxPort::PC, + 12, + Some(IoxDir::Output), + Some(IoxFunction::AF1), + None, + None, + Some(IoxEnable::Enable), + Some(IoxDriveStrength::Drive2mA), + ); + // SPIM_CSN0_A[1] + iox.setup_pin( + IoxPort::PC, + 13, + Some(IoxDir::Output), + Some(IoxFunction::AF1), + None, + None, + Some(IoxEnable::Enable), + Some(IoxDriveStrength::Drive2mA), + ); + crate::udma::SpimChannel::Channel1 +} diff --git a/libs/cramium-hal/src/board/baosor.rs b/libs/cramium-hal/src/board/baosor.rs new file mode 100644 index 000000000..03d0bef35 --- /dev/null +++ b/libs/cramium-hal/src/board/baosor.rs @@ -0,0 +1,123 @@ +// Constants that define pin locations, RAM offsets, etc. for the BaoSec board +use crate::iox; +use crate::iox::IoSetup; + +// console uart buffer +pub const UART_DMA_TX_BUF_PHYS: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 4096; + +// RAM needs two buffers of 1k + 16 bytes = 2048 + 16 = 2064 bytes; round up to one page +pub const SPIM_RAM_IFRAM_ADDR: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 2 * 4096; + +// app uart buffer +pub const APP_UART_IFRAM_ADDR: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 3 * 4096; + +// Flash needs 4096 bytes for Rx, and 0 bytes for Tx + 16 bytes for cmd for 2 pages total. This is released +// after boot. +pub const SPIM_FLASH_IFRAM_ADDR: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 5 * 4096; + +// USB pages - USB subsystem is a hog, needs a lot of pages +pub const CRG_IFRAM_PAGES: usize = 22; +pub const CRG_UDC_MEMBASE: usize = + utralib::HW_IFRAM1_MEM + utralib::HW_IFRAM1_MEM_LEN - CRG_IFRAM_PAGES * 0x1000; + +// MANUALLY SYNCED TO ALLOCATIONS ABOVE +// inclusive numbering - we allocate pages from the top-down, so the last number should generally be 31 +pub const IFRAM0_RESERVED_PAGE_RANGE: [usize; 2] = [31 - 5, 31]; +pub const IFRAM1_RESERVED_PAGE_RANGE: [usize; 2] = [31 - CRG_IFRAM_PAGES, 31]; + +/// Setup pins for the baosor display (Precursor memory LCD target) +pub fn setup_display_pins(iox: &dyn IoSetup) -> crate::udma::SpimChannel { + 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] + crate::udma::SpimChannel::Channel0 +} + +pub fn setup_memory_pins(iox: &dyn IoSetup) -> crate::udma::SpimChannel { + // JPC7_13 + // SPIM_CLK_A[1] + iox.setup_pin( + IoxPort::PC, + 11, + Some(IoxDir::Output), + Some(IoxFunction::AF1), + None, + None, + Some(IoxEnable::Enable), + Some(IoxDriveStrength::Drive4mA), + ); + // SPIM_SD[0-3]_A[1] + for i in 7..11 { + iox.setup_pin( + IoxPort::PC, + i, + None, + Some(IoxFunction::AF1), + None, + None, + Some(IoxEnable::Enable), + Some(IoxDriveStrength::Drive2mA), + ); + } + // SPIM_CSN0_A[1] + iox.setup_pin( + IoxPort::PC, + 12, + Some(IoxDir::Output), + Some(IoxFunction::AF1), + None, + None, + Some(IoxEnable::Enable), + Some(IoxDriveStrength::Drive2mA), + ); + // SPIM_CSN0_A[1] + iox.setup_pin( + IoxPort::PC, + 13, + Some(IoxDir::Output), + Some(IoxFunction::AF1), + None, + None, + Some(IoxEnable::Enable), + Some(IoxDriveStrength::Drive2mA), + ); + crate::udma::SpimChannel::Channel1 +} diff --git a/libs/cramium-hal/src/board/mod.rs b/libs/cramium-hal/src/board/mod.rs new file mode 100644 index 000000000..f8d67d674 --- /dev/null +++ b/libs/cramium-hal/src/board/mod.rs @@ -0,0 +1,8 @@ +#[cfg(feature = "board-baosec")] +pub mod baosec; +#[cfg(feature = "board-baosec")] +pub use baosec::*; +#[cfg(feature = "board-baosor")] +pub mod baosor; +#[cfg(feature = "board-baosor")] +pub use baosor::*; diff --git a/libs/cramium-hal/src/iox.rs b/libs/cramium-hal/src/iox.rs index 319a441fb..113714f27 100644 --- a/libs/cramium-hal/src/iox.rs +++ b/libs/cramium-hal/src/iox.rs @@ -1,5 +1,6 @@ use utralib::generated::utra::iox; -use utralib::generated::*; + +use crate::SharedCsr; macro_rules! set_pin_in_bank { ($self:expr, $register:expr, $port:expr, $pin:expr, $val:expr) => {{ @@ -67,7 +68,7 @@ pub enum IoxEnable { } #[cfg_attr(feature = "derive-rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] #[repr(u32)] pub enum IoxValue { Low = 0, @@ -78,26 +79,48 @@ impl From for IoxValue { fn from(value: u32) -> Self { if value == 0 { IoxValue::Low } else { IoxValue::High } } } +/// Use a trait that will allow us to share code between both `std` and `no-std` implementations +pub trait IoSetup { + fn setup_pin( + &self, + port: IoxPort, + pin: u8, + direction: Option, + function: Option, + schmitt_trigger: Option, + pullup: Option, + slow_slew: Option, + strength: Option, + ); +} + +/// Traits for accessing GPIOs after the port has been set up. +pub trait IoGpio { + fn set_gpio_pin_value(&self, port: IoxPort, pin: u8, value: IoxValue); + fn get_gpio_pin_value(&self, port: IoxPort, pin: u8) -> IoxValue; + fn set_gpio_pin_dir(&self, port: IoxPort, pin: u8, dir: IoxDir); +} + pub struct Iox { - pub csr: CSR, + pub csr: SharedCsr, } impl Iox { - pub fn new(base_address: *mut u32) -> Self { Iox { csr: CSR::new(base_address) } } + pub fn new(base_address: *mut u32) -> Self { Iox { csr: SharedCsr::new(base_address) } } - pub fn set_gpio_dir(&mut self, port: IoxPort, pin: u8, direction: IoxDir) { + pub fn set_gpio_dir(&self, port: IoxPort, pin: u8, direction: IoxDir) { set_pin_in_bank!(self, iox::SFR_GPIOOE_CRGOE0, port, pin, direction) } - pub fn set_gpio_pullup(&mut self, port: IoxPort, pin: u8, enable: IoxEnable) { + pub fn set_gpio_pullup(&self, port: IoxPort, pin: u8, enable: IoxEnable) { set_pin_in_bank!(self, iox::SFR_GPIOPU_CRGPU0, port, pin, enable) } - pub fn set_gpio_pin(&mut self, port: IoxPort, pin: u8, value: IoxValue) { + pub fn set_gpio_pin(&self, port: IoxPort, pin: u8, value: IoxValue) { set_pin_in_bank!(self, iox::SFR_GPIOOUT_CRGO0, port, pin, value) } - pub fn set_gpio_bank(&mut self, port: IoxPort, value: u16, mask: u16) { + pub fn set_gpio_bank(&self, port: IoxPort, value: u16, mask: u16) { // safety: it is safe to manipulate a raw pointer because IoxPort constrains // the offset to be within range. unsafe { @@ -109,11 +132,11 @@ impl Iox { } } - pub fn set_gpio_schmitt_trigger(&mut self, port: IoxPort, pin: u8, enable: IoxEnable) { + pub fn set_gpio_schmitt_trigger(&self, port: IoxPort, pin: u8, enable: IoxEnable) { set_pin_in_bank!(self, iox::SFR_CFG_SCHM_CR_CFG_SCHMSEL0, port, pin, enable) } - pub fn set_slow_slew_rate(&mut self, port: IoxPort, pin: u8, enable: IoxEnable) { + pub fn set_slow_slew_rate(&self, port: IoxPort, pin: u8, enable: IoxEnable) { set_pin_in_bank!(self, iox::SFR_CFG_SLEW_CR_CFG_SLEWSLOW0, port, pin, enable) } @@ -141,7 +164,7 @@ impl Iox { } } - pub fn set_alternate_function(&mut self, port: IoxPort, pin: u8, function: IoxFunction) { + pub fn set_alternate_function(&self, port: IoxPort, pin: u8, function: IoxFunction) { assert!(pin < 16, "pin must be in range of 0-15"); match port { IoxPort::PA => { @@ -248,7 +271,7 @@ impl Iox { /// by the mapping request. The index of the array corresponds to the bit position in /// the bitmask. You may use this to pass as arguments to further functions /// that do things like control slew rate or apply pull-ups. - pub fn set_ports_from_pio_bitmask(&mut self, enable_bitmask: u32) -> [Option<(IoxPort, u8)>; 32] { + pub fn set_ports_from_pio_bitmask(&self, enable_bitmask: u32) -> [Option<(IoxPort, u8)>; 32] { let mut mapping: [Option<(IoxPort, u8)>; 32] = [None; 32]; for i in 0..32 { @@ -310,7 +333,7 @@ impl Iox { /// Returns the PIO bit that was enabled based on the port and pin specifier given; /// returns `None` if the proposed mapping is invalid. - pub fn set_pio_bit_from_port_and_pin(&mut self, port: IoxPort, pin: u8) -> Option { + pub fn set_pio_bit_from_port_and_pin(&self, port: IoxPort, pin: u8) -> Option { match port { IoxPort::PA => None, IoxPort::PB => { @@ -340,7 +363,7 @@ impl Iox { /// Returns the PIO bit that was disabled based on the port and pin specifier given; /// returns `None` if the proposed mapping is invalid. Does not change the AF mapping, /// simply disables the bit in the PIO mux register. - pub fn unset_pio_bit_from_port_and_pin(&mut self, port: IoxPort, pin: u8) -> Option { + pub fn unset_pio_bit_from_port_and_pin(&self, port: IoxPort, pin: u8) -> Option { match port { IoxPort::PA => None, IoxPort::PB => { @@ -365,7 +388,7 @@ impl Iox { } } - pub fn set_drive_strength(&mut self, port: IoxPort, pin: u8, strength: IoxDriveStrength) { + pub fn set_drive_strength(&self, port: IoxPort, pin: u8, strength: IoxDriveStrength) { assert!(pin < 16, "pin must be in range of 0-15"); match port { IoxPort::PA => self.csr.wo( @@ -401,3 +424,46 @@ impl Iox { } } } + +impl IoSetup for Iox { + fn setup_pin( + &self, + port: IoxPort, + pin: u8, + direction: Option, + function: Option, + schmitt_trigger: Option, + pullup: Option, + slow_slew: Option, + strength: Option, + ) { + if let Some(f) = function { + self.set_alternate_function(port, pin, f); + } + if let Some(d) = direction { + self.set_gpio_dir(port, pin, d); + } + if let Some(t) = schmitt_trigger { + self.set_gpio_schmitt_trigger(port, pin, t); + } + if let Some(p) = pullup { + self.set_gpio_pullup(port, pin, p); + } + if let Some(s) = slow_slew { + self.set_slow_slew_rate(port, pin, s); + } + if let Some(s) = strength { + self.set_drive_strength(port, pin, s); + } + } +} + +impl IoGpio for Iox { + fn get_gpio_pin_value(&self, port: IoxPort, pin: u8) -> IoxValue { self.get_gpio_pin(port, pin) } + + fn set_gpio_pin_value(&self, port: IoxPort, pin: u8, value: IoxValue) { + self.set_gpio_pin(port, pin, value); + } + + fn set_gpio_pin_dir(&self, port: IoxPort, pin: u8, dir: IoxDir) { self.set_gpio_dir(port, pin, dir); } +} diff --git a/libs/cramium-hal/src/lib.rs b/libs/cramium-hal/src/lib.rs index 014e7997b..d0c328812 100644 --- a/libs/cramium-hal/src/lib.rs +++ b/libs/cramium-hal/src/lib.rs @@ -2,8 +2,12 @@ #[macro_use] pub mod debug; +pub mod board; pub mod ifram; pub mod iox; pub mod sce; +pub mod sh1107; +pub mod shared_csr; pub mod udma; pub mod usb; +pub use shared_csr::*; diff --git a/libs/cramium-hal/src/sh1107.rs b/libs/cramium-hal/src/sh1107.rs new file mode 100644 index 000000000..bb3b6d043 --- /dev/null +++ b/libs/cramium-hal/src/sh1107.rs @@ -0,0 +1,340 @@ +// `Command` vendored from https://github.com/ithinuel/sh1107-rs/tree/main +use crate::{ + ifram::IframRange, + iox::{IoGpio, IoSetup, IoxPort, IoxValue}, + udma::{PeriphId, Spim, SpimClkPha, SpimClkPol, SpimCs, UdmaGlobalConfig}, +}; + +pub const COLUMN: u8 = 128; +pub const ROW: u8 = 128; +pub const PAGE: u8 = ROW / 8; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum DisplayState { + Off, + On, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum Direction { + Normal, + Inverted, +} +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum AddressMode { + Page, + Column, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum DisplayMode { + BlackOnWhite, + WhiteOnBlack, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum Command { + SetColumnAddress(u8), + SetAddressMode(AddressMode), + SetDisplayMode(DisplayMode), + ForceEntireDisplay(bool), + SetClkDividerOscFrequency { + divider: u8, + osc_freq_ratio: i8, + }, + SetMultiplexRatio(u8), + SetStartLine(u8), + SetSegmentReMap(bool), + SetCOMScanDirection(Direction), + SetDisplayOffset(u8), + SetContrastControl(u8), + /// Set Charge & Discharge period + SetChargePeriods { + precharge: Option, + discharge: u8, + }, + SetVCOMHDeselectLevel(u8), + SetDCDCSettings(u8), + DisplayOnOff(DisplayState), + SetPageAddress(u8), + StartReadModifyWrite, + EndReadModifyWrite, + Nop, +} + +impl Command { + fn encode(self) -> impl Iterator { + use either::Either::*; + match self { + Self::SetColumnAddress(addr) => { + assert!(addr < 128); + Right([addr & 0xF, 0x10 | ((addr & 0x70) >> 4)]) + } + Self::SetAddressMode(mode) => Left(0x20 | if let AddressMode::Page = mode { 0 } else { 1 }), + Self::SetContrastControl(contrast) => Right([0x81, contrast]), + Self::SetSegmentReMap(is_remapped) => Left(0xA0 | if is_remapped { 1 } else { 0 }), + Self::SetMultiplexRatio(ratio) => { + assert!((1..=128).contains(&ratio)); + Right([0xA8, ratio - 1]) + } + Self::ForceEntireDisplay(state) => Left(0xA4 | if state { 1 } else { 0 }), + Self::SetDisplayMode(mode) => { + Left(0xA6 | if let DisplayMode::WhiteOnBlack = mode { 1 } else { 0 }) + } + Self::SetDisplayOffset(offset) => Right([0xD3, offset & 0x7F]), + Self::SetDCDCSettings(cfg) => Right([0xAD, 0x80 | (cfg & 0x0F)]), + Self::DisplayOnOff(state) => Left(0xAE | if let DisplayState::On = state { 1 } else { 0 }), + Self::SetPageAddress(addr) => { + assert!(addr < 16); + Left(0xB0 | (addr & 0x0F)) + } + Self::SetCOMScanDirection(dir) => Left(0xC0 | if let Direction::Normal = dir { 0 } else { 0x08 }), + Self::SetClkDividerOscFrequency { divider, osc_freq_ratio } => { + assert!(osc_freq_ratio % 5 == 0, "osc_freq_ratio must be a multiple of 5."); + assert!((-25..=50).contains(&osc_freq_ratio), "osc_freq_ratio must be within [-25; 50]"); + assert!((1..=16).contains(÷r), "divider must be in [1; 16]"); + + let osc_freq_ratio = osc_freq_ratio / 5 + 5; + Right([0xD5, ((osc_freq_ratio & 0xF) << 4) as u8 | (divider - 1)]) + } + Self::SetChargePeriods { precharge, discharge } => { + let precharge = if let Some(v) = precharge { + assert!((1..=15).contains(&v)); + v + } else { + 0 + }; + assert!((1..=15).contains(&discharge)); + let arg = discharge << 4 | precharge; + + Right([0xD9, arg]) + } + Self::SetVCOMHDeselectLevel(arg) => Right([0xDB, arg]), + Self::SetStartLine(line) => { + assert!(line < 128); + + Right([0xDC, line & 0x7F]) + } + Self::StartReadModifyWrite => Left(0xE0), + Self::EndReadModifyWrite => Left(0xEE), + Self::Nop => Left(0xE3), + } + .map_left(|v| [v]) + .into_iter() + } +} + +#[repr(usize)] +#[derive(Eq, PartialEq, Copy, Clone)] +enum BufferState { + A = 0, + B = 2048, +} +impl BufferState { + pub fn swap(self) -> Self { if self == BufferState::A { BufferState::B } else { BufferState::A } } + + pub fn as_index(&self) -> usize { + match self { + BufferState::A => 0, + BufferState::B => 1, + } + } +} + +pub struct Oled128x128<'a> { + spim: Spim, + // front and back buffers + buffers: [&'static mut [u8]; 2], + // length of the sideband memory region for queuing commands to the OLED. Must be allocated + // immediately after the total frame buffer length + pub sideband_len: usize, + active_buffer: BufferState, + cd_port: IoxPort, + cd_pin: u8, + cs_pin: u8, + iox: &'a dyn IoGpio, +} + +impl<'a> Oled128x128<'a> { + pub fn new(iox: &'a T, udma_global: &'a dyn UdmaGlobalConfig) -> Self + where + T: IoSetup + IoGpio, + { + let (channel, cd_port, cd_pin, cs_pin) = crate::board::setup_display_pins(iox); + udma_global.clock(PeriphId::from(channel), true); + #[cfg(not(feature = "std"))] + let ifram_vaddr = crate::board::DISPLAY_IFRAM_ADDR; + #[cfg(feature = "std")] + let ifram_vaddr = { + xous::map_memory( + xous::MemoryAddress::new(crate::board::DISPLAY_IFRAM_ADDR), + None, + 4096 * 2, + xous::MemoryFlags::R | xous::MemoryFlags::W, + ) + .expect("couldn't map window for display IFRAM") + .as_ptr() as usize + }; + // safety: safe because the udma clock is turned on, and IFRAM is pulling from + // statically allocated bank + let mut spim = unsafe { + Spim::new_with_ifram( + channel, + 2_000_000, + 50_000_000, + SpimClkPol::LeadingEdgeRise, + SpimClkPha::CaptureOnLeading, + SpimCs::Cs0, + 0, + 0, + None, + // 2x buffers reserved: (128 * 128 / 8) * 2 = 4096 + // Add 256 for display commands. + // Internally, an extra 16 is added for UDMA SPIM commands (these are commands + // to the SPIM hardware itself, not transmitted to the display). + // The +16 is not reported here because it's out of band, but we need to allocate + // an IFRAM range large enough to accommodate that. However, because we have + // to round up any allocations to a full page length, we end up with extra + // unused space. + 4096 + 256, + 0, // re-use the Tx buffer for Rx in this implementation + None, + None, + // Note: the IFRAM needs to be 16 bytes longer than the data range to accommodate + // command sending. But because we have to round up to a whole page, we end up wasting 4080 + // bytes. + IframRange::from_raw_parts(crate::board::DISPLAY_IFRAM_ADDR, ifram_vaddr, 4096 * 2), + ) + }; + spim.set_endianness(crate::udma::SpimEndian::MsbFirst); + Self { + spim, + // safety: this is safe because these ranges are in fact allocated, and all values can be + // represented. They have a static lifetime because they are mapped to hardware. There is + // in fact an unsafe front/back buffer contention, but that's the whole point of this routine, + // to safely manage that. + buffers: [unsafe { core::slice::from_raw_parts_mut(ifram_vaddr as *mut u8, 2048) }, unsafe { + core::slice::from_raw_parts_mut((ifram_vaddr + 2048) as *mut u8, 2048) + }], + sideband_len: 256, + active_buffer: BufferState::A, + cd_port, + cd_pin, + cs_pin, + iox, + } + } + + fn set_data(&self) { self.iox.set_gpio_pin_value(self.cd_port, self.cd_pin, crate::iox::IoxValue::High); } + + fn set_command(&self) { + self.iox.set_gpio_pin_value(self.cd_port, self.cd_pin, crate::iox::IoxValue::Low); + } + + pub fn buffer_swap(&mut self) { self.active_buffer = self.active_buffer.swap(); } + + pub fn buffer_mut(&mut self) -> &mut [u8] { self.buffers[self.active_buffer.as_index()] } + + pub fn buffer(&self) -> &[u8] { self.buffers[self.active_buffer.as_index()] } + + // This is needed because the UDMA block will tell you the transaction is done the moment its DMA + // is finished. There is no way, afaik, to tell if a transaction has physically finished on the pins + // without reading back the CS pin. + fn cs_active(&self) -> bool { self.iox.get_gpio_pin_value(self.cd_port, self.cs_pin) == IoxValue::Low } + + /// Transfers the back buffer + pub fn draw(&mut self) { + // this must be opposite of what `buffer` / `buffer_mut` returns + let buffer_start = self.active_buffer.swap() as usize; + let chunk_size = 128; + let chunks = self.buffer().len() / chunk_size; + // we don't do this with an iterator because it involves an immutable borrow of + // `buffer`, which prevents us from doing anything with the interface inside the loop. + for page in 0..chunks { + // The cs_active() waits are necessary because the UDMA block will eagerly report + // the transaction is done before the data is done transmitting, and we have to + // toggle set_data() only after the physical transaction is done, not after the + // the last UDMA action has been queued. + while self.cs_active() {} + self.send_command(Command::SetPageAddress(page as u8).encode()); + while self.cs_active() {} + self.send_command(Command::SetColumnAddress(0).encode()); + while self.cs_active() {} + // wait for commands to finish before toggling set_data + // self.spim.tx_data_await(false); + // crate::println!("Send page {}, offset {:x}", page, buffer_start + page * chunk_size); + self.set_data(); + // safety: data is already copied into the DMA buffer. size & len are in bounds. + unsafe { + self.spim.tx_data_async_from_parts::( + buffer_start + page * chunk_size, + chunk_size, + true, + false, + ); + } + self.spim.tx_data_await(false); + } + } + + pub fn send_command<'b, U>(&'b mut self, cmd: U) + where + U: IntoIterator + 'b, + { + self.set_command(); + let total_buf_len = self.buffers.iter().map(|x| x.len()).sum(); + let mut len = 0; // track the full length of the iterator + // emplace the command in the sideband area, which is after both frame buffers + // crate::print!("cmd: "); + let ifram_raw: &mut [u8] = self.spim.tx_buf_mut(); + for (src, dst) in cmd.into_iter().zip(ifram_raw[total_buf_len..].iter_mut()) { + // crate::print!("{:x} ", src); + *dst = src; + len += 1; + } + // crate::println!(""); + // safety: data is already copied into the DMA buffer. size & len are in bounds. + unsafe { + self.spim.tx_data_async_from_parts::(total_buf_len, len, true, false); + } + self.spim.tx_data_await(false); + } + + pub fn init(&mut self) { + use Command::*; + let init_sequence = [ + DisplayOnOff(DisplayState::Off), + SetDCDCSettings(0x0), + SetStartLine(0), + SetDisplayOffset(0), + SetContrastControl(0x4f), + SetAddressMode(AddressMode::Page), + SetSegmentReMap(true), + SetCOMScanDirection(Direction::Normal), + SetMultiplexRatio(128), + SetClkDividerOscFrequency { divider: 1, osc_freq_ratio: 5 }, + SetChargePeriods { precharge: Some(2), discharge: 2 }, + SetVCOMHDeselectLevel(0x35), + SetPageAddress(0), + ForceEntireDisplay(false), + SetDisplayMode(DisplayMode::BlackOnWhite), + DisplayOnOff(DisplayState::On), + ]; + + for command in init_sequence { + let bytes = command.encode(); + self.send_command(bytes); + } + } + + pub fn put_pixel(&mut self, x: u8, y: u8, on: bool) { + if x > COLUMN || y > ROW { + return; + } + let buffer = self.buffer_mut(); + if on { + buffer[x as usize + (y as usize / 8) * COLUMN as usize] |= 1 << (y % 8); + } else { + buffer[x as usize + (y as usize / 8) * COLUMN as usize] &= !(1 << (y % 8)); + } + } +} diff --git a/libs/cramium-hal/src/shared_csr.rs b/libs/cramium-hal/src/shared_csr.rs new file mode 100644 index 000000000..bbaab1962 --- /dev/null +++ b/libs/cramium-hal/src/shared_csr.rs @@ -0,0 +1,79 @@ +use utralib::*; + +/// Create an immutable-friendly shared CSR object for the I/O ports. The consequence +/// of this is that we don't get the borrow checker to check the global shared state of +/// the I/O pins status, but the truth is, it's global shared state and there's nothing +/// you can do about it. Might as well make the APIs cleaner so we have less work to +/// do maintaining APIs and can pay attention to sharing/allocating the shared state +/// correctly. +#[derive(Debug)] +pub struct SharedCsr { + pub base: *const T, +} +impl SharedCsr +where + T: core::convert::TryFrom + core::convert::TryInto + core::default::Default, +{ + pub fn new(base: *const T) -> Self { SharedCsr { base: base as *const T } } + + pub unsafe fn base(&self) -> *mut T { self.base as *mut T } + + pub fn clone(&self) -> Self { SharedCsr { base: self.base.clone() } } + + /// Read the contents of this register + pub fn r(&self, reg: Register) -> T { + // prevent re-ordering + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + + let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) }; + unsafe { usize_base.add(reg.offset()).read_volatile() }.try_into().unwrap_or_default() + } + + /// Read a field from this CSR + pub fn rf(&self, field: Field) -> T { + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) }; + ((unsafe { usize_base.add(field.register().offset()).read_volatile() } >> field.offset()) + & field.mask()) + .try_into() + .unwrap_or_default() + } + + /// Read-modify-write a given field in this CSR + pub fn rmwf(&self, field: Field, value: T) { + let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) }; + let value_as_usize: usize = value.try_into().unwrap_or_default() << field.offset(); + let previous = unsafe { usize_base.add(field.register().offset()).read_volatile() } + & !(field.mask() << field.offset()); + unsafe { usize_base.add(field.register().offset()).write_volatile(previous | value_as_usize) }; + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + } + + /// Write a given field without reading it first + pub fn wfo(&self, field: Field, value: T) { + let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) }; + let value_as_usize: usize = (value.try_into().unwrap_or_default() & field.mask()) << field.offset(); + unsafe { usize_base.add(field.register().offset()).write_volatile(value_as_usize) }; + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + } + + /// Write the entire contents of a register without reading it first + pub fn wo(&self, reg: Register, value: T) { + let usize_base: *mut usize = unsafe { core::mem::transmute(self.base) }; + let value_as_usize: usize = value.try_into().unwrap_or_default(); + unsafe { usize_base.add(reg.offset()).write_volatile(value_as_usize) }; + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + } + + /// Zero a field from a provided value + pub fn zf(&self, field: Field, value: T) -> T { + let value_as_usize: usize = value.try_into().unwrap_or_default(); + (value_as_usize & !(field.mask() << field.offset())).try_into().unwrap_or_default() + } + + /// Shift & mask a value to its final field position + pub fn ms(&self, field: Field, value: T) -> T { + let value_as_usize: usize = value.try_into().unwrap_or_default(); + ((value_as_usize & field.mask()) << field.offset()).try_into().unwrap_or_default() + } +} diff --git a/libs/cramium-hal/src/udma.rs b/libs/cramium-hal/src/udma.rs index ad80f27ea..abee4347b 100644 --- a/libs/cramium-hal/src/udma.rs +++ b/libs/cramium-hal/src/udma.rs @@ -1,7 +1,8 @@ use core::mem::size_of; -use utralib::generated::*; +use utralib::*; +use crate::SharedCsr; use crate::ifram::{IframRange, UdmaWidths}; /// UDMA has a structure that Rust hates. The concept of UDMA is to take a bunch of @@ -52,6 +53,18 @@ pub enum PeriphId { impl Into for PeriphId { fn into(self) -> u32 { self as u32 } } + +impl From for PeriphId { + fn from(value: SpimChannel) -> Self { + match value { + SpimChannel::Channel0 => PeriphId::Spim0, + SpimChannel::Channel1 => PeriphId::Spim1, + SpimChannel::Channel2 => PeriphId::Spim2, + SpimChannel::Channel3 => PeriphId::Spim3, + } + } +} + #[repr(u32)] #[derive(Copy, Clone)] pub enum PeriphEventId { @@ -202,6 +215,17 @@ impl Into for PeriphEventType { } } +/// Use a trait that will allow us to share code between both `std` and `no-std` implementations +pub trait UdmaGlobalConfig { + fn clock(&self, peripheral: PeriphId, enable: bool); + unsafe fn udma_event_map( + &self, + peripheral: PeriphId, + event_type: PeriphEventType, + to_channel: EventChannel, + ); +} + #[repr(u32)] #[derive(Debug, Copy, Clone, num_derive::FromPrimitive)] pub enum EventChannel { @@ -211,12 +235,12 @@ pub enum EventChannel { Channel3 = 24, } pub struct GlobalConfig { - csr: CSR, + csr: SharedCsr, } impl GlobalConfig { - pub fn new(base_addr: *mut u32) -> Self { GlobalConfig { csr: CSR::new(base_addr) } } + pub fn new(base_addr: *mut u32) -> Self { GlobalConfig { csr: SharedCsr::new(base_addr) } } - pub fn clock_on(&mut self, peripheral: PeriphId) { + pub fn clock_on(&self, peripheral: PeriphId) { // Safety: only safe when used in the context of UDMA registers. unsafe { self.csr.base().add(GlobalReg::ClockGate.into()).write_volatile( @@ -225,7 +249,7 @@ impl GlobalConfig { } } - pub fn clock_off(&mut self, peripheral: PeriphId) { + pub fn clock_off(&self, peripheral: PeriphId) { // Safety: only safe when used in the context of UDMA registers. unsafe { self.csr.base().add(GlobalReg::ClockGate.into()).write_volatile( @@ -246,7 +270,7 @@ impl GlobalConfig { } } - pub fn map_event(&mut self, peripheral: PeriphId, event_type: PeriphEventType, to_channel: EventChannel) { + pub fn map_event(&self, peripheral: PeriphId, event_type: PeriphEventType, to_channel: EventChannel) { let event_type: u32 = event_type.into(); let id: u32 = PeriphEventId::from(peripheral) as u32 + event_type; // Safety: only safe when used in the context of UDMA registers. @@ -262,12 +286,7 @@ impl GlobalConfig { /// Same as map_event(), but for cases where the offset is known. This would typically be the case /// where a remote function transformed a PeriphEventType into a primitive `u32` and passed /// it through an IPC interface. - pub fn map_event_with_offset( - &mut self, - peripheral: PeriphId, - event_offset: u32, - to_channel: EventChannel, - ) { + pub fn map_event_with_offset(&self, peripheral: PeriphId, event_offset: u32, to_channel: EventChannel) { let id: u32 = PeriphEventId::from(peripheral) as u32 + event_offset; // Safety: only safe when used in the context of UDMA registers. unsafe { @@ -285,6 +304,24 @@ impl GlobalConfig { } } +impl UdmaGlobalConfig for GlobalConfig { + fn clock(&self, peripheral: PeriphId, enable: bool) { + if enable { + self.clock_on(peripheral); + } else { + self.clock_off(peripheral); + } + } + + unsafe fn udma_event_map( + &self, + peripheral: PeriphId, + event_type: PeriphEventType, + to_channel: EventChannel, + ) { + self.map_event(peripheral, event_type, to_channel); + } +} // --------------------------------- DMA channel ------------------------------------ const CFG_EN: u32 = 0b01_0000; // start a transfer #[allow(dead_code)] @@ -297,6 +334,8 @@ const CFG_SIZE_16: u32 = 0b00_0010; // 16-bit transfer const CFG_SIZE_32: u32 = 0b00_0100; // 32-bit transfer #[allow(dead_code)] const CFG_CLEAR: u32 = 0b10_0000; // stop and clear all pending transfers +#[allow(dead_code)] +const CFG_PENDING: u32 = 0b10_0000; // on read, indicates a transfer pending const CFG_SHADOW: u32 = 0b10_0000; // indicates a shadow transfer #[repr(usize)] @@ -359,9 +398,7 @@ pub trait Udma { } fn udma_busy(&self, bank: Bank) -> bool { // Safety: only safe when used in the context of UDMA registers. - unsafe { - (self.csr().base().add(bank as usize).add(DmaReg::Cfg.into()).read_volatile() & CFG_EN) != 0 - } + unsafe { self.csr().base().add(bank as usize).add(DmaReg::Saddr.into()).read_volatile() != 0 } } } @@ -839,7 +876,7 @@ pub enum SpimWordsPerXfer { Words4 = 2, } #[repr(u32)] -#[derive(Copy, Clone)] +#[derive(Debug, Copy, Clone)] pub enum SpimEndian { MsbFirst = 0, LsbFirst = 1, @@ -950,6 +987,7 @@ pub struct Spim { // immediately after the tx buf len pub rx_buf_len_bytes: usize, dummy_cycles: u8, + endianness: SpimEndian, } // length of the command buffer @@ -1030,6 +1068,7 @@ impl Spim { tx_buf_len_bytes: max_tx_len_bytes, rx_buf_len_bytes: max_rx_len_bytes, dummy_cycles: dummy_cycles.unwrap_or(0), + endianness: SpimEndian::MsbFirst, }; // setup the interface using a UDMA command spim.send_cmd_list(&[SpimCmd::Config(pol, pha, clk_div as u8)]); @@ -1107,6 +1146,7 @@ impl Spim { tx_buf_len_bytes: max_tx_len_bytes, rx_buf_len_bytes: max_rx_len_bytes, dummy_cycles: dummy_cycles.unwrap_or(0), + endianness: SpimEndian::MsbFirst, }; // setup the interface using a UDMA command spim.send_cmd_list(&[SpimCmd::Config(pol, pha, clk_div as u8)]); @@ -1120,6 +1160,8 @@ impl Spim { /// to prevent races/contention for the underlying device. The main reason this is introduced is /// to facilitate a panic handler for the graphics frame buffer, where we're about to kill the OS /// anyways: we don't care about soundness guarantees after this point. + /// + /// Note that the endianness is set to MSB first by default. pub unsafe fn from_raw_parts( csr: usize, cs: SpimCs, @@ -1145,6 +1187,7 @@ impl Spim { tx_buf_len_bytes, rx_buf_len_bytes, dummy_cycles, + endianness: SpimEndian::MsbFirst, } } @@ -1175,6 +1218,12 @@ impl Spim { ) } + /// Note that endianness is disregarded in the case that the channel is being used to talk to + /// a memory device, because the endianness is always MsbFirst. + pub fn set_endianness(&mut self, endianness: SpimEndian) { self.endianness = endianness; } + + pub fn get_endianness(&self) -> SpimEndian { self.endianness } + /// The command buf is *always* a `u32`; so tie the type down here. fn cmd_buf_mut(&mut self) -> &mut [u32] { &mut self.ifram.as_slice_mut()[(self.tx_buf_len_bytes + self.rx_buf_len_bytes) / size_of::() @@ -1221,7 +1270,16 @@ impl Spim { } } - pub fn is_tx_busy(&self) -> bool { self.udma_busy(Bank::Tx) } + pub fn is_tx_busy(&self) -> bool { self.udma_busy(Bank::Tx) || self.udma_busy(Bank::Custom) } + + pub fn tx_data_await(&self, _use_yield: bool) { + while self.is_tx_busy() { + #[cfg(feature = "std")] + if _use_yield { + xous::yield_slice(); + } + } + } /// `tx_data_async` will queue a data buffer into the SPIM interface and return as soon as the enqueue /// is completed (which can be before the transmission is actually done). The function may partially @@ -1278,6 +1336,8 @@ impl Spim { let mut words_sent: usize = 0; if use_cs { + // ensure any previous transaction is completed + while self.udma_busy(Bank::Custom) || self.udma_busy(Bank::Tx) {} if self.sot_wait == 0 { self.send_cmd_list(&[SpimCmd::StartXfer(self.cs)]) } else { @@ -1286,19 +1346,38 @@ impl Spim { SpimCmd::Wait(SpimWaitType::Cycles(self.sot_wait)), ]) } + // wait for CS to assert + while self.udma_busy(Bank::Custom) {} } + let mut one_shot = false; + let evt = if eot_event { SpimEventGen::Enabled } else { SpimEventGen::Disabled }; while words_sent < total_words { // determine the valid length of data we could send let tx_len = (total_words - words_sent).min(self.tx_buf_len_bytes); // setup the command list for data to send - let cmd_list = [SpimCmd::TxData( + let cmd_list_oneshot = [ + SpimCmd::TxData( + self.mode, + SpimWordsPerXfer::Words1, + bits_per_xfer as u8, + self.get_endianness(), + tx_len as u32, + ), + SpimCmd::EndXfer(evt), + ]; + let cmd_list_repeated = [SpimCmd::TxData( self.mode, SpimWordsPerXfer::Words1, bits_per_xfer as u8, - SpimEndian::LsbFirst, + self.get_endianness(), tx_len as u32, )]; - self.send_cmd_list(&cmd_list); + if tx_len == total_words && use_cs { + one_shot = true; + self.send_cmd_list(&cmd_list_oneshot); + } else { + self.send_cmd_list(&cmd_list_repeated); + } let cfg_size = match size_of::() { 1 => CFG_SIZE_8, 2 => CFG_SIZE_16, @@ -1336,8 +1415,9 @@ impl Spim { } } } - if use_cs { - let evt = if eot_event { SpimEventGen::Enabled } else { SpimEventGen::Disabled }; + if use_cs && !one_shot { + // wait for all data to transmit before de-asserting CS + while self.udma_busy(Bank::Tx) {} if self.eot_wait == 0 { self.send_cmd_list(&[SpimCmd::EndXfer(evt)]) } else { @@ -1346,11 +1426,12 @@ impl Spim { SpimCmd::EndXfer(evt), ]) } + while self.udma_busy(Bank::Custom) {} } } pub fn rx_data(&mut self, _rx_data: &mut [T], _cs: Option) { - todo!("Not yet done...let's see if tx_data works first before templating"); + todo!("Not yet done...template off of tx_data, but we need a test target before we can do this"); } /// Activate is the logical sense, not the physical sense. To be clear: `true` causes CS to go low. diff --git a/libs/xous-pl230/src/pl230_tests/units.rs b/libs/xous-pl230/src/pl230_tests/units.rs index 4034b2822..2ab798d69 100644 --- a/libs/xous-pl230/src/pl230_tests/units.rs +++ b/libs/xous-pl230/src/pl230_tests/units.rs @@ -137,7 +137,7 @@ pub fn pio_test(pl230: &mut Pl230) -> bool { report_api("id2", pl230.csr.r(utra::pl230::PERIPH_ID_2)); // Configure PB15 -> PIO0 for test (although the code is capable of toggling all pins, only map one). - let mut iox = iox::Iox::new(utralib::generated::HW_IOX_BASE as *mut u32); + let iox = iox::Iox::new(utralib::generated::HW_IOX_BASE as *mut u32); let pin = iox.set_pio_bit_from_port_and_pin(iox::IoxPort::PB, 15).unwrap(); report_api("Configured PIO pin: ", pin as u32); diff --git a/loader/Cargo.toml b/loader/Cargo.toml index 8934ea380..7224fbd91 100644 --- a/loader/Cargo.toml +++ b/loader/Cargo.toml @@ -72,6 +72,9 @@ cramium-soc = [ "sram-margin", "boot-delay", ] +board-baosec = ["cramium-hal/board-baosec"] +board-baosor = ["cramium-hal/board-baosor"] +board-dabao = ["cramium-hal/board-dabao"] cramium-fpga = [ "utralib/cramium-fpga", "debug-print", @@ -96,7 +99,6 @@ boot-delay = [] simulation-only = [] quantum-timer-test = ["pio", "pio-proc"] spim-test = [] -spi-alt-channel = [] irq-test = [] usb-test = [] trng-test = [] diff --git a/loader/src/lib.rs b/loader/src/lib.rs index 3b047db27..e9e285a04 100644 --- a/loader/src/lib.rs +++ b/loader/src/lib.rs @@ -26,10 +26,10 @@ pub const FLG_SWAP_USED: u32 = 0x8000_0000; // Locate the hard-wired IFRAM allocations for UDMA #[allow(dead_code)] #[cfg(feature = "cramium-soc")] -pub const UART_IFRAM_ADDR: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 4096; +pub const UART_IFRAM_ADDR: usize = cramium_hal::board::UART_DMA_TX_BUF_PHYS; #[allow(dead_code)] #[cfg(feature = "cramium-soc")] -pub const APP_UART_IFRAM_ADDR: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 3 * 4096; +pub const APP_UART_IFRAM_ADDR: usize = cramium_hal::board::APP_UART_IFRAM_ADDR; /// This is the amount of space that the loader stack will occupy as it runs, assuming no swap and giving one /// page for the clean suspend marker diff --git a/loader/src/main.rs b/loader/src/main.rs index 7265c8fcd..06b42b449 100644 --- a/loader/src/main.rs +++ b/loader/src/main.rs @@ -93,6 +93,9 @@ pub unsafe extern "C" fn rust_entry(signed_buffer: *const usize, signature: u32) #[cfg(feature = "cramium-soc")] crate::platform::early_init(); // sets up PLLs so we're not running at 16MHz... + #[cfg(feature = "cramium-soc")] + crate::platform::process_update(); + // initially validate the whole image on disk (including kernel args) // kernel args must be validated because tampering with them can change critical assumptions about // how data is loaded into memory diff --git a/loader/src/platform/cramium.rs b/loader/src/platform/cramium.rs index a9df85f1d..03b736089 100644 --- a/loader/src/platform/cramium.rs +++ b/loader/src/platform/cramium.rs @@ -6,3 +6,7 @@ pub mod swap; pub use swap::*; mod bootlogo; mod poweron_bt; + +mod update; +pub use update::*; +mod verifier; diff --git a/loader/src/platform/cramium/bootlogo.rs b/loader/src/platform/cramium/bootlogo.rs index df736e8c8..e5cbaa2f3 100644 --- a/loader/src/platform/cramium/bootlogo.rs +++ b/loader/src/platform/cramium/bootlogo.rs @@ -1,119 +1,39 @@ -use core::mem::size_of; - -use cramium_hal::ifram::IframRange; -use cramium_hal::iox::Iox; -use cramium_hal::udma::{GlobalConfig, PeriphId}; -use cramium_hal::{iox, udma}; - -use crate::platform::cramium::setup_port; - -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] - setup_port( - iox, - SPI_PORT, - SPI_CLK_PIN, - Some(iox::IoxFunction::AF1), - Some(iox::IoxDir::Output), - Some(iox::IoxDriveStrength::Drive2mA), - Some(iox::IoxEnable::Enable), - None, - None, - ); - // SPIM_SD0_A[0] - setup_port( - iox, - SPI_PORT, - SPI_DAT_PIN, - Some(iox::IoxFunction::AF1), - Some(iox::IoxDir::Output), - Some(iox::IoxDriveStrength::Drive2mA), - Some(iox::IoxEnable::Enable), - None, - None, - ); - // 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. - setup_port( - iox, - SPI_PORT, - SPI_CS_PIN, - Some(iox::IoxFunction::AF1), - Some(iox::IoxDir::Output), - Some(iox::IoxDriveStrength::Drive2mA), - Some(iox::IoxEnable::Enable), - None, - Some(iox::IoxEnable::Enable), - ); - // 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; +use cramium_hal::iox::{IoGpio, IoSetup}; +use cramium_hal::udma::UdmaGlobalConfig; + +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(); } diff --git a/loader/src/platform/cramium/cramium.rs b/loader/src/platform/cramium/cramium.rs index d7baff115..e1110063c 100644 --- a/loader/src/platform/cramium/cramium.rs +++ b/loader/src/platform/cramium/cramium.rs @@ -15,6 +15,51 @@ use utralib::generated::*; // This puts the byte-address hex offset at (6 * 256 + 8 * 8) / 8 = 0xC8 // within the IFR region. Total IFR region size is 0x200. +/* + Thoughts on where to put the updating routine. + + As a Xous runtime program: + Pros: + - Full security of MMU + - Updater primitives are available as Xous primitives + Cons: + - Less RAM available to stage data + - ReRAM is XIP; makes kernel update tricky + As a loader program: + Pros: + - Higher performance (no OS overhead) + - Faster dev time + - Can stage full images in PSRAM before committing + - Full overwrite of ReRAM OS possible + Cons: + - Larger loader image + - No MMU security - bugs are more brittle/scary + - Loader becomes a primary attack surface due to its size and complexity + - Less code re-use with main code base + - Loader update needs a special path to hand-off an image to Xous to avoid XIP conflict + + I think the winning argument is that we could stage the full image in PSRAM before + committing to either ReRAM or SPI RAM. This allows us to do full signature checking prior + to committing any objects. + + We could structure this so that when going into update mode, the secret key lifecycle + bits are pushed forward, so we only have derived keys available. This would make any + break into the loader updater less able to get at any root keys? +*/ + +/* + To-do: + -[x] Add dummy lifecycle gate call + -[ ] New OLED base driver + -[ ] I2C driver for AXP2101 + -[ ] camera base driver (maybe loopback to OLED as demo?) + -[ ] USB stack into loader; debugging there. Present as bulk transfer to emulated disk on + PSRAM using ghostFS + -[ ] bring mbox routine into loader so we can have access to ReRAM write primitive; structure so + that we can improve this easily as the chip bugs are fixed + -[ ] Image validation & burning routine +*/ + pub const RAM_SIZE: usize = utralib::generated::HW_SRAM_MEM_LEN; pub const RAM_BASE: usize = utralib::generated::HW_SRAM_MEM; pub const FLASH_BASE: usize = utralib::generated::HW_RERAM_MEM; @@ -140,6 +185,7 @@ pub fn early_init() { // Now setup the clocks for real // Safety: this can only be called in the early_init boot context let perclk = unsafe { init_clock_asic(800_000_000) }; + // let perclk = unsafe { init_clock_asic_c(800_000_000, 0) }; crate::println!("Perclk is {} Hz", perclk); // Configure the UDMA UART. This UART's settings will be used as the initial console UART. @@ -147,10 +193,10 @@ pub fn early_init() { // on the cramium-hal crate to be functional. // Set up the IO mux to map UART_A0: - // UART_RX_A[0] = PA3 - // UART_TX_A[0] = PA4 - // UART_RX_A[1] = PD13 - // UART_RX_A[1] = PD14 + // UART_RX_A[0] = PA3 app + // UART_TX_A[0] = PA4 app + // UART_RX_A[1] = PD13 console + // UART_RX_A[1] = PD14 console let mut iox = Iox::new(utra::iox::HW_IOX_BASE as *mut u32); iox.set_alternate_function(IoxPort::PD, 13, IoxFunction::AF1); iox.set_alternate_function(IoxPort::PD, 14, IoxFunction::AF1); @@ -287,11 +333,11 @@ pub fn early_init() { #[cfg(feature = "spim-test")] { + use cramium_hal::board::{SPIM_FLASH_IFRAM_ADDR, SPIM_RAM_IFRAM_ADDR}; use cramium_hal::ifram::IframRange; use cramium_hal::iox::*; use cramium_hal::udma::*; use loader::swap::SPIM_FLASH_IFRAM_ADDR; - use loader::swap::SPIM_RAM_IFRAM_ADDR; fn setup_port( iox: &mut Iox, @@ -327,118 +373,9 @@ pub fn early_init() { // setup the I/O pins let mut iox = Iox::new(utralib::generated::HW_IOX_BASE as *mut u32); let mut udma_global = GlobalConfig::new(utralib::generated::HW_UDMA_CTRL_BASE as *mut u32); - #[cfg(feature = "spi-alt-channel")] - let channel = { - // JQSPI1 - // SPIM_CLK_A[0] - setup_port( - &mut iox, - IoxPort::PD, - 4, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive4mA), - Some(IoxEnable::Enable), - None, - None, - ); - // SPIM_SD[0-3]_A[0] - for i in 0..3 { - setup_port( - &mut iox, - IoxPort::PD, - i, - Some(IoxFunction::AF1), - None, - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - } - // SPIM_CSN0_A[0] - setup_port( - &mut iox, - IoxPort::PD, - 5, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - // SPIM_CSN0_A[1] - setup_port( - &mut iox, - IoxPort::PD, - 6, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - udma_global.clock_on(PeriphId::Spim0); // JQSPI1 - SpimChannel::Channel0 - }; - #[cfg(not(feature = "spi-alt-channel"))] - let channel = { - // JPC7_13 - // SPIM_CLK_A[1] - setup_port( - &mut iox, - IoxPort::PC, - 11, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive4mA), - Some(IoxEnable::Enable), - None, - None, - ); - // SPIM_SD[0-3]_A[1] - for i in 7..11 { - setup_port( - &mut iox, - IoxPort::PC, - i, - Some(IoxFunction::AF1), - None, - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - } - // SPIM_CSN0_A[1] - setup_port( - &mut iox, - IoxPort::PC, - 12, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - // SPIM_CSN0_A[1] - setup_port( - &mut iox, - IoxPort::PC, - 13, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - udma_global.clock_on(PeriphId::Spim1); // JPC7_13 - SpimChannel::Channel1 - }; + let channel = cramium_hal::board::setup_memory_pins(&iox); + udma_global.clock_off(PeriphId::from(channel)); + crate::println!("Configuring SPI channel: {:?}", channel); // safety: this is safe because clocks have been set up let mut flash_spim = unsafe { @@ -507,7 +444,8 @@ pub fn early_init() { crate::println!("flash ID: {:x}", flash_id); crate::println!("ram ID: {:x}", ram_id); // density 18, memory type 20, mfg ID C2 ==> MX25L128833F - assert!(flash_id & 0xFF_FF_FF == 0x1820C2); + // density 38, memory type 25, mfg ID C2 ==> MX25U12832F + assert!(flash_id & 0xFF_FF_FF == 0x1820C2 || flash_id & 0xFF_FF_FF == 0x38_25_C2); // KGD 5D, mfg ID 9D; remainder of bits are part of the EID assert!(ram_id & 0xFF_FF == 0x5D9D); @@ -534,7 +472,8 @@ pub fn early_init() { crate::println!("QPI flash ID: {:x}", flash_id); crate::println!("QPI ram ID: {:x}", ram_id); // density 18, memory type 20, mfg ID C2 ==> MX25L128833F - assert!(flash_id & 0xFF_FF_FF == 0x1820C2); + // density 38, memory type 25, mfg ID C2 ==> MX25U12832F + assert!(flash_id & 0xFF_FF_FF == 0x1820C2 || flash_id & 0xFF_FF_FF == 0x38_25_C2); // KGD 5D, mfg ID 9D; remainder of bits are part of the EID assert!(ram_id & 0xFF_FF == 0x5D9D); @@ -786,6 +725,7 @@ pub fn early_init() { } } + /* let aoc_base = utralib::CSR::new(0x4006_0000 as *mut u32); unsafe { for i in 0..0x50 / 4 { @@ -796,6 +736,7 @@ pub fn early_init() { aoc_base.base().add(4).write_volatile(pmu_cr & !1); crate::println!("pmu_cr upd: {:x}", aoc_base.base().add(4).read_volatile()); } + */ udma_uart.write("Press any key to continue...".as_bytes()); getc(); udma_uart.write(b"\n\rBooting!\n\r"); @@ -1361,3 +1302,168 @@ pub extern "C" fn trap_handler( unsafe { mie::set_mext() }; unsafe { _resume_context(0x61008000u32) }; // this is the scratch page used in the assembly routine above } + +#[allow(dead_code)] +pub fn log_2(mut value: u32) -> u32 { + let mut result = 0; + + // Shift right until we find the position of the highest set bit + while value > 1 { + value >>= 1; + result += 1; + } + + result +} + +#[allow(dead_code)] +/// Direct translation of the C code +pub unsafe fn init_clock_asic_c(freq_hz: u32, duty_sram: u32) -> u32 { + use utra::sysctrl; + let daric_cgu = sysctrl::HW_SYSCTRL_BASE as *mut u32; + + const UNIT_MHZ: u32 = 1000u32 * 1000u32; + const PFD_F_MHZ: u32 = 16; + const FREQ_0: u32 = 16u32 * UNIT_MHZ; + const FREQ_OSC_MHZ: u32 = 48; // Actually 48MHz + const M: u32 = FREQ_OSC_MHZ / PFD_F_MHZ; // - 1; // OSC input was 24, replace with 48 + + const TBL_Q: [u16; 7] = [ + // keep later DIV even number as possible + 0x7777, // 16-32 MHz + 0x7737, // 32-64 + 0x3733, // 64-128 + 0x3313, // 128-256 + 0x3311, // 256-512 // keep ~ 100MHz + 0x3301, // 512-1024 + 0x3301, // 1024-1600 + ]; + const TBL_MUL: [u32; 7] = [ + 64, // 16-32 MHz + 32, // 32-64 + 16, // 64-128 + 8, // 128-256 + 4, // 256-512 + 2, // 512-1024 + 2, // 1024-1600 + ]; + + if (0 == (daric_cgu.add(sysctrl::SFR_IPCPLLMN.offset()).read_volatile() & 0x0001F000)) + || (0 == (daric_cgu.add(sysctrl::SFR_IPCPLLMN.offset()).read_volatile() & 0x00000fff)) + { + // for SIM, avoid div by 0 if unconfigurated + // , default VCO 48MHz / 48 * 1200 = 1.2GHz + // TODO magic numbers + daric_cgu + .add(sysctrl::SFR_IPCPLLMN.offset()) + .write_volatile(((M << 12) & 0x0001F000) | ((1200) & 0x00000fff)); + daric_cgu.add(sysctrl::SFR_IPCPLLF.offset()).write_volatile(0); // ?? + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + daric_cgu.add(sysctrl::SFR_IPCARIPFLOW.offset()).write_volatile(0x32); // commit + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + } + + // TODO select int/ext osc/xtal + daric_cgu.add(sysctrl::SFR_CGUSEL1.offset()).write_volatile(1); // 0: RC, 1: XTAL + daric_cgu.add(sysctrl::SFR_CGUFSCR.offset()).write_volatile(FREQ_OSC_MHZ); // external crystal is 48MHz + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + daric_cgu.add(sysctrl::SFR_CGUSET.offset()).write_volatile(0x32); + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + + if freq_hz < 1000000 { + daric_cgu.add(sysctrl::SFR_IPCOSC.offset()).write_volatile(freq_hz); + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + daric_cgu.add(sysctrl::SFR_IPCARIPFLOW.offset()).write_volatile(0x32); // commit, must write 32 + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + } + // switch to OSC + daric_cgu.add(sysctrl::SFR_CGUSEL0.offset()).write_volatile(0); // clktop sel, 0:clksys, 1:clkpll0 + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + daric_cgu.add(sysctrl::SFR_CGUSET.offset()).write_volatile(0x32); // commit + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + + if freq_hz < 1000000 { + } else { + let f16_mhz_log2: usize = log_2(freq_hz / FREQ_0) as usize; + + // PD PLL + daric_cgu + .add(sysctrl::SFR_IPCLPEN.offset()) + .write_volatile(daric_cgu.add(sysctrl::SFR_IPCLPEN.offset()).read_volatile() | 0x02); + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + daric_cgu.add(sysctrl::SFR_IPCARIPFLOW.offset()).write_volatile(0x32); // commit, must write 32 + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + + // delay + for _ in 0..1024 { + unsafe { core::arch::asm!("nop") }; + } + + let n_fxp24: u64 = (((freq_hz as u64) << 24u64) * TBL_MUL[f16_mhz_log2] as u64 + + PFD_F_MHZ as u64 * UNIT_MHZ as u64 / 2u64) + / (PFD_F_MHZ as u64 * UNIT_MHZ as u64); // rounded + let n_frac: u32 = (n_fxp24 & 0x00ffffff) as u32; + + daric_cgu + .add(sysctrl::SFR_IPCPLLMN.offset()) + .write_volatile(((M << 12) & 0x0001F000) | ((n_fxp24 >> 24) & 0x00000fff) as u32); // 0x1F598; // ?? + daric_cgu + .add(sysctrl::SFR_IPCPLLF.offset()) + .write_volatile(n_frac | if 0 == n_frac { 0 } else { 1 << 24 }); // ?? + daric_cgu.add(sysctrl::SFR_IPCPLLQ.offset()).write_volatile(TBL_Q[f16_mhz_log2] as u32); // ?? TODO select DIV for VCO freq + + // VCO bias CPP bias CPI bias + // 1 2 3 + //DARIC_IPC->ipc = (3 << 6) | (5 << 3) | (5); + daric_cgu.add(sysctrl::SFR_IPCCR.offset()).write_volatile((1 << 6) | (2 << 3) | (3)); + // daric_cgu.add(sysctrl::SFR_IPCCR.offset()).write_volatile((3 << 6) | (5 << 3) | (5)); + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + daric_cgu.add(sysctrl::SFR_IPCARIPFLOW.offset()).write_volatile(0x32); // commit, must write 32 + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + + daric_cgu + .add(sysctrl::SFR_IPCLPEN.offset()) + .write_volatile(daric_cgu.add(sysctrl::SFR_IPCLPEN.offset()).read_volatile() & !0x02); + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + daric_cgu.add(sysctrl::SFR_IPCARIPFLOW.offset()).write_volatile(0x32); // commit, must write 32 + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + + // delay + for _ in 0..1024 { + unsafe { core::arch::asm!("nop") }; + } + //printf("read reg a0 : %08" PRIx32"\n", *((volatile uint32_t* )0x400400a0)); + //printf("read reg a4 : %04" PRIx16"\n", *((volatile uint16_t* )0x400400a4)); + //printf("read reg a8 : %04" PRIx16"\n", *((volatile uint16_t* )0x400400a8)); + crate::println!("PLL switchover"); + // TODO wait/poll lock status? + daric_cgu.add(sysctrl::SFR_CGUSEL0.offset()).write_volatile(1); // clktop sel, 0:clksys, 1:clkpll0 + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + daric_cgu.add(sysctrl::SFR_CGUSET.offset()).write_volatile(0x32); // commit + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + crate::println!("PLL switchover done"); + + // printf (" MN: 0x%05x, F: 0x%06x, Q: 0x%04x\n", + // DARIC_IPC->pll_mn, DARIC_IPC->pll_f, DARIC_IPC->pll_q); + // printf (" LPEN: 0x%01x, OSC: 0x%04x, BIAS: 0x%04x,\n", + // DARIC_IPC->lpen, DARIC_IPC->osc, DARIC_IPC->ipc); + } + + daric_cgu.add(utra::sysctrl::SFR_CGUFD_CFGFDCR_0_4_0.offset()).write_volatile(0x7fff); // CPU + if 0 == duty_sram { + daric_cgu.add(utra::sysctrl::SFR_CGUFD_CFGFDCR_0_4_1.offset()).write_volatile(0x3f7f); // aclk + } else { + daric_cgu.add(utra::sysctrl::SFR_CGUFD_CFGFDCR_0_4_1.offset()).write_volatile(duty_sram); + } + daric_cgu.add(utra::sysctrl::SFR_CGUFD_CFGFDCR_0_4_2.offset()).write_volatile(0x1f3f); // hclk + daric_cgu.add(utra::sysctrl::SFR_CGUFD_CFGFDCR_0_4_3.offset()).write_volatile(0x0f1f); // iclk + daric_cgu.add(utra::sysctrl::SFR_CGUFD_CFGFDCR_0_4_4.offset()).write_volatile(0x070f); // pclk + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + daric_cgu.add(utra::sysctrl::SFR_CGUSET.offset()).write_volatile(0x32); // commit + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + + // UDMACORE->CFG_CG = 0xffffffff; //everything on + // core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + + 100_000_000 // bodge for now +} diff --git a/loader/src/platform/cramium/poweron_bt.rs b/loader/src/platform/cramium/poweron_bt.rs index c5a52545b..cab53951a 100644 --- a/loader/src/platform/cramium/poweron_bt.rs +++ b/loader/src/platform/cramium/poweron_bt.rs @@ -1,739 +1,131 @@ -pub const LOGO_MAP: [u32; 11 * 536] = [ - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffe0007, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x1fffffff, 0xff800000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x03ffffff, 0xfc000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x007fffff, - 0xf0000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x001fffff, 0x80000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x0007ffff, 0x00000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x0003ffff, 0x00000000, 0xfffffffc, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x0000ffff, 0x00000000, 0xfffffff0, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00007fff, 0x00000000, - 0xffffffe0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x00003fff, 0x00000000, 0xffffffc0, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00001fff, 0x00000000, 0xffffff80, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000fff, - 0x00000000, 0xffffff00, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x000007ff, 0x00000000, 0xfffffe00, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x000003ff, 0x00000000, 0xfffffc00, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x000001ff, 0x0000fff8, 0xfffff800, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x800000ff, 0x001fffff, 0xfffff800, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf00000ff, 0x007fffff, - 0xfffff000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xfc00007f, 0x01ffffff, 0xffffe000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfe00007f, 0x07ffffff, 0xffffe000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff00003f, - 0x0fffffff, 0xffffc000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffc0001f, 0x1fffffff, 0xffffc000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffc0001f, 0x3fffffff, 0xffff8000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffe0001f, 0x7fffffff, 0xffff8000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xfff0000f, 0xffffffff, 0xffff0000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8000f, 0xffffffff, - 0xffff0000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xfff80007, 0xffffffff, 0xffff0001, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffc0007, 0xffffffff, 0xfffe0003, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffc0007, - 0xffffffff, 0xfffe0003, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfffe0007, 0xffffffff, 0xfffe0007, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffe0003, 0xffffffff, 0xfffe0007, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffff0003, 0xffffffff, 0xfffc0007, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0003, 0xffffffff, 0xfffc000f, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff0003, 0xffffffff, - 0xfffc000f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffff0001, 0xffffffff, 0xfffc000f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, 0xfffc000f, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, - 0xffffffff, 0xfffc000f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8000f, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8001f, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffff8001, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, - 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8001f, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, - 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8001f, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffff8001, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, - 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8001f, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, - 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffff8001, 0xffffffff, 0xfff8001f, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8001f, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8001f, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff8001f, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff807, - 0xffffffff, 0xfff8001f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffe003, 0xffffffff, 0xfff0000f, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xfff80000, 0x0fffc001, 0x00000000, 0x00000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xfff80000, - 0x0fff8000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0x7ff80000, 0x0fff0000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x7ff80000, 0x0fff0000, 0x00000000, - 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0x7ff80000, 0x0fff0000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0x7ff80000, 0x0fff0000, 0x00000000, 0x00000000, 0xff000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x7ff80000, 0x0fff0000, - 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0x7ff80000, 0x0fff0000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x7ff80000, 0x0fff0000, 0x00000000, 0x00000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x7ff80000, - 0x0fff0000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0x7ff80000, 0x0fff0000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xfff80000, 0x0fff8000, 0x00000000, - 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0xfff80000, 0x0fffc001, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffe003, 0xffffffff, 0xffffffff, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xfffff007, - 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, - 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, - 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, - 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0xffffff80, 0xffffffff, 0x00ffffff, 0xfffffe00, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xffff8000, 0x001fffff, 0xffffe000, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xffff8000, - 0x0003ffff, 0xffff8000, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0x000fff80, 0xffff8000, 0x0000ffff, 0xfffe0000, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xffff8000, 0x00003fff, 0xfff80000, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, - 0xffff8000, 0x00001fff, 0xfff00000, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0x000fff80, 0xffff8000, 0x00000fff, 0xffe00000, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xffff8000, 0x000007ff, - 0xffc00000, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0x000fff80, 0xffff8000, 0x000003ff, 0xff800000, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xffff8000, 0x000001ff, 0xff000000, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xffff8000, - 0x000000ff, 0xfe000000, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0x000fff80, 0xffff8000, 0x000000ff, 0xfc000000, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xffff8000, 0xe000007f, 0xfc00000f, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, - 0xffff8001, 0xfe00007f, 0xf80000ff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xff80003f, 0xf80003ff, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xffc0003f, - 0xf00007ff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0xffffff80, 0xffff8001, 0xffe0001f, 0xf0000fff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfff0001f, 0xf0001fff, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, - 0xfff0001f, 0xe0003fff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0xffffff80, 0xffff8001, 0xfff8000f, 0xe0003fff, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfff8000f, 0xe0003fff, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, - 0xffff8001, 0xfffc000f, 0xe0007fff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffc000f, 0xc0007fff, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffc0007, - 0xc0007fff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, - 0xfffe0007, 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, - 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffe0007, - 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, - 0xfffe0007, 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, - 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffe0007, - 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffe0007, 0xc000ffff, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, - 0xfffc0007, 0xc000ffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffc000f, 0xc0007fff, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfffc000f, 0xe0007fff, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, - 0xffff8001, 0xfff8000f, 0xe0007fff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfff8000f, 0xe0003fff, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xfff8000f, - 0xe0003fff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0xffffff80, 0xffff8001, 0xfff0001f, 0xf0001fff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xffe0001f, 0xf0001fff, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, - 0xffc0003f, 0xf0000fff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0xffffff80, 0xffff8001, 0xff80003f, 0xf80007ff, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffff8001, 0xff00003f, 0xf80001ff, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, - 0xf8010001, 0xf800007f, 0xfc00007f, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0x000fff80, 0xf0000000, 0x0000007f, 0xfc000001, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xf0000000, 0x000000ff, - 0xfe000000, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0x000fff80, 0xf0000000, 0x000001ff, 0xff000000, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xf0000000, 0x000003ff, 0xff000000, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xf0000000, - 0x000003ff, 0xff800000, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0x000fff80, 0xf0000000, 0x000007ff, 0xffc00000, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xf0000000, 0x00000fff, 0xffe00000, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, - 0xf0000000, 0x00003fff, 0xfff80000, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0x000fff80, 0xf0000000, 0x00007fff, 0xfffc0000, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x000fff80, 0xf0000000, 0x0001ffff, - 0xffff0000, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0x000fff80, 0xf0000000, 0x0007ffff, 0xffffc000, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0x003fffff, 0xfffff800, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, - 0x0fffffff, 0xffffffe0, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, - 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, - 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, - 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0xffffff80, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0xffffff80, 0xffffffff, 0xffffffff, 0xffffffff, 0xff0003ff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0x01ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0x01ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff000000, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0x01ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xff000000, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0x01ffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf007ffff, 0xffffffff, 0xf3ffffff, 0xffffffff, - 0xffff81ff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xe007ffff, - 0xffffffff, 0xf3ffffff, 0xffffffff, 0xfffe007f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xc7e7ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfffc7e3f, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xcfe7ffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xfff8ff1f, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xcfe7ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfff9ff9f, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xcfe7ffff, 0x3f3f3e07, 0xf319f83f, 0xfe60ff0c, 0x8671ff8f, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xcfe7ffff, 0x3f1e3c03, - 0xf309f00f, 0xfe407e04, 0x0273ffcf, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xc7e7ffff, 0x9e1e78f1, 0xf3e1e3c7, 0xfe1e3c70, 0x3873ffcf, 0xfffffffe, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xe3e7ffff, 0x9e1e79f9, 0xf3f1e7e7, 0xfe3f3cf8, - 0x7c73ffcf, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xf007ffff, - 0x9e5c73fc, 0xf3f9cff3, 0xfe7f9cfc, 0x7e73ffcf, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xfc07ffff, 0xccccf3fc, 0xf3f9c003, 0xfe7f9cfc, 0x7e73ffcf, 0xfffffffe, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7ffff, 0xccccf3fc, 0xf3f9c003, - 0xfe7f9cfc, 0x7e73ffcf, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffe7ffff, 0xccccf3fc, 0xf3f9fff3, 0xfe7f9cfc, 0x7e71ff8f, 0xfffffffe, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7ffff, 0xc9e0f3fc, 0xf3f9fff3, 0xfe7f9cfc, 0x7e79ff9f, - 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7ffff, 0xe1e1f9f9, - 0xf3f9c7e7, 0xfe3f3cfc, 0x7e78ff1f, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffe7ffff, 0xe1e1f8f1, 0xf3f9e7c7, 0xfe1e3cfc, 0x7e7c7e3f, 0xffc78f1e, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7ffff, 0xe3f1fc03, 0xf3f9e00f, 0xfe407cfc, - 0x7e7e007f, 0xffc78f1e, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffe7ffff, - 0xf3f3fe07, 0xf3f9f83f, 0xfe60fcfc, 0x7e7f81ff, 0xffc78f1e, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xfe7fffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xfe3f1fff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xff1f1fff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff803fff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffc0ffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, +#![cfg_attr(rustfmt, rustfmt_skip)] +pub const LOGO_MAP: [u8; 2048] = [ +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xff, 0xe0, 0x07, 0xff, 0xc0, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xf8, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xfe, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xfe, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xff, 0xe1, 0xff, 0xff, 0xff, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xff, 0x81, 0xff, 0xc7, 0xff, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x81, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x03, 0xfc, 0x00, 0x7f, 0x81, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x03, 0xfc, 0x00, 0x7f, 0x81, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0x3f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0x3f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0x3f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0x3f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0x3f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0x1f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0x1f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0x3f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0x3f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0x3f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x07, 0xf8, 0x00, 0x3f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x03, 0xf8, 0x00, 0x3f, 0xc1, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x03, 0xfc, 0x00, 0x7f, 0x81, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x03, 0xfe, 0x00, 0xff, 0x81, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xf8, 0x03, 0xff, 0x01, 0xff, 0x81, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xff, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xf8, 0x00, 0xff, 0xff, 0xfe, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xf8, 0x00, 0x7f, 0xff, 0xfc, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xf8, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x81, 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xe0, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x01, 0xff, 0x80, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x03, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x80, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0x8f, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0x8f, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0x8f, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0x8f, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0x8f, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0xff, 0x87, 0xf8, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xf8, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x80, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x01, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; diff --git a/loader/src/platform/cramium/swap.rs b/loader/src/platform/cramium/swap.rs index 8c0c008de..095f4ed34 100644 --- a/loader/src/platform/cramium/swap.rs +++ b/loader/src/platform/cramium/swap.rs @@ -1,12 +1,11 @@ use core::mem::size_of; use aes_gcm_siv::{AeadInPlace, Aes256GcmSiv, KeyInit, Nonce, Tag}; +use cramium_hal::board::{APP_UART_IFRAM_ADDR, SPIM_FLASH_IFRAM_ADDR, SPIM_RAM_IFRAM_ADDR}; use cramium_hal::ifram::IframRange; use cramium_hal::iox::*; use cramium_hal::sce; use cramium_hal::udma::*; -use loader::APP_UART_IFRAM_ADDR; -use loader::swap::SPIM_RAM_IFRAM_ADDR; use rand_chacha::ChaCha8Rng; use rand_chacha::rand_core::RngCore; use rand_chacha::rand_core::SeedableRng; @@ -36,156 +35,15 @@ pub struct SwapHal { buf: RawPage, } -pub fn setup_port( - iox: &mut Iox, - port: IoxPort, - pin: u8, - function: Option, - direction: Option, - drive: Option, - slow_slew: Option, - schmitt: Option, - pullup: Option, -) { - if let Some(f) = function { - iox.set_alternate_function(port, pin, f); - } - if let Some(d) = direction { - iox.set_gpio_dir(port, pin, d); - } - if let Some(t) = schmitt { - iox.set_gpio_schmitt_trigger(port, pin, t); - } - if let Some(p) = pullup { - iox.set_gpio_pullup(port, pin, p); - } - if let Some(s) = slow_slew { - iox.set_slow_slew_rate(port, pin, s); - } - if let Some(s) = drive { - iox.set_drive_strength(port, pin, s); - } -} - impl SwapHal { pub fn new(cfg: &BootConfig) -> Option { if let Some(swap) = cfg.swap { - let mut udma_global = GlobalConfig::new(utralib::generated::HW_UDMA_CTRL_BASE as *mut u32); + let udma_global = GlobalConfig::new(utralib::generated::HW_UDMA_CTRL_BASE as *mut u32); // setup the I/O pins - let mut iox = Iox::new(utralib::generated::HW_IOX_BASE as *mut u32); - #[cfg(feature = "spi-alt-channel")] - let channel = { - // JQSPI1 - // SPIM_CLK_A[0] - setup_port( - &mut iox, - IoxPort::PD, - 4, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive4mA), - Some(IoxEnable::Enable), - None, - None, - ); - // SPIM_SD[0-3]_A[0] - for i in 0..3 { - setup_port( - &mut iox, - IoxPort::PD, - i, - Some(IoxFunction::AF1), - None, - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - } - // SPIM_CSN0_A[0] - setup_port( - &mut iox, - IoxPort::PD, - 5, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - // SPIM_CSN0_A[1] - setup_port( - &mut iox, - IoxPort::PD, - 6, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - udma_global.clock_on(PeriphId::Spim0); // JQSPI1 - SpimChannel::Channel0 - }; - #[cfg(not(feature = "spi-alt-channel"))] - let channel = { - // JPC7_13 - // SPIM_CLK_A[1] - setup_port( - &mut iox, - IoxPort::PC, - 11, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive4mA), - Some(IoxEnable::Enable), - None, - None, - ); - // SPIM_SD[0-3]_A[1] - for i in 7..11 { - setup_port( - &mut iox, - IoxPort::PC, - i, - Some(IoxFunction::AF1), - None, - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - } - // SPIM_CSN0_A[1] - setup_port( - &mut iox, - IoxPort::PC, - 12, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - // SPIM_CSN0_A[1] - setup_port( - &mut iox, - IoxPort::PC, - 13, - Some(IoxFunction::AF1), - Some(IoxDir::Output), - Some(IoxDriveStrength::Drive2mA), - Some(IoxEnable::Enable), - None, - None, - ); - udma_global.clock_on(PeriphId::Spim1); // JPC7_13 - SpimChannel::Channel1 - }; + let iox = Iox::new(utralib::generated::HW_IOX_BASE as *mut u32); + let channel = cramium_hal::board::setup_memory_pins(&iox); + udma_global.clock_on(PeriphId::from(channel)); // safety: this is safe because clocks have been set up let mut flash_spim = unsafe { @@ -235,7 +93,8 @@ impl SwapHal { crate::println!("flash ID: {:x}", flash_id); crate::println!("ram ID: {:x}", ram_id); // density 18, memory type 20, mfg ID C2 ==> MX25L128833F - assert!(flash_id & 0xFF_FF_FF == 0x1820C2); + // density 38, memory type 25, mfg ID C2 ==> MX25U12832F + assert!(flash_id & 0xFF_FF_FF == 0x1820C2 || flash_id & 0xFF_FF_FF == 0x38_25_C2); // KGD 5D, mfg ID 9D; remainder of bits are part of the EID assert!(ram_id & 0xFF_FF == 0x5D9D); @@ -260,7 +119,8 @@ impl SwapHal { crate::println!("QPI flash ID: {:x}", flash_id); crate::println!("QPI ram ID: {:x}", ram_id); // density 18, memory type 20, mfg ID C2 ==> MX25L128833F - assert!(flash_id & 0xFF_FF_FF == 0x1820C2); + // density 38, memory type 25, mfg ID C2 ==> MX25U12832F + assert!(flash_id & 0xFF_FF_FF == 0x1820C2 || flash_id & 0xFF_FF_FF == 0x38_25_C2); // KGD 5D, mfg ID 9D; remainder of bits are part of the EID assert!(ram_id & 0xFF_FF == 0x5D9D); @@ -522,7 +382,7 @@ pub fn userspace_maps(cfg: &mut BootConfig) { SWAPPER_PID, ); - let mut iox = Iox::new(utralib::utra::iox::HW_IOX_BASE as *mut u32); + let iox = Iox::new(utralib::utra::iox::HW_IOX_BASE as *mut u32); iox.set_alternate_function(IoxPort::PD, 2, IoxFunction::AF2); iox.set_alternate_function(IoxPort::PD, 3, IoxFunction::AF2); // rx as input, with pull-up @@ -532,7 +392,7 @@ pub fn userspace_maps(cfg: &mut BootConfig) { iox.set_gpio_dir(IoxPort::PD, 3, IoxDir::Output); // Set up the UDMA_UART block to the correct baud rate and enable status - let mut udma_global = + let udma_global = cramium_hal::udma::GlobalConfig::new(utralib::utra::udma_ctrl::HW_UDMA_CTRL_BASE as *mut u32); udma_global.clock_on(cramium_hal::udma::PeriphId::Uart0); udma_global.map_event( diff --git a/loader/src/platform/cramium/update.rs b/loader/src/platform/cramium/update.rs new file mode 100644 index 000000000..5aabce976 --- /dev/null +++ b/loader/src/platform/cramium/update.rs @@ -0,0 +1,9 @@ +/// Checks to see if the necessary conditions for an update are met +pub fn process_update() { + // Placeholder: + // Remember to lock the root keys before processing any updates + crate::platform::cramium::verifier::lifecycle_lock_root(); + { + // update code here + } +} diff --git a/loader/src/platform/cramium/verifier.rs b/loader/src/platform/cramium/verifier.rs new file mode 100644 index 000000000..f2cc70dff --- /dev/null +++ b/loader/src/platform/cramium/verifier.rs @@ -0,0 +1,4 @@ +pub fn lifecycle_lock_root() { + // placeholder to lock out access to root secrets due to the lifecycle being advanced past + // signature verification +} diff --git a/loader/src/swap.rs b/loader/src/swap.rs index 101712029..af1a68474 100644 --- a/loader/src/swap.rs +++ b/loader/src/swap.rs @@ -98,16 +98,6 @@ pub struct SwapSpec { pub sram_size: u32, } -// RAM needs two buffers of 1k + 16 bytes = 2048 + 16 = 2064 bytes; round up to one page -#[allow(dead_code)] -#[cfg(feature = "cramium-soc")] -pub const SPIM_RAM_IFRAM_ADDR: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 2 * 4096; -// Flash will be released after the loader is done: it's only accessed to copy the IniS sectors into swap, -// then abandoned. It needs 4096 bytes for Rx, and 0 bytes for Tx + 16 bytes for cmd. -#[allow(dead_code)] -#[cfg(feature = "cramium-soc")] -pub const SPIM_FLASH_IFRAM_ADDR: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 5 * 4096; - /// Function that derives the usable amount of swap space from the total length of swap memory available. /// This is used repeatedly in the initialization process to define the boundary between the swap page /// storage and the message authentication code (MAC) tables. diff --git a/services/cram-console/src/cmds/mbox.rs b/services/cram-console/src/cmds/mbox.rs index dd24f9c7a..6b81302e3 100644 --- a/services/cram-console/src/cmds/mbox.rs +++ b/services/cram-console/src/cmds/mbox.rs @@ -12,6 +12,8 @@ const TX_FIFO_DEPTH: u32 = 128; const CLIFFORD_SIZE: usize = 128; +const FLASH_TEST_PAGE: usize = 0x602F_0000; + #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[allow(dead_code)] pub enum MboxError { @@ -32,6 +34,7 @@ pub enum ToRvOp { RetKnock = 128, RetDct8x8 = 129, RetClifford = 130, + RetFlashWrite = 131, } impl TryFrom for ToRvOp { type Error = MboxError; @@ -42,6 +45,7 @@ impl TryFrom for ToRvOp { 128 => Ok(ToRvOp::RetKnock), 129 => Ok(ToRvOp::RetDct8x8), 130 => Ok(ToRvOp::RetClifford), + 131 => Ok(ToRvOp::RetFlashWrite), _ => Err(MboxError::InvalidOpcode), } } @@ -56,6 +60,7 @@ pub enum ToCm7Op { Knock = 1, Dct8x8 = 2, Clifford = 3, + FlashWrite = 4, } pub struct MboxToCm7Pkt<'a> { @@ -74,6 +79,7 @@ pub struct Mbox { csr: CSR, phys_mem: xous::MemoryRange, modals: Modals, + flash_window: xous::MemoryRange, } impl Mbox { pub fn new() -> Mbox { @@ -119,9 +125,17 @@ impl Mbox { // generate available events - not hooked up to IRQ, but we'll poll for now csr.wfo(mailbox::EV_ENABLE_AVAILABLE, 1); + let flash_mem = xous::syscall::map_memory( + xous::MemoryAddress::new(FLASH_TEST_PAGE), + None, + 4096, + xous::MemoryFlags::R | xous::MemoryFlags::W, + ) + .expect("couldn't map flash test window"); + let xns = xous_names::XousNames::new().unwrap(); - Self { csr, phys_mem: phys_mem.unwrap(), modals: Modals::new(&xns).unwrap() } + Self { csr, phys_mem: phys_mem.unwrap(), modals: Modals::new(&xns).unwrap(), flash_window: flash_mem } } fn expect_tx(&mut self, val: u32) -> Result<(), MboxError> { @@ -257,6 +271,94 @@ impl<'a> ShellCmdApi<'a> for Mbox { } }; } + "flashtest" => { + let mut test_data = [FLASH_TEST_PAGE as u32, 0x8, 0xace0_ba55, 0xfeed_face]; + log::info!("Flash write of {:x?}", test_data); + + let orig_data = { + let flash_slice: &[u8] = unsafe { self.flash_window.as_slice() }; + flash_slice.to_vec() + }; + let test_word = u32::from_le_bytes(orig_data[..4].try_into().unwrap()); + log::info!("Data values before writing: {:x} {:x?}", test_word, &orig_data[..8]); + if test_word == test_data[2] { + log::info!("inverting test data"); + // invert the bit sense for the test + test_data[2] = !test_data[2]; + test_data[3] = !test_data[3]; + log::info!("Test data: {:x?}", &test_data); + } + let write_pkt = MboxToCm7Pkt { + version: MBOX_PROTOCOL_REV, + opcode: ToCm7Op::FlashWrite, + data: &test_data, + }; + match self.try_send(write_pkt) { + Ok(_) => { + write!(ret, "Packet send Ok\n").ok(); + log::info!("flash write sent OK"); + let start = env.ticktimer.elapsed_ms(); + while self.poll_not_ready() { + xous::yield_slice(); + if env.ticktimer.elapsed_ms() - start > 1000 { + write!(ret, "Response timeout!\n").ok(); + log::info!("flash write timeout"); + return Ok(Some(ret)); + } + } + // now receive the packet + match self.try_rx() { + Ok(rx_pkt) => { + log::info!("Knock result: {:x}", rx_pkt.data[0]); + if rx_pkt.version != MBOX_PROTOCOL_REV { + write!( + ret, + "Version mismatch {} != {}", + rx_pkt.version, MBOX_PROTOCOL_REV + ) + .ok(); + } + if rx_pkt.opcode != ToRvOp::RetFlashWrite { + write!( + ret, + "Opcode mismatch {} != {}", + rx_pkt.opcode as u16, + ToRvOp::RetFlashWrite as u16 + ) + .ok(); + } + if rx_pkt.data.len() != 1 { + write!( + ret, + "Expected length mismatch {} != {}", + rx_pkt.data.len(), + 1 + ) + .ok(); + } else { + log::info!("Wrote {} bytes", rx_pkt.data[0]); + cache_flush(); + let flash_slice: &[u8] = unsafe { self.flash_window.as_slice() }; + log::info!("Data values before writing: {:x?}", &orig_data[..16]); + log::info!("Data values after writing: {:x?}", &flash_slice[..16]); + if flash_slice.eq(&orig_data) { + log::info!("Fail: flash data did not change"); + } else { + log::info!("Pass: flash data updated"); + } + } + } + Err(e) => { + write!(ret, "Error while deserializing: {:?}\n", e).ok(); + } + } + } + Err(e) => { + write!(ret, "Packet send error: {:?}\n", e).ok(); + log::info!("Flash write send error: {:?}", e); + } + } + } // Time trial results // - on Precursor (100MHz): 27.60 seconds // - RV32 Daric (400MHz): 10.11 seconds (2.72x over Precursor) @@ -410,3 +512,18 @@ impl<'a> ShellCmdApi<'a> for Mbox { Ok(Some(ret)) } } + +#[inline(always)] +fn cache_flush() { + unsafe { + #[rustfmt::skip] + core::arch::asm!( + ".word 0x500F", + "nop", + "nop", + "nop", + "nop", + "nop", + ); + } +} diff --git a/services/cram-hal-service/src/iox_lib.rs b/services/cram-hal-service/src/iox_lib.rs index 5602dfdea..3bc96992a 100644 --- a/services/cram-hal-service/src/iox_lib.rs +++ b/services/cram-hal-service/src/iox_lib.rs @@ -1,6 +1,8 @@ use core::sync::atomic::Ordering; -use cramium_hal::iox::{IoxDir, IoxDriveStrength, IoxEnable, IoxFunction, IoxPort, IoxValue}; +use cramium_hal::iox::{ + IoGpio, IoSetup, IoxDir, IoxDriveStrength, IoxEnable, IoxFunction, IoxPort, IoxValue, +}; use num_traits::*; use crate::{Opcode, SERVER_NAME_CRAM_HAL, api::IoxConfigMessage}; @@ -18,23 +20,6 @@ impl IoxHal { IoxHal { conn } } - pub fn setup_io_pin( - &self, - port: IoxPort, - pin: u8, - direction: Option, - function: Option, - schmitt_trigger: Option, - pullup: Option, - slow_slew: Option, - strength: Option, - ) { - let msg = - IoxConfigMessage { port, pin, direction, function, schmitt_trigger, pullup, slow_slew, strength }; - let buf = xous_ipc::Buffer::into_buf(msg).unwrap(); - buf.lend(self.conn, Opcode::ConfigureIox.to_u32().unwrap()).expect("Couldn't set up IO"); - } - pub fn set_gpio_pin_value(&self, port: IoxPort, pin: u8, value: IoxValue) { xous::send_message( self.conn, @@ -138,6 +123,48 @@ impl IoxHal { } } +impl IoSetup for IoxHal { + fn setup_pin( + &self, + port: IoxPort, + pin: u8, + direction: Option, + function: Option, + schmitt_trigger: Option, + pullup: Option, + slow_slew: Option, + strength: Option, + ) { + let msg = + IoxConfigMessage { port, pin, direction, function, schmitt_trigger, pullup, slow_slew, strength }; + let buf = xous_ipc::Buffer::into_buf(msg).unwrap(); + buf.lend(self.conn, Opcode::ConfigureIox.to_u32().unwrap()).expect("Couldn't set up IO"); + } +} + +impl IoGpio for IoxHal { + fn get_gpio_pin_value(&self, port: IoxPort, pin: u8) -> IoxValue { self.get_gpio_pin_value(port, pin) } + + fn set_gpio_pin_dir(&self, port: IoxPort, pin: u8, dir: IoxDir) { + let msg = IoxConfigMessage { + port, + pin, + direction: Some(dir), + function: None, + schmitt_trigger: None, + pullup: None, + slow_slew: None, + strength: None, + }; + let buf = xous_ipc::Buffer::into_buf(msg).unwrap(); + buf.lend(self.conn, Opcode::ConfigureIox.to_u32().unwrap()).expect("Couldn't set up IO"); + } + + fn set_gpio_pin_value(&self, port: IoxPort, pin: u8, value: IoxValue) { + self.set_gpio_pin_value(port, pin, value); + } +} + impl Drop for IoxHal { fn drop(&mut self) { // de-allocate myself. It's unsafe because we are responsible to make sure nobody else is using the diff --git a/services/cram-hal-service/src/lib.rs b/services/cram-hal-service/src/lib.rs index 4bae7b100..f0b4e2e5a 100644 --- a/services/cram-hal-service/src/lib.rs +++ b/services/cram-hal-service/src/lib.rs @@ -4,7 +4,7 @@ pub mod keyboard; pub mod trng; use api::Opcode; -use cramium_hal::udma::{EventChannel, PeriphEventType, PeriphId}; +use cramium_hal::udma::{EventChannel, PeriphEventType, PeriphId, UdmaGlobalConfig}; pub use iox_lib::*; use num_traits::*; @@ -64,3 +64,16 @@ impl UdmaGlobal { .expect("Couldn't setup UDMA event mapping"); } } + +impl UdmaGlobalConfig for UdmaGlobal { + fn clock(&self, peripheral: PeriphId, enable: bool) { self.udma_clock_config(peripheral, enable); } + + unsafe fn udma_event_map( + &self, + peripheral: PeriphId, + event_type: PeriphEventType, + to_channel: EventChannel, + ) { + self.udma_event_map(peripheral, event_type, to_channel); + } +} diff --git a/services/cram-hal-service/src/main.rs b/services/cram-hal-service/src/main.rs index d6066c4d4..b7872009d 100644 --- a/services/cram-hal-service/src/main.rs +++ b/services/cram-hal-service/src/main.rs @@ -102,19 +102,24 @@ fn main() { ifram_allocs[0].push(None); ifram_allocs[1].push(None); } - // Top page of IFRAM0 is occupied by the log server's Tx buffer. We can't know the - // `Sender` of it, so fill it with a value for `Some` that can't map to any PID. - ifram_allocs[0][31] = Some(Sender::from_usize(usize::MAX)); + // mark loader-hardwired pages for IFRAM0 + for i in + cramium_hal::board::IFRAM0_RESERVED_PAGE_RANGE[0]..=cramium_hal::board::IFRAM0_RESERVED_PAGE_RANGE[1] + { + ifram_allocs[0][i] = Some(Sender::from_usize(usize::MAX)); + } + // mark loader-hardwired pages for IFRAM1 + for i in + cramium_hal::board::IFRAM1_RESERVED_PAGE_RANGE[0]..=cramium_hal::board::IFRAM1_RESERVED_PAGE_RANGE[1] + { + ifram_allocs[1][i] = Some(Sender::from_usize(usize::MAX)); + } // Second page from top of IFRAM0 is occupied by the swap handler. This was allocated - // by the loader, before the kernel even started. + // by the loader, before the kernel even started. Mark the PID properly. #[cfg(feature = "swap")] { ifram_allocs[0][30] = Some(Sender::from_usize(SWAPPER_PID as usize)); } - #[cfg(feature = "app-uart")] - { - ifram_allocs[0][29] = Some(Sender::from_usize(usize::MAX)); - } let iox_page = xous::syscall::map_memory( xous::MemoryAddress::new(utralib::generated::HW_IOX_BASE), @@ -123,7 +128,7 @@ fn main() { xous::MemoryFlags::R | xous::MemoryFlags::W, ) .expect("couldn't claim the IOX hardware page"); - let mut iox = iox::Iox::new(iox_page.as_mut_ptr() as *mut u32); + let iox = iox::Iox::new(iox_page.as_ptr() as *mut u32); let udma_global_csr = xous::syscall::map_memory( xous::MemoryAddress::new(utralib::generated::HW_UDMA_CTRL_BASE), @@ -132,7 +137,7 @@ fn main() { xous::MemoryFlags::R | xous::MemoryFlags::W, ) .expect("couldn't map UDMA global control"); - let mut udma_global = GlobalConfig::new(udma_global_csr.as_mut_ptr() as *mut u32); + let udma_global = GlobalConfig::new(udma_global_csr.as_mut_ptr() as *mut u32); let mut pio_ss = xous_pio::PioSharedState::new(); // map and enable the interrupt for the PIO system timer diff --git a/services/graphics-server/Cargo.toml b/services/graphics-server/Cargo.toml index 48ce98167..e16518829 100644 --- a/services/graphics-server/Cargo.toml +++ b/services/graphics-server/Cargo.toml @@ -43,10 +43,13 @@ cramium-soc = [ "cramium-hal", "cramium-hal/std", ] +board-baosec = ["cramium-hal/board-baosec"] +board-baosor = ["cramium-hal/board-baosor"] +board-dabao = ["cramium-hal/board-dabao"] + precursor = ["utralib/precursor"] hosted = ["utralib/hosted"] renode = ["utralib/renode"] -spi-alt-channel = [] debugprint = [] braille = [] gfx-testing = [] diff --git a/services/graphics-server/src/backend/cramium.rs b/services/graphics-server/src/backend/cramium.rs index e3b1b65da..ed1359cc4 100644 --- a/services/graphics-server/src/backend/cramium.rs +++ b/services/graphics-server/src/backend/cramium.rs @@ -66,8 +66,9 @@ use core::mem::size_of; use cram_hal_service::IoxHal; +use cramium_hal::board::setup_display_pins; +use cramium_hal::udma; use cramium_hal::udma::PeriphId; -use cramium_hal::{iox, udma}; use crate::api::Point; use crate::api::{LINES, WIDTH}; @@ -104,99 +105,8 @@ impl XousDisplay { // setup the I/O pins let iox = IoxHal::new(); - #[cfg(feature = "spi-alt-channel")] - let channel = { - const SPI_CS_PIN: u8 = 10; - const SPI_CLK_PIN: u8 = 7; - const SPI_DAT_PIN: u8 = 8; - const SPI_PORT: iox::IoxPort = iox::IoxPort::PD; - - // SPIM_CLK_B[1] - iox.setup_io_pin( - SPI_PORT, - SPI_CLK_PIN, - Some(iox::IoxDir::Output), - Some(iox::IoxFunction::AF2), - None, - None, - Some(iox::IoxEnable::Enable), - Some(iox::IoxDriveStrength::Drive2mA), - ); - // SPIM_SD0_B[1] - iox.setup_io_pin( - SPI_PORT, - SPI_DAT_PIN, - Some(iox::IoxDir::Output), - Some(iox::IoxFunction::AF2), - None, - None, - Some(iox::IoxEnable::Enable), - Some(iox::IoxDriveStrength::Drive2mA), - ); - // SPIM_SCSN0_B[1] - // chip select toggle by UDMA has ~6 cycles setup and 1 cycles hold time, which - // meets the requirements for the display. - iox.setup_io_pin( - SPI_PORT, - SPI_CS_PIN, - Some(iox::IoxDir::Output), - Some(iox::IoxFunction::AF2), - None, - Some(iox::IoxEnable::Enable), - Some(iox::IoxEnable::Enable), - Some(iox::IoxDriveStrength::Drive2mA), - ); - // using bank SPIM_B[1] - udma_global.udma_clock_config(PeriphId::Spim1, true); - udma::SpimChannel::Channel1 - }; - - #[cfg(not(feature = "spi-alt-channel"))] - 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_io_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_io_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_io_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.udma_clock_config(PeriphId::Spim0, true); - udma::SpimChannel::Channel0 - }; + let (channel, _, _, _) = setup_display_pins(&iox); + udma_global.udma_clock_config(PeriphId::from(channel), true); log::info!("gfx using spi channel {:?}", channel); // safety: this is safe because we remembered to set up the clock config; and, diff --git a/services/graphics-server/src/betrusted-128x128.bmp b/services/graphics-server/src/betrusted-128x128.bmp new file mode 100644 index 000000000..0750ddc32 Binary files /dev/null and b/services/graphics-server/src/betrusted-128x128.bmp differ diff --git a/services/graphics-server/src/convert_bmp_sh1107.py b/services/graphics-server/src/convert_bmp_sh1107.py new file mode 100644 index 000000000..79dfac027 --- /dev/null +++ b/services/graphics-server/src/convert_bmp_sh1107.py @@ -0,0 +1,98 @@ +#!/usr/bin/python3 + +import argparse +import numpy as np + +def bitflip(data_block, bitwidth=32): + if bitwidth == 0: + return data_block + + bytewidth = bitwidth // 8 + bitswapped = bytearray() + + i = 0 + while i < len(data_block): + data = int.from_bytes(data_block[i:i+bytewidth], byteorder='big', signed=False) + b = '{:0{width}b}'.format(data, width=bitwidth) + bitswapped.extend(int(b[::-1], 2).to_bytes(bytewidth, byteorder='big')) + i = i + bytewidth + + return bytes(bitswapped) + + +def convert(ifile, ofile): + with open(ifile, "rb") as f: + image = f.read() + + offset = image[0xa] # skip header + length = len(image) - offset + if length != 2050: + print("Image is not a full frame: {}", length) + exit(1) + + bitmap = [] + for index in range(2048): + b = image[offset + index] + bits = [] + for bit in range(8): + if (b >> (7 - bit)) & 1 == 0: + bits += [0] + else: + bits += [1] + bitmap += bits + + if False: + # Reshape the flat bitmap into a 2D array (row-normal) + bitmap_2d = np.array(bitmap).reshape((128, 128)) + + # Transpose the 2D array to convert it to column-normal + transposed_bitmap_2d = bitmap_2d.T + + # Flatten the transposed 2D array back to a 1D list (column-normal) + column_normal_bitmap = transposed_bitmap_2d.flatten() + + rotated = [] + for index in range(2048): + bits = column_normal_bitmap[index * 8 : (index + 1) * 8] + b = 0 + for (i, bit) in enumerate(bits): + if bit != 0: + b |= 1 << (7-i) + rotated += [b] + else: + rotated = [] + for index in range(2048): + rotated += [image[offset + index]] + + with open(ofile, "w") as output: + output.write("#![cfg_attr(rustfmt, rustfmt_skip)]\n") + output.write("pub const LOGO_MAP: [u8; 2048] = [") + for index in range(2048): + if index % 16 == 0: + output.write("\n") + b = rotated[index] + if index % 16 < 15: + output.write("0x{:02x}, ".format(b)) + else: + output.write("0x{:02x},".format(b)) + output.write("\n];\n") + + +def main(): + parser = argparse.ArgumentParser(description="Convert BMP to rust header file") + parser.add_argument( + "-f", "--file", required=True, help="filename to process", type=str + ) + parser.add_argument( + "-o", "--output-file", required=False, help="name of output Rust file", type=str, default="logo.rs" + ) + args = parser.parse_args() + + ifile = args.file + + convert(ifile, args.output_file) + + +if __name__ == "__main__": + main() + diff --git a/services/xous-log/Cargo.toml b/services/xous-log/Cargo.toml index 0236b683b..6de5fc259 100644 --- a/services/xous-log/Cargo.toml +++ b/services/xous-log/Cargo.toml @@ -41,6 +41,10 @@ cramium-hal = { path = "../../libs/cramium-hal", optional = true, default-featur [features] cramium-soc = ["utralib/cramium-soc", "cramium-hal"] cramium-fpga = ["utralib/cramium-fpga"] +board-baosec = ["cramium-hal/board-baosec"] +board-baosor = ["cramium-hal/board-baosor"] +board-dabao = ["cramium-hal/board-dabao"] + precursor = ["utralib/precursor"] hosted = ["utralib/hosted"] renode = ["utralib/renode"] diff --git a/services/xous-log/src/platform/cramium/debug.rs b/services/xous-log/src/platform/cramium/debug.rs index d3631e14a..a89b7c4a5 100644 --- a/services/xous-log/src/platform/cramium/debug.rs +++ b/services/xous-log/src/platform/cramium/debug.rs @@ -57,7 +57,7 @@ impl Uart { let mut uart = unsafe { udma::Uart::get_handle( crate::platform::debug::DEFAULT_UART_ADDR as usize, - crate::implementation::UART_DMA_TX_BUF_PHYS, + cramium_hal::board::UART_DMA_TX_BUF_PHYS, crate::implementation::UART_DMA_TX_BUF_VIRT as usize, ) }; diff --git a/services/xous-log/src/platform/cramium/implementation.rs b/services/xous-log/src/platform/cramium/implementation.rs index 0592be4c5..b1d689370 100644 --- a/services/xous-log/src/platform/cramium/implementation.rs +++ b/services/xous-log/src/platform/cramium/implementation.rs @@ -1,6 +1,7 @@ use core::fmt::{Error, Write}; use std::pin::Pin; +use cramium_hal::board::UART_DMA_TX_BUF_PHYS; use cramium_hal::udma; use utralib::generated::*; @@ -15,9 +16,6 @@ pub static mut UART_IRQ: Option>> = None; #[cfg(feature = "cramium-soc")] pub static mut KBD_CONN: u32 = 0; -#[cfg(feature = "cramium-soc")] -pub const UART_DMA_TX_BUF_PHYS: usize = utralib::HW_IFRAM0_MEM + utralib::HW_IFRAM0_MEM_LEN - 4096; - pub fn init() -> Output { #[cfg(feature = "cramium-fpga")] let uart = xous::syscall::map_memory( diff --git a/services/xous-swapper/Cargo.toml b/services/xous-swapper/Cargo.toml index 9614ce4b3..3357ed91b 100644 --- a/services/xous-swapper/Cargo.toml +++ b/services/xous-swapper/Cargo.toml @@ -29,8 +29,11 @@ utralib = { version = "0.1.25", optional = true, default-features = false } [features] cramium-soc = ["utralib/cramium-soc", "cramium-hal", "loader/cramium-soc"] -spi-alt-channel = [] # needs to match loader setting! cramium-fpga = ["utralib/cramium-fpga"] +board-baosec = ["cramium-hal/board-baosec"] +board-baosor = ["cramium-hal/board-baosor"] +board-dabao = ["cramium-hal/board-dabao"] + precursor = ["utralib/precursor"] hosted = ["utralib/hosted"] renode = ["utralib/renode"] diff --git a/services/xous-swapper/src/debug.rs b/services/xous-swapper/src/debug.rs index a1c669772..e44834b01 100644 --- a/services/xous-swapper/src/debug.rs +++ b/services/xous-swapper/src/debug.rs @@ -22,7 +22,7 @@ impl DebugUart { let mut uart = unsafe { udma::Uart::get_handle( loader::swap::SWAP_APP_UART_VADDR as usize, - loader::APP_UART_IFRAM_ADDR as usize, + cramium_hal::board::APP_UART_IFRAM_ADDR as usize, loader::swap::SWAP_APP_UART_IFRAM_VADDR as usize, ) }; diff --git a/services/xous-swapper/src/platform/cramium/hw.rs b/services/xous-swapper/src/platform/cramium/hw.rs index 08f091d7e..01ed61c56 100644 --- a/services/xous-swapper/src/platform/cramium/hw.rs +++ b/services/xous-swapper/src/platform/cramium/hw.rs @@ -2,9 +2,10 @@ use core::fmt::Write; use core::mem::size_of; use aes_gcm_siv::{AeadInPlace, Aes256GcmSiv, Error, KeyInit, Nonce, Tag}; +use cramium_hal::board::SPIM_RAM_IFRAM_ADDR; use cramium_hal::ifram::IframRange; use cramium_hal::udma::*; -use loader::swap::{SPIM_RAM_IFRAM_ADDR, SWAP_HAL_VADDR, SwapSpec}; +use loader::swap::{SWAP_HAL_VADDR, SwapSpec}; use crate::debug::*; @@ -26,9 +27,6 @@ impl SwapHal { // because once we remove the MAC area, we need even less storage, but it's a small error. let ram_size_actual = loader::swap::derive_usable_swap(spec.swap_len as usize); - #[cfg(feature = "spi-alt-channel")] - let channel = SpimChannel::Channel0; - #[cfg(not(feature = "spi-alt-channel"))] let channel = SpimChannel::Channel1; Self { swap_mac_start: ram_size_actual, diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 9090039c5..098ff0302 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -481,6 +481,12 @@ fn main() -> Result<(), Box> { // ------ Cramium hardware image configs ------ Some("cramium-fpga") | Some("cramium-soc") => { + let board = "board-baosec"; + // select the board + builder.add_feature(board); + builder.add_loader_feature(board); + builder.add_kernel_feature(board); + // placement in flash is a tension between dev convenience and RAM usage. Things in flash // are resident, non-swapable, but end up making the slow kernel burn process take longer. let cramium_flash_pkgs = [ @@ -500,15 +506,15 @@ fn main() -> Result<(), Box> { if !builder.is_swap_set() { builder.set_swap(0, 4 * 1024 * 1024); } - // builder.add_loader_feature("board-bringup"); + builder.add_loader_feature("board-bringup"); // builder.add_loader_feature("spim-test"); // builder.add_loader_feature("spi-alt-channel"); // this flag, when asserted, uses the J_QSPI + // header. By default, we use JPC7_13 (J_QSPI does not work, for some reason; bit 3 is stuck + // high...) // builder.add_loader_feature("irq-test"); // builder.add_loader_feature("usb-test"); // builder.add_loader_feature("trng-test"); // builder.add_loader_feature("dump-trng"); - // header. By default, we use JPC7_13 (J_QSPI does not work, for some reason; bit 3 is stuck - // high...) builder.add_loader_feature("swap"); builder.add_kernel_feature("swap"); builder.add_feature("swap"); @@ -523,6 +529,7 @@ fn main() -> Result<(), Box> { builder.add_kernel_feature("v2p"); builder.add_feature("mass-storage"); builder.add_feature("ditherpunk"); + match task.as_deref() { Some("cramium-fpga") => builder.target_cramium_fpga(), Some("cramium-soc") => builder.target_cramium_soc(),