From 4257b7618364f1d8ce4c9811ab88c410e057453d Mon Sep 17 00:00:00 2001 From: equation314 Date: Wed, 12 Dec 2018 01:24:36 +0800 Subject: [PATCH 01/14] aarch64/fb: add bcm2837 mailbox --- crate/bcm2837/src/lib.rs | 1 + crate/bcm2837/src/mailbox.rs | 80 ++++++++++++++++++++++++++++++++++ crate/bcm2837/src/mini_uart.rs | 31 ++++++------- 3 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 crate/bcm2837/src/mailbox.rs diff --git a/crate/bcm2837/src/lib.rs b/crate/bcm2837/src/lib.rs index 9635fdc..d8af5ab 100644 --- a/crate/bcm2837/src/lib.rs +++ b/crate/bcm2837/src/lib.rs @@ -5,6 +5,7 @@ extern crate volatile; pub mod gpio; pub mod timer; +pub mod mailbox; pub mod mini_uart; pub mod interrupt; diff --git a/crate/bcm2837/src/mailbox.rs b/crate/bcm2837/src/mailbox.rs new file mode 100644 index 0000000..89ca1d6 --- /dev/null +++ b/crate/bcm2837/src/mailbox.rs @@ -0,0 +1,80 @@ +use crate::IO_BASE; +use volatile::{ReadOnly, Volatile, WriteOnly}; + +/// The base address for the `MU` registers. +const MAILBOX_BASE: usize = IO_BASE + 0xB000 + 0x880; + +/// Available mailbox channels +/// +/// (ref: https://github.com/raspberrypi/firmware/wiki/Mailboxes) +#[repr(u8)] +#[derive(Copy, Clone, Debug)] +pub enum MailboxChannel { + Framebuffer = 1, + Property = 8, +} + +/// Read from mailbox status register (MAILx_STA). +#[repr(u32)] +enum MailboxStatus { + MailboxEmpty = 1 << 30, + MailboxFull = 1 << 31, +} + +/// Mailbox registers. We basically only support mailbox 0 & 1. We +/// deliver to the VC in mailbox 1, it delivers to us in mailbox 0. See +/// BCM2835-ARM-Peripherals.pdf section 1.3 for an explanation about +/// the placement of memory barriers. +/// +/// (ref: https://github.com/raspberrypi/firmware/wiki/Mailboxes) +#[repr(C)] +#[allow(non_snake_case)] +struct Registers { + MAIL0_RD: ReadOnly, // 0x00 + __reserved0: [u32; 3], + MAIL0_POL: ReadOnly, // 0x10 + MAIL0_SND: ReadOnly, // 0x14 + MAIL0_STA: ReadOnly, // 0x18 + MAIL0_CNF: Volatile, // 0x1c + + MAIL1_WRT: WriteOnly, // 0x20 + __reserved1: [u32; 3], + _MAIL1_POL: ReadOnly, // 0x30 + _MAIL1_SND: ReadOnly, // 0x34 + MAIL1_STA: ReadOnly, // 0x38 + _MAIL1_CNF: Volatile, // 0x3c +} + +/// The Raspberry Pi's mailbox. +/// +/// (ref: https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes) +pub struct Mailbox { + registers: &'static mut Registers, +} + +impl Mailbox { + /// Returns a new instance of `Mailbox`. + #[inline] + pub fn new() -> Mailbox { + Mailbox { + registers: unsafe { &mut *(MAILBOX_BASE as *mut Registers) }, + } + } + + // Read from the requested channel of mailbox 0. + pub fn read(&self, channel: MailboxChannel) -> u32 { + loop { + while self.registers.MAIL0_STA.read() & (MailboxStatus::MailboxEmpty as u32) != 0 {} + let data = self.registers.MAIL0_RD.read(); + if data & 0xF == channel as u32 { + return data & !0xF; + } + } + } + + // Write to the requested channel of mailbox 1. + pub fn write(&mut self, channel: MailboxChannel, data: u32) { + while self.registers.MAIL1_STA.read() & (MailboxStatus::MailboxFull as u32) != 0 {} + self.registers.MAIL1_WRT.write((data & !0xF) | (channel as u32)); + } +} diff --git a/crate/bcm2837/src/mini_uart.rs b/crate/bcm2837/src/mini_uart.rs index c1d0101..a3a5503 100644 --- a/crate/bcm2837/src/mini_uart.rs +++ b/crate/bcm2837/src/mini_uart.rs @@ -2,12 +2,12 @@ use crate::IO_BASE; use crate::gpio::{Function, Gpio}; use volatile::{ReadOnly, Volatile}; -/// The base address for the `MU` registers. -const MU_REG_BASE: usize = IO_BASE + 0x215040; - /// The `AUXENB` register from page 9 of the BCM2837 documentation. const AUX_ENABLES: *mut Volatile = (IO_BASE + 0x215004) as *mut Volatile; +/// The base address for the `MU` registers. +const MU_REG_BASE: usize = IO_BASE + 0x215040; + /// Enum representing bit fields of the `AUX_MU_IIR_REG` register. #[repr(u8)] pub enum MiniUartInterruptId { @@ -55,19 +55,10 @@ pub struct MiniUart { } impl MiniUart { - /// Initializes the mini UART by enabling it as an auxiliary peripheral, - /// setting the data size to 8 bits, setting the BAUD rate to ~115200 (baud - /// divider of 270), setting GPIO pins 14 and 15 to alternative function 5 - /// (TXD1/RDXD1), and finally enabling the UART transmitter and receiver. - /// - /// By default, reads will never time out. To set a read timeout, use - /// `set_read_timeout()`. + /// Returns a new instance of `MiniUart`. + #[inline] pub fn new() -> MiniUart { - let registers = unsafe { - // Enable the mini UART as an auxiliary device. - (*AUX_ENABLES).write(1); - &mut *(MU_REG_BASE as *mut Registers) - }; + let registers = unsafe { &mut *(MU_REG_BASE as *mut Registers) }; MiniUart { registers: registers, @@ -75,7 +66,17 @@ impl MiniUart { } } + /// Initializes the mini UART by enabling it as an auxiliary peripheral, + /// setting the data size to 8 bits, setting the BAUD rate to ~115200 (baud + /// divider of 270), setting GPIO pins 14 and 15 to alternative function 5 + /// (TXD1/RDXD1), and finally enabling the UART transmitter and receiver. + /// + /// By default, reads will never time out. To set a read timeout, use + /// `set_read_timeout()`. pub fn init(&mut self) { + // Enable the mini UART as an auxiliary device. + unsafe { (*AUX_ENABLES).write(1) } + Gpio::new(14).into_alt(Function::Alt5).set_gpio_pd(0); Gpio::new(15).into_alt(Function::Alt5).set_gpio_pd(0); From d7511d81200e180a21210a81200a5ad9bb651375 Mon Sep 17 00:00:00 2001 From: equation314 Date: Fri, 14 Dec 2018 21:19:44 +0800 Subject: [PATCH 02/14] aarch64/fb: add mailbox property interfaces --- crate/bcm2837/src/mailbox.rs | 4 +- kernel/Cargo.lock | 2 +- kernel/src/arch/aarch64/board/raspi3/irq.rs | 1 - .../src/arch/aarch64/board/raspi3/mailbox.rs | 266 ++++++++++++++++++ kernel/src/arch/aarch64/board/raspi3/mod.rs | 1 + kernel/src/arch/aarch64/mod.rs | 4 +- 6 files changed, 273 insertions(+), 5 deletions(-) create mode 100644 kernel/src/arch/aarch64/board/raspi3/mailbox.rs diff --git a/crate/bcm2837/src/mailbox.rs b/crate/bcm2837/src/mailbox.rs index 89ca1d6..0e7d32f 100644 --- a/crate/bcm2837/src/mailbox.rs +++ b/crate/bcm2837/src/mailbox.rs @@ -61,7 +61,7 @@ impl Mailbox { } } - // Read from the requested channel of mailbox 0. + /// Read from the requested channel of mailbox 0. pub fn read(&self, channel: MailboxChannel) -> u32 { loop { while self.registers.MAIL0_STA.read() & (MailboxStatus::MailboxEmpty as u32) != 0 {} @@ -72,7 +72,7 @@ impl Mailbox { } } - // Write to the requested channel of mailbox 1. + /// Write to the requested channel of mailbox 1. pub fn write(&mut self, channel: MailboxChannel, data: u32) { while self.registers.MAIL1_STA.read() & (MailboxStatus::MailboxFull as u32) != 0 {} self.registers.MAIL1_WRT.write((data & !0xF) | (channel as u32)); diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 064af4a..ecc04cb 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -1,7 +1,7 @@ [[package]] name = "aarch64" version = "2.2.2" -source = "git+https://github.com/equation314/aarch64#e3b60adb233ad34d05443e0b5ec34cac29253296" +source = "git+https://github.com/equation314/aarch64#06b2f5507dd5393e40c1506cd4414ef36864afc6" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/src/arch/aarch64/board/raspi3/irq.rs b/kernel/src/arch/aarch64/board/raspi3/irq.rs index d8730dc..9575e29 100644 --- a/kernel/src/arch/aarch64/board/raspi3/irq.rs +++ b/kernel/src/arch/aarch64/board/raspi3/irq.rs @@ -1,6 +1,5 @@ use crate::arch::interrupt::TrapFrame; use bcm2837::interrupt::Controller; -use log::*; pub use bcm2837::interrupt::Interrupt; diff --git a/kernel/src/arch/aarch64/board/raspi3/mailbox.rs b/kernel/src/arch/aarch64/board/raspi3/mailbox.rs new file mode 100644 index 0000000..83e1557 --- /dev/null +++ b/kernel/src/arch/aarch64/board/raspi3/mailbox.rs @@ -0,0 +1,266 @@ +//! Mailbox property interface +//! +//! (ref: https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface) + +use bcm2837::mailbox::{Mailbox, MailboxChannel}; +use lazy_static::lazy_static; +use core::mem; +use spin::Mutex; +use aarch64::barrier; + +lazy_static! { + static ref MAILBOX: Mutex = Mutex::new(Mailbox::new()); +} + +#[derive(Debug)] +pub struct PropertyMailboxError(u32); +pub type PropertyMailboxResult = Result; + +/// Buffer request/response code. +/// Copied from `linux/include/soc/bcm2835/raspberrypi-firmware.h` +#[repr(u32)] +#[allow(dead_code)] +#[derive(Copy, Clone, Debug)] +#[allow(non_camel_case_types)] +enum PropertyMailboxStatus { + RPI_FIRMWARE_STATUS_REQUEST = 0, + RPI_FIRMWARE_STATUS_SUCCESS = 0x80000000, + RPI_FIRMWARE_STATUS_ERROR = 0x80000001, +} +use self::PropertyMailboxStatus::*; + +/// Tag identifier. +/// Copied from `linux/include/soc/bcm2835/raspberrypi-firmware.h` +#[repr(u32)] +#[allow(dead_code)] +#[derive(Copy, Clone, Debug)] +#[allow(non_camel_case_types)] +enum PropertyMailboxTagId { + RPI_FIRMWARE_PROPERTY_END = 0, + RPI_FIRMWARE_GET_FIRMWARE_REVISION = 0x00000001, + + RPI_FIRMWARE_SET_CURSOR_INFO = 0x00008010, + RPI_FIRMWARE_SET_CURSOR_STATE = 0x00008011, + + RPI_FIRMWARE_GET_BOARD_MODEL = 0x00010001, + RPI_FIRMWARE_GET_BOARD_REVISION = 0x00010002, + RPI_FIRMWARE_GET_BOARD_MAC_ADDRESS = 0x00010003, + RPI_FIRMWARE_GET_BOARD_SERIAL = 0x00010004, + RPI_FIRMWARE_GET_ARM_MEMORY = 0x00010005, + RPI_FIRMWARE_GET_VC_MEMORY = 0x00010006, + RPI_FIRMWARE_GET_CLOCKS = 0x00010007, + RPI_FIRMWARE_GET_POWER_STATE = 0x00020001, + RPI_FIRMWARE_GET_TIMING = 0x00020002, + RPI_FIRMWARE_SET_POWER_STATE = 0x00028001, + RPI_FIRMWARE_GET_CLOCK_STATE = 0x00030001, + RPI_FIRMWARE_GET_CLOCK_RATE = 0x00030002, + RPI_FIRMWARE_GET_VOLTAGE = 0x00030003, + RPI_FIRMWARE_GET_MAX_CLOCK_RATE = 0x00030004, + RPI_FIRMWARE_GET_MAX_VOLTAGE = 0x00030005, + RPI_FIRMWARE_GET_TEMPERATURE = 0x00030006, + RPI_FIRMWARE_GET_MIN_CLOCK_RATE = 0x00030007, + RPI_FIRMWARE_GET_MIN_VOLTAGE = 0x00030008, + RPI_FIRMWARE_GET_TURBO = 0x00030009, + RPI_FIRMWARE_GET_MAX_TEMPERATURE = 0x0003000a, + RPI_FIRMWARE_GET_STC = 0x0003000b, + RPI_FIRMWARE_ALLOCATE_MEMORY = 0x0003000c, + RPI_FIRMWARE_LOCK_MEMORY = 0x0003000d, + RPI_FIRMWARE_UNLOCK_MEMORY = 0x0003000e, + RPI_FIRMWARE_RELEASE_MEMORY = 0x0003000f, + RPI_FIRMWARE_EXECUTE_CODE = 0x00030010, + RPI_FIRMWARE_EXECUTE_QPU = 0x00030011, + RPI_FIRMWARE_SET_ENABLE_QPU = 0x00030012, + RPI_FIRMWARE_GET_DISPMANX_RESOURCE_MEM_HANDLE = 0x00030014, + RPI_FIRMWARE_GET_EDID_BLOCK = 0x00030020, + RPI_FIRMWARE_GET_CUSTOMER_OTP = 0x00030021, + RPI_FIRMWARE_GET_DOMAIN_STATE = 0x00030030, + RPI_FIRMWARE_GET_THROTTLED = 0x00030046, + RPI_FIRMWARE_GET_CLOCK_MEASURED = 0x00030047, + RPI_FIRMWARE_NOTIFY_REBOOT = 0x00030048, + RPI_FIRMWARE_SET_CLOCK_STATE = 0x00038001, + RPI_FIRMWARE_SET_CLOCK_RATE = 0x00038002, + RPI_FIRMWARE_SET_VOLTAGE = 0x00038003, + RPI_FIRMWARE_SET_TURBO = 0x00038009, + RPI_FIRMWARE_SET_CUSTOMER_OTP = 0x00038021, + RPI_FIRMWARE_SET_DOMAIN_STATE = 0x00038030, + RPI_FIRMWARE_GET_GPIO_STATE = 0x00030041, + RPI_FIRMWARE_SET_GPIO_STATE = 0x00038041, + RPI_FIRMWARE_SET_SDHOST_CLOCK = 0x00038042, + RPI_FIRMWARE_GET_GPIO_CONFIG = 0x00030043, + RPI_FIRMWARE_SET_GPIO_CONFIG = 0x00038043, + RPI_FIRMWARE_GET_PERIPH_REG = 0x00030045, + RPI_FIRMWARE_SET_PERIPH_REG = 0x00038045, + RPI_FIRMWARE_GET_POE_HAT_VAL = 0x00030049, + RPI_FIRMWARE_SET_POE_HAT_VAL = 0x00030050, + + /* Dispmanx TAGS */ + RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE = 0x00040001, + RPI_FIRMWARE_FRAMEBUFFER_BLANK = 0x00040002, + RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT = 0x00040003, + RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_WIDTH_HEIGHT = 0x00040004, + RPI_FIRMWARE_FRAMEBUFFER_GET_DEPTH = 0x00040005, + RPI_FIRMWARE_FRAMEBUFFER_GET_PIXEL_ORDER = 0x00040006, + RPI_FIRMWARE_FRAMEBUFFER_GET_ALPHA_MODE = 0x00040007, + RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH = 0x00040008, + RPI_FIRMWARE_FRAMEBUFFER_GET_VIRTUAL_OFFSET = 0x00040009, + RPI_FIRMWARE_FRAMEBUFFER_GET_OVERSCAN = 0x0004000a, + RPI_FIRMWARE_FRAMEBUFFER_GET_PALETTE = 0x0004000b, + RPI_FIRMWARE_FRAMEBUFFER_GET_TOUCHBUF = 0x0004000f, + RPI_FIRMWARE_FRAMEBUFFER_GET_GPIOVIRTBUF = 0x00040010, + RPI_FIRMWARE_FRAMEBUFFER_RELEASE = 0x00048001, + RPI_FIRMWARE_FRAMEBUFFER_TEST_PHYSICAL_WIDTH_HEIGHT = 0x00044003, + RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_WIDTH_HEIGHT = 0x00044004, + RPI_FIRMWARE_FRAMEBUFFER_TEST_DEPTH = 0x00044005, + RPI_FIRMWARE_FRAMEBUFFER_TEST_PIXEL_ORDER = 0x00044006, + RPI_FIRMWARE_FRAMEBUFFER_TEST_ALPHA_MODE = 0x00044007, + RPI_FIRMWARE_FRAMEBUFFER_TEST_VIRTUAL_OFFSET = 0x00044009, + RPI_FIRMWARE_FRAMEBUFFER_TEST_OVERSCAN = 0x0004400a, + RPI_FIRMWARE_FRAMEBUFFER_TEST_PALETTE = 0x0004400b, + RPI_FIRMWARE_FRAMEBUFFER_TEST_VSYNC = 0x0004400e, + RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT = 0x00048003, + RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT = 0x00048004, + RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH = 0x00048005, + RPI_FIRMWARE_FRAMEBUFFER_SET_PIXEL_ORDER = 0x00048006, + RPI_FIRMWARE_FRAMEBUFFER_SET_ALPHA_MODE = 0x00048007, + RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET = 0x00048009, + RPI_FIRMWARE_FRAMEBUFFER_SET_OVERSCAN = 0x0004800a, + RPI_FIRMWARE_FRAMEBUFFER_SET_PALETTE = 0x0004800b, + RPI_FIRMWARE_FRAMEBUFFER_SET_TOUCHBUF = 0x0004801f, + RPI_FIRMWARE_FRAMEBUFFER_SET_GPIOVIRTBUF = 0x00048020, + RPI_FIRMWARE_FRAMEBUFFER_SET_VSYNC = 0x0004800e, + RPI_FIRMWARE_FRAMEBUFFER_SET_BACKLIGHT = 0x0004800f, + + RPI_FIRMWARE_VCHIQ_INIT = 0x00048010, + + RPI_FIRMWARE_GET_COMMAND_LINE = 0x00050001, + RPI_FIRMWARE_GET_DMA_CHANNELS = 0x00060001, +} +use self::PropertyMailboxTagId::*; + +/// A property mailbox tag. +#[repr(C, packed)] +#[derive(Debug)] +#[allow(safe_packed_borrows)] +struct PropertyMailboxTag { + id: PropertyMailboxTagId, + buf_size: u32, + req_resp_size: u32, + buf: T, +} + +/// A request that contained a sequence of concatenated tags. The response +/// overwrites the request. +#[repr(C, packed)] +#[derive(Debug)] +#[allow(safe_packed_borrows)] +struct PropertyMailboxRequest { + buf_size: u32, + req_resp_code: PropertyMailboxStatus, + buf: T, + end_tag: PropertyMailboxTagId, +} + +/// Request buffer address must be 16-byte aligned. +#[repr(C, align(16))] +#[derive(Debug)] +struct Align16(PropertyMailboxRequest); + +/// Pack a sequence of concatenated tags into a request, and send the address +/// to the mailbox. +/// Returns PropertyMailboxResult. +macro_rules! send_request { + ($tags: ident) => {{ + let req = Align16(PropertyMailboxRequest { + buf_size: mem::size_of_val(&$tags) as u32, + req_resp_code: RPI_FIRMWARE_STATUS_REQUEST, + buf: $tags, + end_tag: RPI_FIRMWARE_PROPERTY_END, + }); + + unsafe { barrier::wmb() } + { + let mut mbox = MAILBOX.lock(); + mbox.write(MailboxChannel::Property, &req as *const _ as u32); + mbox.read(MailboxChannel::Property); + } + unsafe { barrier::rmb() } + + match req.0.req_resp_code { + RPI_FIRMWARE_STATUS_SUCCESS => Ok(req.0.buf), + other => Err(PropertyMailboxError(other as u32)), + } + }}; +} + +/// Send a tag to mailbox. Will call `send_request!`. +/// Returns PropertyMailboxResult. +macro_rules! send_one_tag { + ($id: expr, [$($arg: expr),*]) => {{ + let buf = [$($arg),*]; + let tag = PropertyMailboxTag { + id: $id, + buf_size: mem::size_of_val(&buf) as u32, + req_resp_size: 0, + buf, + }; + Ok(send_request!(tag)?.buf) + }}; +} + +/// Allocates contiguous memory on the GPU. `size` and `align` are in bytes. +/// Returns memory `handle`. +pub fn mem_alloc(size: u32, align: u32, flags: u32) -> PropertyMailboxResult { + let ret = send_one_tag!(RPI_FIRMWARE_LOCK_MEMORY, [size, align, flags])?; + Ok(ret[0]) +} + +/// Free the memory buffer of `handle`. status=0 is success. +pub fn mem_free(handle: u32) -> PropertyMailboxResult<()> { + let status = send_one_tag!(RPI_FIRMWARE_RELEASE_MEMORY, [handle])?; + match status[0] { + 0 => Ok(()), + other => Err(PropertyMailboxError(other)), + } +} + +/// Lock buffer in place, and return a `bus_address`. Must be done before memory +/// can be accessed. +pub fn mem_lock(handle: u32) -> PropertyMailboxResult { + let ret = send_one_tag!(RPI_FIRMWARE_LOCK_MEMORY, [handle])?; + Ok(ret[0]) +} + +/// Unlock buffer. It retains contents, but may move. Needs to be locked before +/// next use. status=0 is success. +pub fn mem_unlock(handle: u32) -> PropertyMailboxResult<()> { + let status = send_one_tag!(RPI_FIRMWARE_UNLOCK_MEMORY, [handle])?; + match status[0] { + 0 => Ok(()), + other => Err(PropertyMailboxError(other)), + } +} + +/// Get physical (display) width/height. Returns `(width, height)` in pixels. +/// Note that the "physical (display)" size is the size of the allocated buffer +/// in memory, not the resolution of the video signal sent to the display device. +pub fn framebuffer_get_physical_size() -> PropertyMailboxResult<(u32, u32)> { + let ret = send_one_tag!(RPI_FIRMWARE_FRAMEBUFFER_GET_PHYSICAL_WIDTH_HEIGHT, [0, 0])?; + Ok((ret[0], ret[1])) +} + +/// Get depth. Returns bits per pixel. +pub fn framebuffer_get_depth() -> PropertyMailboxResult { + let ret = send_one_tag!(RPI_FIRMWARE_FRAMEBUFFER_GET_DEPTH, [0])?; + Ok(ret[0]) +} + +/// Set virtual offset. Returns `(X, Y)` in pixel. +/// The response may not be the same as the request so it must be checked. +/// May be the previous offset or 0 for unsupported. +pub fn framebuffer_set_virtual_offset(xoffset: u32, yoffset: u32) -> PropertyMailboxResult<(u32, u32)> { + let ret = send_one_tag!( + RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, + [xoffset, yoffset] + )?; + Ok((ret[0], ret[1])) +} diff --git a/kernel/src/arch/aarch64/board/raspi3/mod.rs b/kernel/src/arch/aarch64/board/raspi3/mod.rs index bfaa4f6..f62aad2 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mod.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mod.rs @@ -5,6 +5,7 @@ use once::*; pub mod irq; pub mod timer; pub mod serial; +pub mod mailbox; pub const IO_REMAP_BASE: usize = bcm2837::IO_BASE; pub const IO_REMAP_END: usize = 0x40001000; diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index 1d9269f..3edf8cb 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -18,10 +18,12 @@ global_asm!(include_str!("boot/boot.S")); #[no_mangle] // don't mangle the name of this function pub extern "C" fn rust_main() -> ! { memory::init_mmu_early(); // Enable mmu and paging + + crate::logging::init(); + board::init_early(); println!("{}", LOGO); - crate::logging::init(); interrupt::init(); memory::init(); driver::init(); From 6ba9e34f770edb7988adf615b47a84e570e69975 Mon Sep 17 00:00:00 2001 From: equation314 Date: Sun, 16 Dec 2018 20:55:04 +0800 Subject: [PATCH 03/14] aarch64/fb: add framebuffer initialization --- kernel/src/arch/aarch64/board/raspi3/fb.rs | 190 ++++++++++++++++++ .../src/arch/aarch64/board/raspi3/mailbox.rs | 93 ++++++++- kernel/src/arch/aarch64/board/raspi3/mod.rs | 8 +- .../src/arch/aarch64/board/raspi3/serial.rs | 10 +- kernel/src/arch/aarch64/mod.rs | 6 +- kernel/src/lib.rs | 2 + 6 files changed, 297 insertions(+), 12 deletions(-) create mode 100644 kernel/src/arch/aarch64/board/raspi3/fb.rs diff --git a/kernel/src/arch/aarch64/board/raspi3/fb.rs b/kernel/src/arch/aarch64/board/raspi3/fb.rs new file mode 100644 index 0000000..00ff2da --- /dev/null +++ b/kernel/src/arch/aarch64/board/raspi3/fb.rs @@ -0,0 +1,190 @@ +//! Framebuffer + +use super::mailbox; +use alloc::string::String; +use core::fmt; +use lazy_static::lazy_static; +use log::*; +use once::*; +use spin::Mutex; + +/// Framebuffer information +#[repr(C)] +#[derive(Debug, Clone, Copy)] +pub struct FramebufferInfo { + /// visible width + pub xres: u32, + /// visible height + pub yres: u32, + /// virtual width + pub xres_virtual: u32, + /// virtual height + pub yres_virtual: u32, + /// virtual offset x + pub xoffset: u32, + /// virtual offset y + pub yoffset: u32, + + /// bits per pixel + pub depth: u32, + /// bytes per line + pub pitch: u32, + + /// bus address, starts from 0xC0000000/0x40000000 + /// (see https://github.com/raspberrypi/firmware/wiki/Accessing-mailboxes) + pub bus_addr: u32, + /// screen buffer size + pub screen_size: u32, +} + +#[repr(u32)] +#[derive(Debug, Clone, Copy)] +#[allow(non_camel_case_types)] +pub enum ColorFormat { + BGR565 = 16, + RGBA8888 = 32, +} +use self::ColorFormat::*; + +#[repr(C)] +union ColorBuffer { + base_addr: u32, + buf16: &'static mut [u16], + buf32: &'static mut [u32], +} + +impl ColorBuffer { + fn new(color_format: ColorFormat, bus_addr: u32, size: u32) -> ColorBuffer { + unsafe { + match color_format { + BGR565 => ColorBuffer { + buf16: core::slice::from_raw_parts_mut( + bus_addr as *mut u16, + (size / 2) as usize, + ), + }, + RGBA8888 => ColorBuffer { + buf32: core::slice::from_raw_parts_mut( + bus_addr as *mut u32, + (size / 4) as usize, + ), + }, + } + } + } + + #[inline] + fn read16(&self, index: u32) -> u16 { + unsafe { self.buf16[index as usize] } + } + + #[inline] + fn read32(&self, index: u32) -> u32 { + unsafe { self.buf32[index as usize] } + } + + #[inline] + fn write16(&mut self, index: u32, pixel: u16) { + unsafe { self.buf16[index as usize] = pixel } + } + + #[inline] + fn write32(&mut self, index: u32, pixel: u32) { + unsafe { self.buf32[index as usize] = pixel } + } +} + +/// Frambuffer structure +pub struct Framebuffer { + pub fb_info: FramebufferInfo, + pub color_format: ColorFormat, + buf: ColorBuffer, +} + +impl fmt::Debug for Framebuffer { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut f = f.debug_struct("Framebuffer"); + f.field("fb_info", &self.fb_info); + f.field("color_format", &self.color_format); + f.field("base_addr", unsafe { &self.buf.base_addr }); + f.finish() + } +} + +impl Framebuffer { + fn new(width: u32, height: u32, depth: u32) -> Result { + assert_has_not_been_called!("Framebuffer::new must be called only once"); + + let (width, height) = if width == 0 || height == 0 { + mailbox::framebuffer_get_physical_size()? + } else { + (width, height) + }; + let depth = if depth == 0 { + mailbox::framebuffer_get_depth()? + } else { + depth + }; + + let info = mailbox::framebuffer_alloc(width, height, depth)?; + let color_format = match info.depth { + 16 => BGR565, + 32 => RGBA8888, + _ => Err(format!("unsupported color depth {}", info.depth))?, + }; + + if info.bus_addr == 0 || info.screen_size == 0 { + Err(format!("mailbox call returned an invalid address/size"))?; + } + if info.pitch == 0 || info.pitch != info.xres * info.depth / 8 { + Err(format!( + "mailbox call returned an invalid pitch value {}", + info.pitch + ))?; + } + + let paddr = info.bus_addr & !0xC0000000; + Ok(Framebuffer { + buf: ColorBuffer::new(color_format, paddr, info.screen_size), + color_format, + fb_info: info, + }) + } + + #[inline] + pub fn base_addr(&self) -> u32 { + unsafe { self.buf.base_addr } + } + + #[inline] + pub fn read(&self, x: u32, y: u32) -> u32 { + match self.color_format { + BGR565 => self.buf.read16(y * self.fb_info.xres + x) as u32, + RGBA8888 => self.buf.read32(y * self.fb_info.xres + x), + } + } + + #[inline] + pub fn write(&mut self, x: u32, y: u32, pixel: u32) { + match self.color_format { + BGR565 => self.buf.write16(y * self.fb_info.xres + x, pixel as u16), + RGBA8888 => self.buf.write32(y * self.fb_info.xres + x, pixel), + } + } +} + +lazy_static! { + pub static ref FRAME_BUFFER: Mutex> = Mutex::new(None); +} + +/// Initialize framebuffer +pub fn init() { + match Framebuffer::new(0, 0, 0) { + Ok(fb) => { + let info = fb.fb_info; + info!("framebuffer: init end\n{:#x?}", fb); + *FRAME_BUFFER.lock() = Some(fb); + } + Err(err) => error!("framebuffer init failed: {}", err), + } +} diff --git a/kernel/src/arch/aarch64/board/raspi3/mailbox.rs b/kernel/src/arch/aarch64/board/raspi3/mailbox.rs index 83e1557..6efb670 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mailbox.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mailbox.rs @@ -2,8 +2,10 @@ //! //! (ref: https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface) +use super::fb::FramebufferInfo; use bcm2837::mailbox::{Mailbox, MailboxChannel}; use lazy_static::lazy_static; +use alloc::string::String; use core::mem; use spin::Mutex; use aarch64::barrier; @@ -16,6 +18,12 @@ lazy_static! { pub struct PropertyMailboxError(u32); pub type PropertyMailboxResult = Result; +impl From for String { + fn from(error: PropertyMailboxError) -> Self { + format!("{:x?}", error) + } +} + /// Buffer request/response code. /// Copied from `linux/include/soc/bcm2835/raspberrypi-firmware.h` #[repr(u32)] @@ -167,11 +175,11 @@ struct Align16(PropertyMailboxRequest); /// Pack a sequence of concatenated tags into a request, and send the address /// to the mailbox. -/// Returns PropertyMailboxResult. +/// Returns `PropertyMailboxResult`. macro_rules! send_request { ($tags: ident) => {{ let req = Align16(PropertyMailboxRequest { - buf_size: mem::size_of_val(&$tags) as u32, + buf_size: mem::size_of_val(&$tags) as u32 + 12, req_resp_code: RPI_FIRMWARE_STATUS_REQUEST, buf: $tags, end_tag: RPI_FIRMWARE_PROPERTY_END, @@ -179,8 +187,9 @@ macro_rules! send_request { unsafe { barrier::wmb() } { + let addr = &req as *const _ as u32; let mut mbox = MAILBOX.lock(); - mbox.write(MailboxChannel::Property, &req as *const _ as u32); + mbox.write(MailboxChannel::Property, addr); mbox.read(MailboxChannel::Property); } unsafe { barrier::rmb() } @@ -193,7 +202,7 @@ macro_rules! send_request { } /// Send a tag to mailbox. Will call `send_request!`. -/// Returns PropertyMailboxResult. +/// Returns `PropertyMailboxResult`. macro_rules! send_one_tag { ($id: expr, [$($arg: expr),*]) => {{ let buf = [$($arg),*]; @@ -264,3 +273,79 @@ pub fn framebuffer_set_virtual_offset(xoffset: u32, yoffset: u32) -> PropertyMai )?; Ok((ret[0], ret[1])) } + +/// Allocate framebuffer on GPU and try to set width/height/depth. +/// Returns `FramebufferInfo`. +pub fn framebuffer_alloc(width: u32, height: u32, depth: u32) -> PropertyMailboxResult { + #[repr(C, packed)] + #[derive(Debug)] + struct FramebufferAllocTag { + set_physical_size: PropertyMailboxTag<[u32; 2]>, + set_virtual_size: PropertyMailboxTag<[u32; 2]>, + set_depth: PropertyMailboxTag<[u32; 1]>, + set_virtual_offset: PropertyMailboxTag<[u32; 2]>, + allocate: PropertyMailboxTag<[u32; 2]>, + get_pitch: PropertyMailboxTag<[u32; 1]>, + } + + let tags = FramebufferAllocTag { + // Set physical (buffer) width/height. Returns `(width, height)` in pixel. + set_physical_size: PropertyMailboxTag { + id: RPI_FIRMWARE_FRAMEBUFFER_SET_PHYSICAL_WIDTH_HEIGHT, + buf_size: 8, + req_resp_size: 0, + buf: [width, height], + }, + // Set virtual (buffer) width/height. Returns `(width, height)` in pixel. + set_virtual_size: PropertyMailboxTag { + id: RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_WIDTH_HEIGHT, + buf_size: 8, + req_resp_size: 0, + buf: [width, height], + }, + // Set depth; Returns bits per pixel. + set_depth: PropertyMailboxTag { + id: RPI_FIRMWARE_FRAMEBUFFER_SET_DEPTH, + buf_size: 4, + req_resp_size: 0, + buf: [depth], + }, + // Set virtual offset. Returns `(X, Y)` in pixel. + set_virtual_offset: PropertyMailboxTag { + id: RPI_FIRMWARE_FRAMEBUFFER_SET_VIRTUAL_OFFSET, + buf_size: 8, + req_resp_size: 0, + buf: [0, 0], + }, + // Allocate buffer. Returns `(base_address, size)` in bytes. + allocate: PropertyMailboxTag { + id: RPI_FIRMWARE_FRAMEBUFFER_ALLOCATE, + buf_size: 8, + req_resp_size: 0, + buf: [0x1000, 0], + }, + // Get pitch. Return bytes per line. + get_pitch: PropertyMailboxTag { + id: RPI_FIRMWARE_FRAMEBUFFER_GET_PITCH, + buf_size: 4, + req_resp_size: 0, + buf: [0], + }, + }; + + let ret = send_request!(tags)?; + Ok(FramebufferInfo { + xres: ret.set_physical_size.buf[0], + yres: ret.set_physical_size.buf[1], + xres_virtual: ret.set_virtual_size.buf[0], + yres_virtual: ret.set_virtual_size.buf[1], + xoffset: ret.set_virtual_offset.buf[0], + yoffset: ret.set_virtual_offset.buf[1], + + depth: ret.set_depth.buf[0], + pitch: ret.get_pitch.buf[0], + + bus_addr: ret.allocate.buf[0], + screen_size: ret.allocate.buf[1], + }) +} diff --git a/kernel/src/arch/aarch64/board/raspi3/mod.rs b/kernel/src/arch/aarch64/board/raspi3/mod.rs index f62aad2..2bbee12 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mod.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mod.rs @@ -2,6 +2,7 @@ use once::*; +pub mod fb; pub mod irq; pub mod timer; pub mod serial; @@ -10,16 +11,17 @@ pub mod mailbox; pub const IO_REMAP_BASE: usize = bcm2837::IO_BASE; pub const IO_REMAP_END: usize = 0x40001000; -/// Some initializations must be done before other initializations. -pub fn init_early() { +/// Initialize serial port before other initializations. +pub fn init_serial_early() { assert_has_not_been_called!("board::init must be called only once"); - serial::SERIAL_PORT.lock().init(); + serial::init(); println!("Hello Raspberry Pi!"); } /// Initialize raspi3 drivers pub fn init_driver() { + fb::init(); timer::init(); } diff --git a/kernel/src/arch/aarch64/board/raspi3/serial.rs b/kernel/src/arch/aarch64/board/raspi3/serial.rs index 74ed5dd..d74432a 100644 --- a/kernel/src/arch/aarch64/board/raspi3/serial.rs +++ b/kernel/src/arch/aarch64/board/raspi3/serial.rs @@ -2,6 +2,7 @@ use bcm2837::mini_uart::{MiniUart, MiniUartInterruptId}; use lazy_static::lazy_static; use core::fmt; use spin::Mutex; +use once::*; /// Struct to get a global SerialPort interface pub struct SerialPort { @@ -22,6 +23,8 @@ impl SerialPort { /// Init a newly created SerialPort, can only be called once. pub fn init(&mut self) { + assert_has_not_been_called!("SerialPort::init must be called only once"); + self.mu.init(); super::irq::register_irq(super::irq::Interrupt::Aux, handle_serial_irq); } @@ -78,6 +81,11 @@ fn handle_serial_irq() { } } -lazy_static!{ +lazy_static! { pub static ref SERIAL_PORT: Mutex = Mutex::new(SerialPort::new()); } + + +pub fn init() { + SERIAL_PORT.lock().init(); +} diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index 3edf8cb..ecfc34d 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -18,15 +18,13 @@ global_asm!(include_str!("boot/boot.S")); #[no_mangle] // don't mangle the name of this function pub extern "C" fn rust_main() -> ! { memory::init_mmu_early(); // Enable mmu and paging + board::init_serial_early(); crate::logging::init(); - - board::init_early(); - println!("{}", LOGO); - interrupt::init(); memory::init(); driver::init(); + println!("{}", LOGO); crate::process::init(); diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 6513ac9..f6d938e 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -1,6 +1,7 @@ #![feature(lang_items)] #![feature(alloc)] #![feature(naked_functions)] +#![feature(untagged_unions)] #![feature(asm)] #![feature(optin_builtin_traits)] #![feature(panic_info_message)] @@ -8,6 +9,7 @@ #![no_std] // just keep it ... +#[macro_use] extern crate alloc; pub use crate::process::{processor, new_kernel_context}; From 5987c2068b1422b95611a2c83d1a17010976d348 Mon Sep 17 00:00:00 2001 From: equation314 Date: Sun, 16 Dec 2018 22:26:04 +0800 Subject: [PATCH 04/14] aarch64/fb: remap framebuffer base address --- crate/memory/src/memory_set.rs | 14 +++-- crate/memory/src/paging/mod.rs | 14 ++++- kernel/Cargo.lock | 2 +- kernel/src/arch/aarch64/board/raspi3/fb.rs | 4 +- kernel/src/arch/aarch64/memory.rs | 64 +++++++++++++++------- kernel/src/arch/aarch64/paging.rs | 13 ++--- 6 files changed, 72 insertions(+), 39 deletions(-) diff --git a/crate/memory/src/memory_set.rs b/crate/memory/src/memory_set.rs index 3c631eb..7c5c1c8 100644 --- a/crate/memory/src/memory_set.rs +++ b/crate/memory/src/memory_set.rs @@ -222,8 +222,8 @@ pub struct MemoryAttr { user: bool, readonly: bool, execute: bool, - mmio: bool, hide: bool, + mmio: usize, } impl MemoryAttr { @@ -251,8 +251,12 @@ impl MemoryAttr { self.execute = true; self } - pub fn mmio(mut self) -> Self { - self.mmio = true; + /* + ** @brief set the MMIO type + ** @retval MemoryAttr the memory attribute itself + */ + pub fn mmio(mut self, value: usize) -> Self { + self.mmio = value; self } /* @@ -273,9 +277,9 @@ impl MemoryAttr { if self.user { entry.set_user(true); } if self.readonly { entry.set_writable(false); } if self.execute { entry.set_execute(true); } - if self.mmio { entry.set_mmio(true); } + if self.mmio != 0 { entry.set_mmio(self.mmio); } if self.hide { entry.set_present(false); } - if self.user || self.readonly || self.execute || self.mmio || self.hide { entry.update(); } + if self.user || self.readonly || self.execute || self.mmio != 0 || self.hide { entry.update(); } } } diff --git a/crate/memory/src/paging/mod.rs b/crate/memory/src/paging/mod.rs index 6bbe9b2..0fa7447 100644 --- a/crate/memory/src/paging/mod.rs +++ b/crate/memory/src/paging/mod.rs @@ -195,6 +195,16 @@ pub trait Entry { ** @retval none */ fn set_execute(&mut self, value: bool); - fn mmio(&self) -> bool; - fn set_mmio(&mut self, value: bool); + /* + ** @brief get MMIO type + ** (e.g. aarch64 can have normal/device/normal_non_cacheable memory) + ** @retval usize + */ + fn mmio(&self) -> usize; + /* + ** @brief set MMIO type + ** @param value: usize the value distinguished memory type + ** @retval none + */ + fn set_mmio(&mut self, value: usize); } diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index ecc04cb..a39024e 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -1,7 +1,7 @@ [[package]] name = "aarch64" version = "2.2.2" -source = "git+https://github.com/equation314/aarch64#06b2f5507dd5393e40c1506cd4414ef36864afc6" +source = "git+https://github.com/equation314/aarch64#95e875933967067908bf1da66bf74db24d450062" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/src/arch/aarch64/board/raspi3/fb.rs b/kernel/src/arch/aarch64/board/raspi3/fb.rs index 00ff2da..ef3b187 100644 --- a/kernel/src/arch/aarch64/board/raspi3/fb.rs +++ b/kernel/src/arch/aarch64/board/raspi3/fb.rs @@ -143,9 +143,11 @@ impl Framebuffer { ))?; } + use crate::arch::memory; let paddr = info.bus_addr & !0xC0000000; + let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb") as u32; Ok(Framebuffer { - buf: ColorBuffer::new(color_format, paddr, info.screen_size), + buf: ColorBuffer::new(color_format, vaddr, info.screen_size), color_format, fb_info: info, }) diff --git a/kernel/src/arch/aarch64/memory.rs b/kernel/src/arch/aarch64/memory.rs index 6a5996f..00ff312 100644 --- a/kernel/src/arch/aarch64/memory.rs +++ b/kernel/src/arch/aarch64/memory.rs @@ -1,11 +1,13 @@ //! Memory initialization for aarch64. +use crate::memory::{init_heap, MemoryArea, MemoryAttr, MemorySet, FRAME_ALLOCATOR}; +use aarch64::paging::{memory_attribute::*, PhysFrame as Frame}; +use aarch64::{addr::*, barrier, regs::*}; +use atags::atags::Atags; +use lazy_static::lazy_static; use log::*; +use spin::Mutex; use ucore_memory::PAGE_SIZE; -use atags::atags::Atags; -use aarch64::{barrier, regs::*, addr::*}; -use aarch64::paging::{PhysFrame as Frame, memory_attribute::*}; -use crate::memory::{FRAME_ALLOCATOR, init_heap, MemoryArea, MemoryAttr, MemorySet}; /// Memory initialization. pub fn init() { @@ -62,19 +64,19 @@ pub fn init_mmu_early() { // Switch the MMU on. // // First, force all previous changes to be seen before the MMU is enabled. - unsafe { barrier::isb(barrier::SY); } + unsafe { barrier::isb(barrier::SY) } // Enable the MMU and turn on data and instruction caching. SCTLR_EL1.modify(SCTLR_EL1::M::Enable + SCTLR_EL1::C::Cacheable + SCTLR_EL1::I::Cacheable); // Force MMU init to complete before next instruction - unsafe { barrier::isb(barrier::SY); } + unsafe { barrier::isb(barrier::SY) } } fn init_frame_allocator() { + use crate::consts::MEMORY_OFFSET; use bit_allocator::BitAlloc; use core::ops::Range; - use crate::consts::MEMORY_OFFSET; let (start, end) = memory_map().expect("failed to find memory map"); let mut ba = FRAME_ALLOCATOR.lock(); @@ -82,14 +84,14 @@ fn init_frame_allocator() { info!("FrameAllocator init end"); /* - * @param: - * start: start address - * end: end address - * @brief: - * transform the memory address to the page number - * @retval: - * the page number range from start address to end address - */ + * @param: + * start: start address + * end: end address + * @brief: + * transform the memory address to the page number + * @retval: + * the page number range from start address to end address + */ fn to_range(start: usize, end: usize) -> Range { let page_start = (start - MEMORY_OFFSET) / PAGE_SIZE; let page_end = (end - MEMORY_OFFSET - 1) / PAGE_SIZE + 1; @@ -97,9 +99,13 @@ fn init_frame_allocator() { } } +lazy_static! { + pub static ref KERNEL_MEMORY_SET: Mutex = Mutex::new(MemorySet::new_bare()); +} + /// remap kernel page table after all initialization. fn remap_the_kernel() { - let mut ms = MemorySet::new_bare(); + let mut ms = KERNEL_MEMORY_SET.lock(); ms.push(MemoryArea::new_identity(0, bootstacktop as usize, MemoryAttr::default(), "kstack")); ms.push(MemoryArea::new_identity(stext as usize, etext as usize, MemoryAttr::default().execute().readonly(), "text")); ms.push(MemoryArea::new_identity(sdata as usize, edata as usize, MemoryAttr::default(), "data")); @@ -107,13 +113,29 @@ fn remap_the_kernel() { ms.push(MemoryArea::new_identity(sbss as usize, ebss as usize, MemoryAttr::default(), "bss")); use super::board::{IO_REMAP_BASE, IO_REMAP_END}; - ms.push(MemoryArea::new_identity(IO_REMAP_BASE, IO_REMAP_END, MemoryAttr::default().mmio(), "io_remap")); - - unsafe { ms.get_page_table_mut().activate_as_kernel(); } - ::core::mem::forget(ms); + ms.push(MemoryArea::new_identity( + IO_REMAP_BASE, + IO_REMAP_END, + MemoryAttr::default().mmio(MairDevice::attr_value().value as usize), + "io_remap", + )); + + unsafe { ms.get_page_table_mut().activate_as_kernel() } info!("kernel remap end"); } +pub fn ioremap(start: usize, len: usize, name: &'static str) -> usize { + let mut ms = KERNEL_MEMORY_SET.lock(); + let area = MemoryArea::new_identity( + start, + start + len, + MemoryAttr::default().mmio(MairNormalNonCacheable::attr_value().value as usize), + name, + ); + ms.push(area); + start +} + /// Returns the (start address, end address) of the available memory on this /// system if it can be determined. If it cannot, `None` is returned. /// @@ -131,7 +153,7 @@ fn memory_map() -> Option<(usize, usize)> { None } -extern { +extern "C" { fn bootstacktop(); fn stext(); fn etext(); diff --git a/kernel/src/arch/aarch64/paging.rs b/kernel/src/arch/aarch64/paging.rs index fa0e074..cfe1770 100644 --- a/kernel/src/arch/aarch64/paging.rs +++ b/kernel/src/arch/aarch64/paging.rs @@ -162,15 +162,10 @@ impl Entry for PageEntry { self.as_flags().set(EF::PXN, !value) } } - fn mmio(&self) -> bool { - self.0.attr().value == MairDevice::attr_value().value - } - fn set_mmio(&mut self, value: bool) { - if value { - self.0.modify_attr(MairDevice::attr_value()) - } else { - self.0.modify_attr(MairNormal::attr_value()) - } + fn mmio(&self) -> usize { self.0.attr().value as usize } + fn set_mmio(&mut self, value: usize) { + use aarch64::paging::{PageTableAttribute, MEMORY_ATTR_MASK}; + self.0.modify_attr(PageTableAttribute::new(MEMORY_ATTR_MASK, 0, value as u64)) } } From 48cf25716f257794ef097daa7214788fc77cd3fa Mon Sep 17 00:00:00 2001 From: equation314 Date: Mon, 17 Dec 2018 01:33:42 +0800 Subject: [PATCH 05/14] aarch64/fb: flush data cache around mailbox accesses can run on real raspi3 --- kernel/Cargo.lock | 2 +- kernel/src/arch/aarch64/board/raspi3/mailbox.rs | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index a39024e..47635c9 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -1,7 +1,7 @@ [[package]] name = "aarch64" version = "2.2.2" -source = "git+https://github.com/equation314/aarch64#95e875933967067908bf1da66bf74db24d450062" +source = "git+https://github.com/equation314/aarch64#9770a21c00f5d74c32ed044ca200f0459caca828" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/src/arch/aarch64/board/raspi3/mailbox.rs b/kernel/src/arch/aarch64/board/raspi3/mailbox.rs index 6efb670..1bee860 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mailbox.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mailbox.rs @@ -8,7 +8,7 @@ use lazy_static::lazy_static; use alloc::string::String; use core::mem; use spin::Mutex; -use aarch64::barrier; +use aarch64::{asm, barrier}; lazy_static! { static ref MAILBOX: Mutex = Mutex::new(Mailbox::new()); @@ -185,14 +185,16 @@ macro_rules! send_request { end_tag: RPI_FIRMWARE_PROPERTY_END, }); - unsafe { barrier::wmb() } + let start = &req as *const _ as u32; + let end = start + req.0.buf_size; { - let addr = &req as *const _ as u32; + // flush data cache around mailbox accesses let mut mbox = MAILBOX.lock(); - mbox.write(MailboxChannel::Property, addr); + asm::flush_dcache_range(start as usize, end as usize); + mbox.write(MailboxChannel::Property, start); mbox.read(MailboxChannel::Property); + asm::flush_dcache_range(start as usize, end as usize); } - unsafe { barrier::rmb() } match req.0.req_resp_code { RPI_FIRMWARE_STATUS_SUCCESS => Ok(req.0.buf), From b5cc79d1b299de0908a7e6343271b07d64f888ca Mon Sep 17 00:00:00 2001 From: equation314 Date: Mon, 17 Dec 2018 14:28:51 +0800 Subject: [PATCH 06/14] modify mmio() & set_mmio() in PageEntry --- crate/memory/src/memory_set.rs | 4 +- crate/memory/src/paging/mod.rs | 8 ++-- kernel/Cargo.lock | 2 +- kernel/src/arch/aarch64/board/raspi3/fb.rs | 6 ++- .../src/arch/aarch64/board/raspi3/mailbox.rs | 2 +- kernel/src/arch/aarch64/memory.rs | 9 +++-- kernel/src/arch/aarch64/paging.rs | 38 +++++++++++++++---- kernel/src/arch/riscv32/paging.rs | 6 +-- kernel/src/arch/x86_64/paging.rs | 4 +- 9 files changed, 53 insertions(+), 26 deletions(-) diff --git a/crate/memory/src/memory_set.rs b/crate/memory/src/memory_set.rs index 7c5c1c8..7886509 100644 --- a/crate/memory/src/memory_set.rs +++ b/crate/memory/src/memory_set.rs @@ -223,7 +223,7 @@ pub struct MemoryAttr { readonly: bool, execute: bool, hide: bool, - mmio: usize, + mmio: u8, } impl MemoryAttr { @@ -255,7 +255,7 @@ impl MemoryAttr { ** @brief set the MMIO type ** @retval MemoryAttr the memory attribute itself */ - pub fn mmio(mut self, value: usize) -> Self { + pub fn mmio(mut self, value: u8) -> Self { self.mmio = value; self } diff --git a/crate/memory/src/paging/mod.rs b/crate/memory/src/paging/mod.rs index 0fa7447..af8b0ae 100644 --- a/crate/memory/src/paging/mod.rs +++ b/crate/memory/src/paging/mod.rs @@ -198,13 +198,13 @@ pub trait Entry { /* ** @brief get MMIO type ** (e.g. aarch64 can have normal/device/normal_non_cacheable memory) - ** @retval usize + ** @retval u8 the MMIO type */ - fn mmio(&self) -> usize; + fn mmio(&self) -> u8; /* ** @brief set MMIO type - ** @param value: usize the value distinguished memory type + ** @param value: u8 the MMIO type ** @retval none */ - fn set_mmio(&mut self, value: usize); + fn set_mmio(&mut self, value: u8); } diff --git a/kernel/Cargo.lock b/kernel/Cargo.lock index 47635c9..1228664 100644 --- a/kernel/Cargo.lock +++ b/kernel/Cargo.lock @@ -1,7 +1,7 @@ [[package]] name = "aarch64" version = "2.2.2" -source = "git+https://github.com/equation314/aarch64#9770a21c00f5d74c32ed044ca200f0459caca828" +source = "git+https://github.com/equation314/aarch64#b6a0f4a3be6f74927c88305a6af5ad2be079bccd" dependencies = [ "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/kernel/src/arch/aarch64/board/raspi3/fb.rs b/kernel/src/arch/aarch64/board/raspi3/fb.rs index ef3b187..5d6d8f3 100644 --- a/kernel/src/arch/aarch64/board/raspi3/fb.rs +++ b/kernel/src/arch/aarch64/board/raspi3/fb.rs @@ -48,7 +48,7 @@ use self::ColorFormat::*; #[repr(C)] union ColorBuffer { - base_addr: u32, + base_addr: usize, buf16: &'static mut [u16], buf32: &'static mut [u32], } @@ -154,10 +154,11 @@ impl Framebuffer { } #[inline] - pub fn base_addr(&self) -> u32 { + pub fn base_addr(&self) -> usize { unsafe { self.buf.base_addr } } + /// Read pixel at `(x, y)`. #[inline] pub fn read(&self, x: u32, y: u32) -> u32 { match self.color_format { @@ -166,6 +167,7 @@ impl Framebuffer { } } + /// Write pixel at `(x, y)`. #[inline] pub fn write(&mut self, x: u32, y: u32, pixel: u32) { match self.color_format { diff --git a/kernel/src/arch/aarch64/board/raspi3/mailbox.rs b/kernel/src/arch/aarch64/board/raspi3/mailbox.rs index 1bee860..9b63027 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mailbox.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mailbox.rs @@ -8,7 +8,7 @@ use lazy_static::lazy_static; use alloc::string::String; use core::mem; use spin::Mutex; -use aarch64::{asm, barrier}; +use aarch64::asm; lazy_static! { static ref MAILBOX: Mutex = Mutex::new(Mailbox::new()); diff --git a/kernel/src/arch/aarch64/memory.rs b/kernel/src/arch/aarch64/memory.rs index 00ff312..60a3334 100644 --- a/kernel/src/arch/aarch64/memory.rs +++ b/kernel/src/arch/aarch64/memory.rs @@ -1,6 +1,7 @@ //! Memory initialization for aarch64. use crate::memory::{init_heap, MemoryArea, MemoryAttr, MemorySet, FRAME_ALLOCATOR}; +use super::paging::MMIOType; use aarch64::paging::{memory_attribute::*, PhysFrame as Frame}; use aarch64::{addr::*, barrier, regs::*}; use atags::atags::Atags; @@ -32,8 +33,8 @@ pub fn init_mmu_early() { // device. MAIR_EL1.write( - MAIR_EL1::Attr0.val(MairDevice::config_value()) + - MAIR_EL1::Attr1.val(MairNormal::config_value()) + + MAIR_EL1::Attr0.val(MairNormal::config_value()) + + MAIR_EL1::Attr1.val(MairDevice::config_value()) + MAIR_EL1::Attr2.val(MairNormalNonCacheable::config_value()), ); @@ -116,7 +117,7 @@ fn remap_the_kernel() { ms.push(MemoryArea::new_identity( IO_REMAP_BASE, IO_REMAP_END, - MemoryAttr::default().mmio(MairDevice::attr_value().value as usize), + MemoryAttr::default().mmio(MMIOType::Device as u8), "io_remap", )); @@ -129,7 +130,7 @@ pub fn ioremap(start: usize, len: usize, name: &'static str) -> usize { let area = MemoryArea::new_identity( start, start + len, - MemoryAttr::default().mmio(MairNormalNonCacheable::attr_value().value as usize), + MemoryAttr::default().mmio(MMIOType::NormalNonCacheable as u8), name, ); ms.push(area); diff --git a/kernel/src/arch/aarch64/paging.rs b/kernel/src/arch/aarch64/paging.rs index cfe1770..453f7c8 100644 --- a/kernel/src/arch/aarch64/paging.rs +++ b/kernel/src/arch/aarch64/paging.rs @@ -22,7 +22,7 @@ pub fn setup_temp_page_table(frame_lvl4: Frame, frame_lvl3: Frame, frame_lvl2: F p2.zero(); let (start_addr, end_addr) = (0, 0x40000000); - let block_flags = EF::VALID | EF::AF | EF::WRITE | EF::XN; + let block_flags = EF::VALID | EF::AF | EF::WRITE | EF::UXN; for page in Page::::range_of(start_addr, end_addr) { let paddr = PhysAddr::new(page.start_address().as_u64()); @@ -106,6 +106,14 @@ impl ActivePageTable { } } +#[repr(u8)] +pub enum MMIOType { + Normal = 0, + Device = 1, + NormalNonCacheable = 2, + Unsupported = 3, +} + impl Entry for PageEntry { fn update(&mut self) { let addr = VirtAddr::new_unchecked((self as *const _ as u64) << 9); @@ -150,22 +158,38 @@ impl Entry for PageEntry { } fn execute(&self) -> bool { if self.user() { - !self.0.flags().contains(EF::XN) + !self.0.flags().contains(EF::UXN) } else { !self.0.flags().contains(EF::PXN) } } fn set_execute(&mut self, value: bool) { if self.user() { - self.as_flags().set(EF::XN, !value) + self.as_flags().set(EF::UXN, !value) } else { self.as_flags().set(EF::PXN, !value) } } - fn mmio(&self) -> usize { self.0.attr().value as usize } - fn set_mmio(&mut self, value: usize) { - use aarch64::paging::{PageTableAttribute, MEMORY_ATTR_MASK}; - self.0.modify_attr(PageTableAttribute::new(MEMORY_ATTR_MASK, 0, value as u64)) + fn mmio(&self) -> u8 { + let value = self.0.attr().value; + if value == MairNormal::attr_value().value { + 0 + } else if value == MairDevice::attr_value().value { + 1 + } else if value == MairNormalNonCacheable::attr_value().value { + 2 + } else { + 3 + } + } + fn set_mmio(&mut self, value: u8) { + let attr = match value { + 0 => MairNormal::attr_value(), + 1 => MairDevice::attr_value(), + 2 => MairNormalNonCacheable::attr_value(), + _ => return, + }; + self.0.modify_attr(attr); } } diff --git a/kernel/src/arch/riscv32/paging.rs b/kernel/src/arch/riscv32/paging.rs index 6cce3f3..631a9f8 100644 --- a/kernel/src/arch/riscv32/paging.rs +++ b/kernel/src/arch/riscv32/paging.rs @@ -26,7 +26,7 @@ pub fn setup_page_table(frame: Frame) { // Set kernel identity map // 0x10000000 ~ 1K area p2.map_identity(0x40, EF::VALID | EF::READABLE | EF::WRITABLE); - // 0x80000000 ~ 12M area + // 0x80000000 ~ 12M area p2.map_identity(KERNEL_P2_INDEX, EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE); p2.map_identity(KERNEL_P2_INDEX + 1, EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE); p2.map_identity(KERNEL_P2_INDEX + 2, EF::VALID | EF::READABLE | EF::WRITABLE | EF::EXECUTABLE); @@ -196,8 +196,8 @@ impl Entry for PageEntry { fn set_user(&mut self, value: bool) { self.as_flags().set(EF::USER, value); } fn execute(&self) -> bool { self.0.flags().contains(EF::EXECUTABLE) } fn set_execute(&mut self, value: bool) { self.as_flags().set(EF::EXECUTABLE, value); } - fn mmio(&self) -> bool { unimplemented!() } - fn set_mmio(&mut self, value: bool) { unimplemented!() } + fn mmio(&self) -> u8 { 0 } + fn set_mmio(&mut self, _value: u8) { } } impl PageEntry { diff --git a/kernel/src/arch/x86_64/paging.rs b/kernel/src/arch/x86_64/paging.rs index bdf9a4c..e269935 100644 --- a/kernel/src/arch/x86_64/paging.rs +++ b/kernel/src/arch/x86_64/paging.rs @@ -142,8 +142,8 @@ impl Entry for PageEntry { } fn execute(&self) -> bool { !self.0.flags().contains(EF::NO_EXECUTE) } fn set_execute(&mut self, value: bool) { self.as_flags().set(EF::NO_EXECUTE, !value); } - fn mmio(&self) -> bool { unimplemented!() } - fn set_mmio(&mut self, value: bool) { unimplemented!() } + fn mmio(&self) -> u8 { 0 } + fn set_mmio(&mut self, _value: u8) { } } fn get_entry_ptr(addr: usize, level: u8) -> *mut PageEntry { From b47c4758bf3f0e7c97fbe60bdf64e0d61b585a5d Mon Sep 17 00:00:00 2001 From: equation314 Date: Tue, 18 Dec 2018 00:16:56 +0800 Subject: [PATCH 07/14] aarch64/fb: add basic console driver --- kernel/src/arch/aarch64/board/raspi3/fb.rs | 11 +- .../src/arch/aarch64/board/raspi3/serial.rs | 2 +- kernel/src/arch/aarch64/driver/console.rs | 198 ++++++++++++++++++ kernel/src/arch/aarch64/driver/mod.rs | 8 +- kernel/src/arch/aarch64/io.rs | 14 +- 5 files changed, 224 insertions(+), 9 deletions(-) create mode 100644 kernel/src/arch/aarch64/driver/console.rs diff --git a/kernel/src/arch/aarch64/board/raspi3/fb.rs b/kernel/src/arch/aarch64/board/raspi3/fb.rs index 5d6d8f3..19f9887 100644 --- a/kernel/src/arch/aarch64/board/raspi3/fb.rs +++ b/kernel/src/arch/aarch64/board/raspi3/fb.rs @@ -175,6 +175,16 @@ impl Framebuffer { RGBA8888 => self.buf.write32(y * self.fb_info.xres + x, pixel), } } + + /// Clean screen + pub fn clear(&mut self) { + let mut start = self.base_addr(); + let end = start + self.fb_info.screen_size as usize; + while start < end { + unsafe { *(start as *mut usize) = 0 } + start += core::mem::size_of::(); + } + } } lazy_static! { @@ -185,7 +195,6 @@ lazy_static! { pub fn init() { match Framebuffer::new(0, 0, 0) { Ok(fb) => { - let info = fb.fb_info; info!("framebuffer: init end\n{:#x?}", fb); *FRAME_BUFFER.lock() = Some(fb); } diff --git a/kernel/src/arch/aarch64/board/raspi3/serial.rs b/kernel/src/arch/aarch64/board/raspi3/serial.rs index d74432a..abb4ff6 100644 --- a/kernel/src/arch/aarch64/board/raspi3/serial.rs +++ b/kernel/src/arch/aarch64/board/raspi3/serial.rs @@ -22,7 +22,7 @@ impl SerialPort { } /// Init a newly created SerialPort, can only be called once. - pub fn init(&mut self) { + fn init(&mut self) { assert_has_not_been_called!("SerialPort::init must be called only once"); self.mu.init(); diff --git a/kernel/src/arch/aarch64/driver/console.rs b/kernel/src/arch/aarch64/driver/console.rs new file mode 100644 index 0000000..f0b01e5 --- /dev/null +++ b/kernel/src/arch/aarch64/driver/console.rs @@ -0,0 +1,198 @@ +//! Framebuffer console display driver for ARM64 + +use super::board::fb::{FramebufferInfo, FRAME_BUFFER}; +use alloc::vec::Vec; +use core::fmt::{self, Write}; +use lazy_static::lazy_static; +use spin::Mutex; + +#[derive(Debug, Clone, Copy)] +struct Color(u8); + +#[derive(Debug, Clone, Copy)] +#[repr(C)] +pub struct ConsoleChar { + ascii_char: u8, + color: Color, +} + +impl Default for ConsoleChar { + fn default() -> Self { + ConsoleChar { + ascii_char: b' ', + color: Color(0), + } + } +} + +const CHAR_WIDTH: u16 = 8; +const CHAR_HEIGHT: u16 = 16; + +/// Character buffer +struct ConsoleBuffer { + num_row: u16, + num_col: u16, + buf: Vec>, +} + +impl ConsoleBuffer { + fn new(num_row: u16, num_col: u16) -> ConsoleBuffer { + ConsoleBuffer { + num_row, + num_col, + buf: vec![vec![ConsoleChar::default(); num_col as usize]; num_row as usize], + } + } + + /// Read one character at `(row, col)`. + fn read(&self, row: u16, col: u16) -> ConsoleChar { + self.buf[row as usize][col as usize] + } + + /// Write one character at `(row, col)`. + /// TODO: font & color + fn write(&mut self, row: u16, col: u16, ch: ConsoleChar) { + self.buf[row as usize][col as usize] = ch; + + let off_x = col * CHAR_WIDTH; + let off_y = row * CHAR_HEIGHT; + if let Some(fb) = FRAME_BUFFER.lock().as_mut() { + for y in 0..CHAR_HEIGHT { + for x in 0..CHAR_WIDTH { + let pixel = if ch.color.0 == 0 { 0 } else { !0 }; + fb.write((off_x + x) as u32, (off_y + y) as u32, pixel); + } + } + } + } + + /// Delete one character at `(row, col)`. + fn delete(&mut self, row: u16, col: u16) { + self.write(row, col, ConsoleChar::default()); + } + + /// Insert one blank line at the bottom and remove the top line. + /// TODO: improve performance + fn new_line(&mut self) { + for i in 1..self.num_row { + for j in 0..self.num_col { + self.write(i - 1, j, self.read(i, j)); + } + } + for j in 0..self.num_col { + self.write(self.num_row - 1, j, ConsoleChar::default()); + } + } + + /// Clear the entire buffer and screen. + fn clear(&mut self) { + for i in 0..self.num_row as usize { + for j in 0..self.num_col as usize { + self.buf[i][j] = ConsoleChar::default() + } + } + if let Some(fb) = FRAME_BUFFER.lock().as_mut() { + fb.clear(); + } + } +} + +/// Console structure +pub struct Console { + /// current color + color: Color, + /// cursor row + row: u16, + /// cursor column + col: u16, + /// number of rows + num_row: u16, + /// number of columns + num_col: u16, + /// character buffer + buf: ConsoleBuffer, +} + +impl Console { + fn new(fb: &FramebufferInfo) -> Console { + let num_row = fb.yres as u16 / CHAR_HEIGHT; + let num_col = fb.xres as u16 / CHAR_WIDTH; + Console { + color: Color(1), + row: 0, + col: 0, + num_row, + num_col, + buf: ConsoleBuffer::new(num_row, num_col), + } + } + + fn new_line(&mut self) { + self.col = 0; + if self.row < self.num_row - 1 { + self.row += 1; + } else { + self.buf.new_line(); + } + } + + fn write_byte(&mut self, byte: u8) { + match byte { + b'\x7f' => { + if self.col > 0 { + self.col -= 1; + self.buf.delete(self.row, self.col); + } else if self.row > 0 { + self.row -= 1; + self.col = self.num_col - 1; + self.buf.delete(self.row, self.col); + } + } + b'\n' => self.new_line(), + b'\r' => self.col = 0, + byte => { + if self.col >= self.num_col { + self.new_line(); + } + + let ch = ConsoleChar { + ascii_char: byte, + color: self.color, + }; + self.buf.write(self.row, self.col, ch); + self.col += 1; + } + } + } + + pub fn clear(&mut self) { + self.color = Color(1); + self.row = 0; + self.col = 0; + self.buf.clear(); + } +} + +impl fmt::Write for Console { + fn write_str(&mut self, s: &str) -> fmt::Result { + for byte in s.bytes() { + self.write_byte(byte) + } + Ok(()) + } +} + +lazy_static! { + pub static ref CONSOLE: Mutex> = Mutex::new(None); +} + +/// Initialize console driver +pub fn init() { + if let Some(fb) = FRAME_BUFFER.lock().as_ref() { + *CONSOLE.lock() = Some(Console::new(&fb.fb_info)); + } + + if let Some(console) = CONSOLE.lock().as_mut() { + console.write_str("Hello Raspberry Pi!\n").unwrap(); + } +} diff --git a/kernel/src/arch/aarch64/driver/mod.rs b/kernel/src/arch/aarch64/driver/mod.rs index 43d8c43..78e3ba5 100644 --- a/kernel/src/arch/aarch64/driver/mod.rs +++ b/kernel/src/arch/aarch64/driver/mod.rs @@ -1,12 +1,14 @@ -/// ARM64 drivers +//! ARM64 drivers +use super::board; use once::*; -use super::board; +pub mod console; /// Initialize ARM64 common drivers pub fn init() { - assert_has_not_been_called!(); + assert_has_not_been_called!("driver::init must be called only once"); board::init_driver(); + console::init(); } diff --git a/kernel/src/arch/aarch64/io.rs b/kernel/src/arch/aarch64/io.rs index bb3c986..b9815d3 100644 --- a/kernel/src/arch/aarch64/io.rs +++ b/kernel/src/arch/aarch64/io.rs @@ -1,14 +1,20 @@ //! Serial driver for aarch64. -use core::fmt::{Arguments, Write}; use super::board::serial::*; +use super::driver::console::CONSOLE; +use core::fmt::{Arguments, Write}; pub fn getchar() -> char { - unsafe { SERIAL_PORT.force_unlock(); } + unsafe { SERIAL_PORT.force_unlock() } SERIAL_PORT.lock().receive() as char } pub fn putfmt(fmt: Arguments) { - unsafe { SERIAL_PORT.force_unlock(); } - SERIAL_PORT.lock().write_fmt(fmt).unwrap() + unsafe { SERIAL_PORT.force_unlock() } + SERIAL_PORT.lock().write_fmt(fmt).unwrap(); + + unsafe { CONSOLE.force_unlock() } + if let Some(console) = CONSOLE.lock().as_mut() { + console.write_fmt(fmt).unwrap(); + } } From 7b8359eeef95c61446bd52614f0f68aa716ee728 Mon Sep 17 00:00:00 2001 From: equation314 Date: Tue, 18 Dec 2018 17:51:22 +0800 Subject: [PATCH 08/14] aarch64/fb: add 8x16 font --- kernel/src/arch/aarch64/board/raspi3/fb.rs | 2 +- kernel/src/arch/aarch64/driver/console.rs | 91 +- .../src/arch/aarch64/driver/fonts/font8x16.rs | 4629 +++++++++++++++++ kernel/src/arch/aarch64/driver/fonts/mod.rs | 12 + kernel/src/arch/aarch64/driver/mod.rs | 4 + kernel/src/arch/aarch64/io.rs | 2 +- 6 files changed, 4689 insertions(+), 51 deletions(-) create mode 100644 kernel/src/arch/aarch64/driver/fonts/font8x16.rs create mode 100644 kernel/src/arch/aarch64/driver/fonts/mod.rs diff --git a/kernel/src/arch/aarch64/board/raspi3/fb.rs b/kernel/src/arch/aarch64/board/raspi3/fb.rs index 19f9887..5f9ba64 100644 --- a/kernel/src/arch/aarch64/board/raspi3/fb.rs +++ b/kernel/src/arch/aarch64/board/raspi3/fb.rs @@ -198,6 +198,6 @@ pub fn init() { info!("framebuffer: init end\n{:#x?}", fb); *FRAME_BUFFER.lock() = Some(fb); } - Err(err) => error!("framebuffer init failed: {}", err), + Err(err) => warn!("framebuffer init failed: {}", err), } } diff --git a/kernel/src/arch/aarch64/driver/console.rs b/kernel/src/arch/aarch64/driver/console.rs index f0b01e5..209b45e 100644 --- a/kernel/src/arch/aarch64/driver/console.rs +++ b/kernel/src/arch/aarch64/driver/console.rs @@ -1,9 +1,12 @@ //! Framebuffer console display driver for ARM64 -use super::board::fb::{FramebufferInfo, FRAME_BUFFER}; +use super::fb::{FramebufferInfo, FRAME_BUFFER}; +use super::fonts::{Font, Font8x16}; use alloc::vec::Vec; -use core::fmt::{self, Write}; +use core::fmt; +use core::marker::PhantomData; use lazy_static::lazy_static; +use log::*; use spin::Mutex; #[derive(Debug, Clone, Copy)] @@ -25,41 +28,35 @@ impl Default for ConsoleChar { } } -const CHAR_WIDTH: u16 = 8; -const CHAR_HEIGHT: u16 = 16; - /// Character buffer -struct ConsoleBuffer { - num_row: u16, - num_col: u16, +struct ConsoleBuffer { + num_row: usize, + num_col: usize, buf: Vec>, + font: PhantomData, } -impl ConsoleBuffer { - fn new(num_row: u16, num_col: u16) -> ConsoleBuffer { +impl ConsoleBuffer { + fn new(num_row: usize, num_col: usize) -> ConsoleBuffer { ConsoleBuffer { num_row, num_col, - buf: vec![vec![ConsoleChar::default(); num_col as usize]; num_row as usize], + buf: vec![vec![ConsoleChar::default(); num_col]; num_row], + font: PhantomData, } } - /// Read one character at `(row, col)`. - fn read(&self, row: u16, col: u16) -> ConsoleChar { - self.buf[row as usize][col as usize] - } - /// Write one character at `(row, col)`. - /// TODO: font & color - fn write(&mut self, row: u16, col: u16, ch: ConsoleChar) { - self.buf[row as usize][col as usize] = ch; + /// TODO: color + fn write(&mut self, row: usize, col: usize, ch: ConsoleChar) { + self.buf[row][col] = ch; - let off_x = col * CHAR_WIDTH; - let off_y = row * CHAR_HEIGHT; + let off_x = col * F::WIDTH; + let off_y = row * F::HEIGHT; if let Some(fb) = FRAME_BUFFER.lock().as_mut() { - for y in 0..CHAR_HEIGHT { - for x in 0..CHAR_WIDTH { - let pixel = if ch.color.0 == 0 { 0 } else { !0 }; + for y in 0..F::HEIGHT { + for x in 0..F::WIDTH { + let pixel = if ch.color.0 != 0 && F::get(ch.ascii_char, x, y) { !0 } else { 0 }; fb.write((off_x + x) as u32, (off_y + y) as u32, pixel); } } @@ -67,7 +64,7 @@ impl ConsoleBuffer { } /// Delete one character at `(row, col)`. - fn delete(&mut self, row: u16, col: u16) { + fn delete(&mut self, row: usize, col: usize) { self.write(row, col, ConsoleChar::default()); } @@ -76,7 +73,7 @@ impl ConsoleBuffer { fn new_line(&mut self) { for i in 1..self.num_row { for j in 0..self.num_col { - self.write(i - 1, j, self.read(i, j)); + self.write(i - 1, j, self.buf[i][j]); } } for j in 0..self.num_col { @@ -86,8 +83,8 @@ impl ConsoleBuffer { /// Clear the entire buffer and screen. fn clear(&mut self) { - for i in 0..self.num_row as usize { - for j in 0..self.num_col as usize { + for i in 0..self.num_row { + for j in 0..self.num_col { self.buf[i][j] = ConsoleChar::default() } } @@ -98,38 +95,32 @@ impl ConsoleBuffer { } /// Console structure -pub struct Console { +pub struct Console { /// current color color: Color, /// cursor row - row: u16, + row: usize, /// cursor column - col: u16, - /// number of rows - num_row: u16, - /// number of columns - num_col: u16, + col: usize, /// character buffer - buf: ConsoleBuffer, + buf: ConsoleBuffer, } -impl Console { - fn new(fb: &FramebufferInfo) -> Console { - let num_row = fb.yres as u16 / CHAR_HEIGHT; - let num_col = fb.xres as u16 / CHAR_WIDTH; +impl Console { + fn new(fb: &FramebufferInfo) -> Console { + let num_row = fb.yres as usize / F::HEIGHT; + let num_col = fb.xres as usize / F::WIDTH; Console { color: Color(1), row: 0, col: 0, - num_row, - num_col, buf: ConsoleBuffer::new(num_row, num_col), } } fn new_line(&mut self) { self.col = 0; - if self.row < self.num_row - 1 { + if self.row < self.buf.num_row - 1 { self.row += 1; } else { self.buf.new_line(); @@ -144,14 +135,14 @@ impl Console { self.buf.delete(self.row, self.col); } else if self.row > 0 { self.row -= 1; - self.col = self.num_col - 1; + self.col = self.buf.num_col - 1; self.buf.delete(self.row, self.col); } } b'\n' => self.new_line(), b'\r' => self.col = 0, byte => { - if self.col >= self.num_col { + if self.col >= self.buf.num_col { self.new_line(); } @@ -173,7 +164,7 @@ impl Console { } } -impl fmt::Write for Console { +impl fmt::Write for Console { fn write_str(&mut self, s: &str) -> fmt::Result { for byte in s.bytes() { self.write_byte(byte) @@ -183,7 +174,7 @@ impl fmt::Write for Console { } lazy_static! { - pub static ref CONSOLE: Mutex> = Mutex::new(None); + pub static ref CONSOLE: Mutex>> = Mutex::new(None); } /// Initialize console driver @@ -192,7 +183,9 @@ pub fn init() { *CONSOLE.lock() = Some(Console::new(&fb.fb_info)); } - if let Some(console) = CONSOLE.lock().as_mut() { - console.write_str("Hello Raspberry Pi!\n").unwrap(); + if !CONSOLE.lock().is_none() { + info!("console: init end"); + } else { + warn!("console: init failed"); } } diff --git a/kernel/src/arch/aarch64/driver/fonts/font8x16.rs b/kernel/src/arch/aarch64/driver/fonts/font8x16.rs new file mode 100644 index 0000000..d62518c --- /dev/null +++ b/kernel/src/arch/aarch64/driver/fonts/font8x16.rs @@ -0,0 +1,4629 @@ +//! CP437 8x16 dot matrix font + +use super::Font; + +pub enum Font8x16 {} + +impl Font8x16 { + /// font data + /// copied from `linux/lib/fonts/font_8x16.c` + const DATA: [u8; 256 * 16] = [ + /* 0 0x00 '^@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 1 0x01 '^A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x81, /* 10000001 */ + 0xa5, /* 10100101 */ + 0x81, /* 10000001 */ + 0x81, /* 10000001 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0x81, /* 10000001 */ + 0x81, /* 10000001 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 2 0x02 '^B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xdb, /* 11011011 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 3 0x03 '^C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 4 0x04 '^D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 5 0x05 '^E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0xe7, /* 11100111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 6 0x06 '^F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 7 0x07 '^G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 8 0x08 '^H' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xe7, /* 11100111 */ + 0xc3, /* 11000011 */ + 0xc3, /* 11000011 */ + 0xe7, /* 11100111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 9 0x09 '^I' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x42, /* 01000010 */ + 0x42, /* 01000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 10 0x0a '^J' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xc3, /* 11000011 */ + 0x99, /* 10011001 */ + 0xbd, /* 10111101 */ + 0xbd, /* 10111101 */ + 0x99, /* 10011001 */ + 0xc3, /* 11000011 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 11 0x0b '^K' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x0e, /* 00001110 */ + 0x1a, /* 00011010 */ + 0x32, /* 00110010 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 12 0x0c '^L' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 13 0x0d '^M' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x33, /* 00110011 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x70, /* 01110000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 14 0x0e '^N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x7f, /* 01111111 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x63, /* 01100011 */ + 0x67, /* 01100111 */ + 0xe7, /* 11100111 */ + 0xe6, /* 11100110 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 15 0x0f '^O' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xdb, /* 11011011 */ + 0x3c, /* 00111100 */ + 0xe7, /* 11100111 */ + 0x3c, /* 00111100 */ + 0xdb, /* 11011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 16 0x10 '^P' */ + 0x00, /* 00000000 */ + 0x80, /* 10000000 */ + 0xc0, /* 11000000 */ + 0xe0, /* 11100000 */ + 0xf0, /* 11110000 */ + 0xf8, /* 11111000 */ + 0xfe, /* 11111110 */ + 0xf8, /* 11111000 */ + 0xf0, /* 11110000 */ + 0xe0, /* 11100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 17 0x11 '^Q' */ + 0x00, /* 00000000 */ + 0x02, /* 00000010 */ + 0x06, /* 00000110 */ + 0x0e, /* 00001110 */ + 0x1e, /* 00011110 */ + 0x3e, /* 00111110 */ + 0xfe, /* 11111110 */ + 0x3e, /* 00111110 */ + 0x1e, /* 00011110 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 18 0x12 '^R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 19 0x13 '^S' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 20 0x14 '^T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7f, /* 01111111 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7b, /* 01111011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 21 0x15 '^U' */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 22 0x16 '^V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 23 0x17 '^W' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 24 0x18 '^X' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 25 0x19 '^Y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 26 0x1a '^Z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 27 0x1b '^[' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xfe, /* 11111110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 28 0x1c '^\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 29 0x1d '^]' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x28, /* 00101000 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x28, /* 00101000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 30 0x1e '^^' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x7c, /* 01111100 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 31 0x1f '^_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0x7c, /* 01111100 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 32 0x20 ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 33 0x21 '!' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 34 0x22 '"' */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x24, /* 00100100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 35 0x23 '#' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 36 0x24 '$' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x86, /* 10000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 37 0x25 '%' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc2, /* 11000010 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0x86, /* 10000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 38 0x26 '&' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 39 0x27 ''' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 40 0x28 '(' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 41 0x29 ')' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 42 0x2a '*' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0xff, /* 11111111 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 43 0x2b '+' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 44 0x2c ',' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 45 0x2d '-' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 46 0x2e '.' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 47 0x2f '/' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x02, /* 00000010 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x80, /* 10000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 48 0x30 '0' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 49 0x31 '1' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x38, /* 00111000 */ + 0x78, /* 01111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 50 0x32 '2' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 51 0x33 '3' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x3c, /* 00111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 52 0x34 '4' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x1c, /* 00011100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 53 0x35 '5' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 54 0x36 '6' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xfc, /* 11111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 55 0x37 '7' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 56 0x38 '8' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 57 0x39 '9' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 58 0x3a ':' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 59 0x3b ';' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 60 0x3c '<' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 61 0x3d '=' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 62 0x3e '>' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 63 0x3f '?' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 64 0x40 '@' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xde, /* 11011110 */ + 0xdc, /* 11011100 */ + 0xc0, /* 11000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 65 0x41 'A' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 66 0x42 'B' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 67 0x43 'C' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc2, /* 11000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 68 0x44 'D' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 69 0x45 'E' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 70 0x46 'F' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 71 0x47 'G' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xde, /* 11011110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x66, /* 01100110 */ + 0x3a, /* 00111010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 72 0x48 'H' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 73 0x49 'I' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 74 0x4a 'J' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 75 0x4b 'K' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe6, /* 11100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 76 0x4c 'L' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 77 0x4d 'M' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xee, /* 11101110 */ + 0xfe, /* 11111110 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 78 0x4e 'N' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xfe, /* 11111110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 79 0x4f 'O' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 80 0x50 'P' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 81 0x51 'Q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xde, /* 11011110 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 82 0x52 'R' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfc, /* 11111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 83 0x53 'S' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 84 0x54 'T' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x5a, /* 01011010 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 85 0x55 'U' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 86 0x56 'V' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 87 0x57 'W' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0xee, /* 11101110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 88 0x58 'X' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x7c, /* 01111100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x7c, /* 01111100 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 89 0x59 'Y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 90 0x5a 'Z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x86, /* 10000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc2, /* 11000010 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 91 0x5b '[' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 92 0x5c '\' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x80, /* 10000000 */ + 0xc0, /* 11000000 */ + 0xe0, /* 11100000 */ + 0x70, /* 01110000 */ + 0x38, /* 00111000 */ + 0x1c, /* 00011100 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x02, /* 00000010 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 93 0x5d ']' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 94 0x5e '^' */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 95 0x5f '_' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 96 0x60 '`' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 97 0x61 'a' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 98 0x62 'b' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 99 0x63 'c' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 100 0x64 'd' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 101 0x65 'e' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 102 0x66 'f' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x36, /* 00110110 */ + 0x32, /* 00110010 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 103 0x67 'g' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0xcc, /* 11001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 104 0x68 'h' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x6c, /* 01101100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 105 0x69 'i' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 106 0x6a 'j' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + + /* 107 0x6b 'k' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xe0, /* 11100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x78, /* 01111000 */ + 0x78, /* 01111000 */ + 0x6c, /* 01101100 */ + 0x66, /* 01100110 */ + 0xe6, /* 11100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 108 0x6c 'l' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 109 0x6d 'm' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0xfe, /* 11111110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 110 0x6e 'n' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 111 0x6f 'o' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 112 0x70 'p' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + + /* 113 0x71 'q' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x7c, /* 01111100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x1e, /* 00011110 */ + 0x00, /* 00000000 */ + + /* 114 0x72 'r' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x66, /* 01100110 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 115 0x73 's' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x38, /* 00111000 */ + 0x0c, /* 00001100 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 116 0x74 't' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0xfc, /* 11111100 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x36, /* 00110110 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 117 0x75 'u' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 118 0x76 'v' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 119 0x77 'w' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xd6, /* 11010110 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 120 0x78 'x' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 121 0x79 'y' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + + /* 122 0x7a 'z' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 123 0x7b '{' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 124 0x7c '|' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 125 0x7d '}' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x70, /* 01110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x0e, /* 00001110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 126 0x7e '~' */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 127 0x7f '' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 128 0x80 'Ç' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0xc2, /* 11000010 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc2, /* 11000010 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 129 0x81 'ü' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 130 0x82 'é' */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 131 0x83 'â' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 132 0x84 'ä' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 133 0x85 'à' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 134 0x86 'å' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 135 0x87 'ç' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 136 0x88 'ê' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 137 0x89 'ë' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 138 0x8a 'è' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 139 0x8b 'ï' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 140 0x8c 'î' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 141 0x8d 'ì' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 142 0x8e 'Ä' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 143 0x8f 'Å' */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 144 0x90 'É' */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x66, /* 01100110 */ + 0x62, /* 01100010 */ + 0x68, /* 01101000 */ + 0x78, /* 01111000 */ + 0x68, /* 01101000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 145 0x91 'æ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xec, /* 11101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x6e, /* 01101110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 146 0x92 'Æ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3e, /* 00111110 */ + 0x6c, /* 01101100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xfe, /* 11111110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xce, /* 11001110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 147 0x93 'ô' */ + 0x00, /* 00000000 */ + 0x10, /* 00010000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 148 0x94 'ö' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 149 0x95 'ò' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 150 0x96 'û' */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 151 0x97 'ù' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 152 0x98 'ÿ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7e, /* 01111110 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x78, /* 01111000 */ + 0x00, /* 00000000 */ + + /* 153 0x99 'Ö' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 154 0x9a 'Ü' */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 155 0x9b '¢' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 156 0x9c '£' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x64, /* 01100100 */ + 0x60, /* 01100000 */ + 0xf0, /* 11110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xe6, /* 11100110 */ + 0xfc, /* 11111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 157 0x9d '¥' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 158 0x9e '₧' */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xf8, /* 11111000 */ + 0xc4, /* 11000100 */ + 0xcc, /* 11001100 */ + 0xde, /* 11011110 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 159 0x9f 'ƒ' */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 160 0xa0 'á' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0x0c, /* 00001100 */ + 0x7c, /* 01111100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 161 0xa1 'í' */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 162 0xa2 'ó' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 163 0xa3 'ú' */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x00, /* 00000000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 164 0xa4 'ñ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xdc, /* 11011100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 165 0xa5 'Ñ' */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0xc6, /* 11000110 */ + 0xe6, /* 11100110 */ + 0xf6, /* 11110110 */ + 0xfe, /* 11111110 */ + 0xde, /* 11011110 */ + 0xce, /* 11001110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 166 0xa6 'ª' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 167 0xa7 'º' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 168 0xa8 '¿' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x7c, /* 01111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 169 0xa9 '⌐' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 170 0xaa '¬' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 171 0xab '½' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0xe0, /* 11100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xdc, /* 11011100 */ + 0x86, /* 10000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x3e, /* 00111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 172 0xac '¼' */ + 0x00, /* 00000000 */ + 0x60, /* 01100000 */ + 0xe0, /* 11100000 */ + 0x62, /* 01100010 */ + 0x66, /* 01100110 */ + 0x6c, /* 01101100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x66, /* 01100110 */ + 0xce, /* 11001110 */ + 0x9a, /* 10011010 */ + 0x3f, /* 00111111 */ + 0x06, /* 00000110 */ + 0x06, /* 00000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 173 0xad '¡' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 174 0xae '«' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x36, /* 00110110 */ + 0x6c, /* 01101100 */ + 0xd8, /* 11011000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 175 0xaf '»' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xd8, /* 11011000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x6c, /* 01101100 */ + 0xd8, /* 11011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 176 0xb0 '░' */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + 0x11, /* 00010001 */ + 0x44, /* 01000100 */ + + /* 177 0xb1 '▒' */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + 0x55, /* 01010101 */ + 0xaa, /* 10101010 */ + + /* 178 0xb2 '▓' */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + 0xdd, /* 11011101 */ + 0x77, /* 01110111 */ + + /* 179 0xb3 '│' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 180 0xb4 '┤' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 181 0xb5 '╡' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 182 0xb6 '╢' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 183 0xb7 '╖' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 184 0xb8 '╕' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 185 0xb9 '╣' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 186 0xba '║' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 187 0xbb '╗' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x06, /* 00000110 */ + 0xf6, /* 11110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 188 0xbc '╝' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf6, /* 11110110 */ + 0x06, /* 00000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 189 0xbd '╜' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 190 0xbe '╛' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 191 0xbf '┐' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xf8, /* 11111000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 192 0xc0 '└' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 193 0xc1 '┴' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 194 0xc2 '┬' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 195 0xc3 '├' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 196 0xc4 '─' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 197 0xc5 '┼' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 198 0xc6 '╞' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 199 0xc7 '╟' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 200 0xc8 '╚' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 201 0xc9 '╔' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 202 0xca '╩' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 203 0xcb '╦' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 204 0xcc '╠' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x37, /* 00110111 */ + 0x30, /* 00110000 */ + 0x37, /* 00110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 205 0xcd '═' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 206 0xce '╬' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xf7, /* 11110111 */ + 0x00, /* 00000000 */ + 0xf7, /* 11110111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 207 0xcf '╧' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 208 0xd0 '╨' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 209 0xd1 '╤' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 210 0xd2 '╥' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 211 0xd3 '╙' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x3f, /* 00111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 212 0xd4 '╘' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 213 0xd5 '╒' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 214 0xd6 '╓' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x3f, /* 00111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 215 0xd7 '╫' */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0xff, /* 11111111 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + + /* 216 0xd8 '╪' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0xff, /* 11111111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 217 0xd9 '┘' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xf8, /* 11111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 218 0xda '┌' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1f, /* 00011111 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 219 0xdb '█' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 220 0xdc '▄' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + + /* 221 0xdd '▌' */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + 0xf0, /* 11110000 */ + + /* 222 0xde '▐' */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + 0x0f, /* 00001111 */ + + /* 223 0xdf '▀' */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0xff, /* 11111111 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 224 0xe0 'α' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xdc, /* 11011100 */ + 0x76, /* 01110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 225 0xe1 'ß' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x78, /* 01111000 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xcc, /* 11001100 */ + 0xd8, /* 11011000 */ + 0xcc, /* 11001100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xcc, /* 11001100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 226 0xe2 'Γ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 227 0xe3 'π' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 228 0xe4 'Σ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 229 0xe5 'σ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 230 0xe6 'µ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + + /* 231 0xe7 'τ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 232 0xe8 'Φ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 233 0xe9 'Θ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xfe, /* 11111110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 234 0xea 'Ω' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0xee, /* 11101110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 235 0xeb 'δ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1e, /* 00011110 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x3e, /* 00111110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x66, /* 01100110 */ + 0x3c, /* 00111100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 236 0xec '∞' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 237 0xed 'φ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x03, /* 00000011 */ + 0x06, /* 00000110 */ + 0x7e, /* 01111110 */ + 0xdb, /* 11011011 */ + 0xdb, /* 11011011 */ + 0xf3, /* 11110011 */ + 0x7e, /* 01111110 */ + 0x60, /* 01100000 */ + 0xc0, /* 11000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 238 0xee 'ε' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x1c, /* 00011100 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x7c, /* 01111100 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 239 0xef '∩' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7c, /* 01111100 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0xc6, /* 11000110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 240 0xf0 '≡' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0xfe, /* 11111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 241 0xf1 '±' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x7e, /* 01111110 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 242 0xf2 '≥' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x06, /* 00000110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 243 0xf3 '≤' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x30, /* 00110000 */ + 0x60, /* 01100000 */ + 0x30, /* 00110000 */ + 0x18, /* 00011000 */ + 0x0c, /* 00001100 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 244 0xf4 '⌠' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x0e, /* 00001110 */ + 0x1b, /* 00011011 */ + 0x1b, /* 00011011 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + + /* 245 0xf5 '⌡' */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0xd8, /* 11011000 */ + 0x70, /* 01110000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 246 0xf6 '÷' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 247 0xf7 '≈' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x76, /* 01110110 */ + 0xdc, /* 11011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 248 0xf8 '°' */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x38, /* 00111000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 249 0xf9 '·' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 250 0xfa '•' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x18, /* 00011000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 251 0xfb '√' */ + 0x00, /* 00000000 */ + 0x0f, /* 00001111 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0x0c, /* 00001100 */ + 0xec, /* 11101100 */ + 0x6c, /* 01101100 */ + 0x6c, /* 01101100 */ + 0x3c, /* 00111100 */ + 0x1c, /* 00011100 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 252 0xfc 'ⁿ' */ + 0x00, /* 00000000 */ + 0x6c, /* 01101100 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x36, /* 00110110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 253 0xfd '²' */ + 0x00, /* 00000000 */ + 0x3c, /* 00111100 */ + 0x66, /* 01100110 */ + 0x0c, /* 00001100 */ + 0x18, /* 00011000 */ + 0x32, /* 00110010 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 254 0xfe '■' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x7e, /* 01111110 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + + /* 255 0xff ' ' */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + ]; +} + +impl Font for Font8x16 { + const HEIGHT: usize = 16; + const WIDTH: usize = 8; + + #[inline] + fn get(byte: u8, x: usize, y: usize) -> bool { + Self::DATA[byte as usize * 16 + y] & (1 << (7 - x)) != 0 + } +} diff --git a/kernel/src/arch/aarch64/driver/fonts/mod.rs b/kernel/src/arch/aarch64/driver/fonts/mod.rs new file mode 100644 index 0000000..277f477 --- /dev/null +++ b/kernel/src/arch/aarch64/driver/fonts/mod.rs @@ -0,0 +1,12 @@ +//! Console font + +mod font8x16; + +pub use self::font8x16::Font8x16; + +pub trait Font { + const HEIGHT: usize; + const WIDTH: usize; + + fn get(byte: u8, x: usize, y: usize) -> bool; +} diff --git a/kernel/src/arch/aarch64/driver/mod.rs b/kernel/src/arch/aarch64/driver/mod.rs index 78e3ba5..c7553ff 100644 --- a/kernel/src/arch/aarch64/driver/mod.rs +++ b/kernel/src/arch/aarch64/driver/mod.rs @@ -3,6 +3,10 @@ use super::board; use once::*; +pub use self::board::fb; +pub use self::board::serial; + +pub mod fonts; pub mod console; /// Initialize ARM64 common drivers diff --git a/kernel/src/arch/aarch64/io.rs b/kernel/src/arch/aarch64/io.rs index b9815d3..cfad9eb 100644 --- a/kernel/src/arch/aarch64/io.rs +++ b/kernel/src/arch/aarch64/io.rs @@ -1,6 +1,6 @@ //! Serial driver for aarch64. -use super::board::serial::*; +use super::driver::serial::*; use super::driver::console::CONSOLE; use core::fmt::{Arguments, Write}; From 9dda78d2e32077ead3c8077cafff0854a220d55c Mon Sep 17 00:00:00 2001 From: equation314 Date: Tue, 18 Dec 2018 22:53:20 +0800 Subject: [PATCH 09/14] aarch64/fb: improve the performance of ConsoleBuffer::new_line() --- kernel/src/arch/aarch64/board/raspi3/fb.rs | 41 ++++++++++++++++++---- kernel/src/arch/aarch64/driver/console.rs | 21 +++++++---- 2 files changed, 49 insertions(+), 13 deletions(-) diff --git a/kernel/src/arch/aarch64/board/raspi3/fb.rs b/kernel/src/arch/aarch64/board/raspi3/fb.rs index 5f9ba64..869b7eb 100644 --- a/kernel/src/arch/aarch64/board/raspi3/fb.rs +++ b/kernel/src/arch/aarch64/board/raspi3/fb.rs @@ -176,15 +176,44 @@ impl Framebuffer { } } - /// Clean screen - pub fn clear(&mut self) { - let mut start = self.base_addr(); - let end = start + self.fb_info.screen_size as usize; + /// Copy buffer `[src_off .. src_off + size]` to `[dst_off .. dst_off + size]`. + /// `dst_off`, `src_off` and `size` must be aligned with `usize`. + pub fn copy(&mut self, dst_off: usize, src_off: usize, size: usize) { + const USIZE: usize = core::mem::size_of::(); + let mut dst = self.base_addr() + dst_off; + let mut src = self.base_addr() + src_off; + let src_end = src + size; + while src < src_end { + unsafe { *(dst as *mut usize) = *(src as *mut usize) } + dst += USIZE; + src += USIZE; + } + } + + /// Fill buffer `[offset .. offset + size]` with `pixel`. + /// `offset` and `size` must be aligned with `usize`. + pub fn fill(&mut self, offset: usize, size: usize, pixel: u32) { + const USIZE: usize = core::mem::size_of::(); + let mut value: usize = 0; + let repeat = USIZE * 8 / self.fb_info.depth as usize; + let mask = ((1u64 << self.fb_info.depth) - 1) as usize; + for i in 0..repeat { + value <<= self.fb_info.depth; + value += pixel as usize & mask; + } + + let mut start = self.base_addr() + offset; + let end = start + size; while start < end { - unsafe { *(start as *mut usize) = 0 } - start += core::mem::size_of::(); + unsafe { *(start as *mut usize) = value } + start += USIZE; } } + + /// Fill the entire buffer with `0`. + pub fn clear(&mut self) { + self.fill(0, self.fb_info.screen_size as usize, 0); + } } lazy_static! { diff --git a/kernel/src/arch/aarch64/driver/console.rs b/kernel/src/arch/aarch64/driver/console.rs index 209b45e..4822e41 100644 --- a/kernel/src/arch/aarch64/driver/console.rs +++ b/kernel/src/arch/aarch64/driver/console.rs @@ -9,10 +9,10 @@ use lazy_static::lazy_static; use log::*; use spin::Mutex; -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] struct Color(u8); -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq)] #[repr(C)] pub struct ConsoleChar { ascii_char: u8, @@ -68,16 +68,23 @@ impl ConsoleBuffer { self.write(row, col, ConsoleChar::default()); } - /// Insert one blank line at the bottom and remove the top line. - /// TODO: improve performance - fn new_line(&mut self) { + /// Insert one blank line at the bottom, and scroll up one line. + /// XXX: read framebuffer is toooo slow, do not use `fb.copy()`. + pub fn new_line(&mut self) { for i in 1..self.num_row { for j in 0..self.num_col { - self.write(i - 1, j, self.buf[i][j]); + if self.buf[i - 1][j] != self.buf[i][j] { + self.write(i - 1, j, self.buf[i][j]); + } } } for j in 0..self.num_col { - self.write(self.num_row - 1, j, ConsoleChar::default()); + self.buf[self.num_row - 1][j] = ConsoleChar::default(); + } + + if let Some(fb) = FRAME_BUFFER.lock().as_mut() { + let rowbytes = F::HEIGHT * fb.fb_info.pitch as usize; + fb.fill(rowbytes * (self.num_row - 1), rowbytes, 0); } } From 6c717905d7b2352ba58feff33a47f995a4f4580a Mon Sep 17 00:00:00 2001 From: equation314 Date: Wed, 19 Dec 2018 14:49:15 +0800 Subject: [PATCH 10/14] aarch64/fb: add foreground & background color --- kernel/src/arch/aarch64/board/raspi3/fb.rs | 43 +++++---- .../src/arch/aarch64/driver/console/color.rs | 90 +++++++++++++++++++ .../driver/{ => console}/fonts/font8x16.rs | 0 .../aarch64/driver/{ => console}/fonts/mod.rs | 0 .../driver/{console.rs => console/mod.rs} | 56 +++++++++--- kernel/src/arch/aarch64/driver/mod.rs | 2 - kernel/src/arch/aarch64/io.rs | 2 +- 7 files changed, 156 insertions(+), 37 deletions(-) create mode 100644 kernel/src/arch/aarch64/driver/console/color.rs rename kernel/src/arch/aarch64/driver/{ => console}/fonts/font8x16.rs (100%) rename kernel/src/arch/aarch64/driver/{ => console}/fonts/mod.rs (100%) rename kernel/src/arch/aarch64/driver/{console.rs => console/mod.rs} (77%) diff --git a/kernel/src/arch/aarch64/board/raspi3/fb.rs b/kernel/src/arch/aarch64/board/raspi3/fb.rs index 869b7eb..8c4ab36 100644 --- a/kernel/src/arch/aarch64/board/raspi3/fb.rs +++ b/kernel/src/arch/aarch64/board/raspi3/fb.rs @@ -39,12 +39,11 @@ pub struct FramebufferInfo { #[repr(u32)] #[derive(Debug, Clone, Copy)] -#[allow(non_camel_case_types)] -pub enum ColorFormat { - BGR565 = 16, - RGBA8888 = 32, +pub enum ColorDepth { + ColorDepth16 = 16, + ColorDepth32 = 32, } -use self::ColorFormat::*; +use self::ColorDepth::*; #[repr(C)] union ColorBuffer { @@ -54,16 +53,16 @@ union ColorBuffer { } impl ColorBuffer { - fn new(color_format: ColorFormat, bus_addr: u32, size: u32) -> ColorBuffer { + fn new(color_depth: ColorDepth, bus_addr: u32, size: u32) -> ColorBuffer { unsafe { - match color_format { - BGR565 => ColorBuffer { + match color_depth { + ColorDepth16 => ColorBuffer { buf16: core::slice::from_raw_parts_mut( bus_addr as *mut u16, (size / 2) as usize, ), }, - RGBA8888 => ColorBuffer { + ColorDepth32 => ColorBuffer { buf32: core::slice::from_raw_parts_mut( bus_addr as *mut u32, (size / 4) as usize, @@ -97,7 +96,7 @@ impl ColorBuffer { /// Frambuffer structure pub struct Framebuffer { pub fb_info: FramebufferInfo, - pub color_format: ColorFormat, + pub color_depth: ColorDepth, buf: ColorBuffer, } @@ -105,7 +104,7 @@ impl fmt::Debug for Framebuffer { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut f = f.debug_struct("Framebuffer"); f.field("fb_info", &self.fb_info); - f.field("color_format", &self.color_format); + f.field("color_depth", &self.color_depth); f.field("base_addr", unsafe { &self.buf.base_addr }); f.finish() } @@ -127,9 +126,9 @@ impl Framebuffer { }; let info = mailbox::framebuffer_alloc(width, height, depth)?; - let color_format = match info.depth { - 16 => BGR565, - 32 => RGBA8888, + let color_depth = match info.depth { + 16 => ColorDepth16, + 32 => ColorDepth32, _ => Err(format!("unsupported color depth {}", info.depth))?, }; @@ -147,8 +146,8 @@ impl Framebuffer { let paddr = info.bus_addr & !0xC0000000; let vaddr = memory::ioremap(paddr as usize, info.screen_size as usize, "fb") as u32; Ok(Framebuffer { - buf: ColorBuffer::new(color_format, vaddr, info.screen_size), - color_format, + buf: ColorBuffer::new(color_depth, vaddr, info.screen_size), + color_depth, fb_info: info, }) } @@ -161,18 +160,18 @@ impl Framebuffer { /// Read pixel at `(x, y)`. #[inline] pub fn read(&self, x: u32, y: u32) -> u32 { - match self.color_format { - BGR565 => self.buf.read16(y * self.fb_info.xres + x) as u32, - RGBA8888 => self.buf.read32(y * self.fb_info.xres + x), + match self.color_depth { + ColorDepth16 => self.buf.read16(y * self.fb_info.xres + x) as u32, + ColorDepth32 => self.buf.read32(y * self.fb_info.xres + x), } } /// Write pixel at `(x, y)`. #[inline] pub fn write(&mut self, x: u32, y: u32, pixel: u32) { - match self.color_format { - BGR565 => self.buf.write16(y * self.fb_info.xres + x, pixel as u16), - RGBA8888 => self.buf.write32(y * self.fb_info.xres + x, pixel), + match self.color_depth { + ColorDepth16 => self.buf.write16(y * self.fb_info.xres + x, pixel as u16), + ColorDepth32 => self.buf.write32(y * self.fb_info.xres + x, pixel), } } diff --git a/kernel/src/arch/aarch64/driver/console/color.rs b/kernel/src/arch/aarch64/driver/console/color.rs new file mode 100644 index 0000000..b5cdfe4 --- /dev/null +++ b/kernel/src/arch/aarch64/driver/console/color.rs @@ -0,0 +1,90 @@ +//! Frambuffer color + +pub trait FramebufferColor { + /// pack as 32-bit integer + fn pack16(&self) -> u16; + + /// pack as 32-bit integer + fn pack32(&self) -> u32; +} + +#[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct RgbColor(u8, u8, u8); + +#[repr(u8)] +#[allow(dead_code)] +#[derive(Debug, Clone, Copy, PartialEq)] +pub enum ConsoleColor { + Black = 0, + Red = 1, + Green = 2, + Yellow = 3, + Blue = 4, + Magenta = 5, + Cyan = 6, + White = 7, + BrightBlack = 60, + BrightRed = 61, + BrightGreen = 62, + BrightYellow = 63, + BrightBlue = 64, + BrightMagenta = 65, + BrightCyan = 66, + BrightWhite = 67, +} +use self::ConsoleColor::*; + +impl From for RgbColor { + /// Convert `ConsoleColor` to `RgbColor`. + /// use `CMD` color scheme. + /// (ref: https://en.wikipedia.org/wiki/ANSI_escape_code) + fn from(color: ConsoleColor) -> Self { + match color { + Black => RgbColor(0, 0, 0), + Red => RgbColor(128, 0, 0), + Green => RgbColor(0, 128, 8), + Yellow => RgbColor(128, 128, 0), + Blue => RgbColor(0, 0, 128), + Magenta => RgbColor(128, 0, 128), + Cyan => RgbColor(0, 128, 128), + White => RgbColor(192, 192, 192), + BrightBlack => RgbColor(128, 128, 128), + BrightRed => RgbColor(255, 0, 0), + BrightGreen => RgbColor(0, 255, 0), + BrightYellow => RgbColor(255, 255, 0), + BrightBlue => RgbColor(0, 0, 255), + BrightMagenta => RgbColor(255, 0, 255), + BrightCyan => RgbColor(0, 255, 255), + BrightWhite => RgbColor(255, 255, 255), + } + } +} + +impl FramebufferColor for RgbColor { + #[inline] + fn pack16(&self) -> u16 { + // BGR565 + ((self.0 as u16 & 0xF8) << 8) | ((self.1 as u16 & 0xFC) << 3) | (self.2 as u16 >> 3) + } + + #[inline] + fn pack32(&self) -> u32 { + // BGRA8888 + // FIXME: qemu and low version RPi use RGBA order for 24/32-bit color depth, + // but RPi3 B+ uses BGRA order for 24/32-bit color depth. + ((self.0 as u32) << 16) | ((self.1 as u32) << 8) | (self.2 as u32) + } +} + +impl FramebufferColor for ConsoleColor { + #[inline] + fn pack16(&self) -> u16 { + RgbColor::from(*self).pack16() + } + + #[inline] + fn pack32(&self) -> u32 { + RgbColor::from(*self).pack32() + } +} diff --git a/kernel/src/arch/aarch64/driver/fonts/font8x16.rs b/kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/fonts/font8x16.rs rename to kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs diff --git a/kernel/src/arch/aarch64/driver/fonts/mod.rs b/kernel/src/arch/aarch64/driver/console/fonts/mod.rs similarity index 100% rename from kernel/src/arch/aarch64/driver/fonts/mod.rs rename to kernel/src/arch/aarch64/driver/console/fonts/mod.rs diff --git a/kernel/src/arch/aarch64/driver/console.rs b/kernel/src/arch/aarch64/driver/console/mod.rs similarity index 77% rename from kernel/src/arch/aarch64/driver/console.rs rename to kernel/src/arch/aarch64/driver/console/mod.rs index 4822e41..89d9135 100644 --- a/kernel/src/arch/aarch64/driver/console.rs +++ b/kernel/src/arch/aarch64/driver/console/mod.rs @@ -1,7 +1,12 @@ //! Framebuffer console display driver for ARM64 -use super::fb::{FramebufferInfo, FRAME_BUFFER}; -use super::fonts::{Font, Font8x16}; +mod color; +mod fonts; + +use self::color::{ConsoleColor, ConsoleColor::*, FramebufferColor}; +use self::fonts::{Font, Font8x16}; + +use super::fb::{ColorDepth::*, FramebufferInfo, FRAME_BUFFER}; use alloc::vec::Vec; use core::fmt; use core::marker::PhantomData; @@ -9,21 +14,28 @@ use lazy_static::lazy_static; use log::*; use spin::Mutex; +#[repr(C)] #[derive(Debug, Clone, Copy, PartialEq)] -struct Color(u8); +struct ColorPair { + foreground: C, + background: C, +} -#[derive(Debug, Clone, Copy, PartialEq)] #[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq)] pub struct ConsoleChar { ascii_char: u8, - color: Color, + color: ColorPair, } impl Default for ConsoleChar { fn default() -> Self { ConsoleChar { ascii_char: b' ', - color: Color(0), + color: ColorPair { + foreground: Black, + background: Black, + }, } } } @@ -47,16 +59,29 @@ impl ConsoleBuffer { } /// Write one character at `(row, col)`. - /// TODO: color fn write(&mut self, row: usize, col: usize, ch: ConsoleChar) { self.buf[row][col] = ch; let off_x = col * F::WIDTH; let off_y = row * F::HEIGHT; if let Some(fb) = FRAME_BUFFER.lock().as_mut() { + let (foreground, background) = match fb.color_depth { + ColorDepth16 => ( + ch.color.foreground.pack16() as u32, + ch.color.background.pack16() as u32, + ), + ColorDepth32 => ( + ch.color.foreground.pack32(), + ch.color.background.pack32(), + ), + }; for y in 0..F::HEIGHT { for x in 0..F::WIDTH { - let pixel = if ch.color.0 != 0 && F::get(ch.ascii_char, x, y) { !0 } else { 0 }; + let pixel = if F::get(ch.ascii_char, x, y) { + foreground + } else { + background + }; fb.write((off_x + x) as u32, (off_y + y) as u32, pixel); } } @@ -70,7 +95,7 @@ impl ConsoleBuffer { /// Insert one blank line at the bottom, and scroll up one line. /// XXX: read framebuffer is toooo slow, do not use `fb.copy()`. - pub fn new_line(&mut self) { + fn new_line(&mut self) { for i in 1..self.num_row { for j in 0..self.num_col { if self.buf[i - 1][j] != self.buf[i][j] { @@ -104,7 +129,7 @@ impl ConsoleBuffer { /// Console structure pub struct Console { /// current color - color: Color, + color: ColorPair, /// cursor row row: usize, /// cursor column @@ -118,7 +143,10 @@ impl Console { let num_row = fb.yres as usize / F::HEIGHT; let num_col = fb.xres as usize / F::WIDTH; Console { - color: Color(1), + color: ColorPair { + foreground: BrightWhite, + background: Black, + }, row: 0, col: 0, buf: ConsoleBuffer::new(num_row, num_col), @@ -134,6 +162,7 @@ impl Console { } } + // TODO: pasre color with ANSI escape sequences fn write_byte(&mut self, byte: u8) { match byte { b'\x7f' => { @@ -164,7 +193,10 @@ impl Console { } pub fn clear(&mut self) { - self.color = Color(1); + self.color = ColorPair { + foreground: BrightWhite, + background: Black, + }; self.row = 0; self.col = 0; self.buf.clear(); diff --git a/kernel/src/arch/aarch64/driver/mod.rs b/kernel/src/arch/aarch64/driver/mod.rs index c7553ff..9c29662 100644 --- a/kernel/src/arch/aarch64/driver/mod.rs +++ b/kernel/src/arch/aarch64/driver/mod.rs @@ -5,8 +5,6 @@ use once::*; pub use self::board::fb; pub use self::board::serial; - -pub mod fonts; pub mod console; /// Initialize ARM64 common drivers diff --git a/kernel/src/arch/aarch64/io.rs b/kernel/src/arch/aarch64/io.rs index cfad9eb..d452fcb 100644 --- a/kernel/src/arch/aarch64/io.rs +++ b/kernel/src/arch/aarch64/io.rs @@ -1,4 +1,4 @@ -//! Serial driver for aarch64. +//! Input/output for aarch64. use super::driver::serial::*; use super::driver::console::CONSOLE; From 09c2b6e7b7906d67a5f98d49fa4c96c594931ddd Mon Sep 17 00:00:00 2001 From: equation314 Date: Thu, 20 Dec 2018 15:45:17 +0800 Subject: [PATCH 11/14] aarch64/fb: add ANSI escape sequences parser --- .../aarch64/driver/console/escape_parser.rs | 152 ++++++++++++++++++ .../aarch64/driver/console/fonts/font8x16.rs | 3 + .../arch/aarch64/driver/console/fonts/mod.rs | 4 + kernel/src/arch/aarch64/driver/console/mod.rs | 89 +++++----- 4 files changed, 207 insertions(+), 41 deletions(-) create mode 100644 kernel/src/arch/aarch64/driver/console/escape_parser.rs diff --git a/kernel/src/arch/aarch64/driver/console/escape_parser.rs b/kernel/src/arch/aarch64/driver/console/escape_parser.rs new file mode 100644 index 0000000..5c308f2 --- /dev/null +++ b/kernel/src/arch/aarch64/driver/console/escape_parser.rs @@ -0,0 +1,152 @@ +//! ANSI escape sequences parser +//! (ref: https://en.wikipedia.org/wiki/ANSI_escape_code) + +use super::color::{ConsoleColor, ConsoleColor::*, FramebufferColor}; +use alloc::vec::Vec; + +#[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct CharacterAttribute { + /// foreground color + pub foreground: C, + /// background color + pub background: C, + /// show underline + pub underline: bool, + /// swap foreground and background colors + pub reverse: bool, + /// text marked cfor deletion + pub strikethrough: bool, +} + +impl Default for CharacterAttribute { + fn default() -> Self { + CharacterAttribute { + foreground: White, + background: Black, + underline: false, + reverse: false, + strikethrough: false, + } + } +} + +#[derive(Debug, PartialEq)] +enum ParseStatus { + /// The last character is `ESC`, start parsing the escape sequence. + BeginEscapeSequence, + + /// The character followed by `ESC` is `[`, start parsing the CSI (Control + /// Sequence Introducer) sequence. The CSI sequence format is like + /// `ESC [ n1 ; n2 ; ... m`. + ParsingCSI, + + /// Display text Normally. + Text, +} + +#[derive(Debug)] +pub struct EscapeParser { + status: ParseStatus, + char_attr: CharacterAttribute, + current_param: Option, + params: Vec, +} + +impl EscapeParser { + pub fn new() -> EscapeParser { + EscapeParser { + status: ParseStatus::Text, + char_attr: CharacterAttribute::default(), + params: Vec::new(), + current_param: None, + } + } + + pub fn is_parsing(&self) -> bool { + self.status != ParseStatus::Text + } + + /// See an `ECS` character, start parsing escape sequence. + pub fn start_parse(&mut self) { + assert!(self.status == ParseStatus::Text); + self.status = ParseStatus::BeginEscapeSequence; + self.current_param = None; + } + + //// Parse SGR (Select Graphic Rendition) parameters. + fn parse_sgr_params(&mut self) { + use core::mem::transmute; + for param in &self.params { + match param { + 0 => self.char_attr = CharacterAttribute::default(), + 4 => self.char_attr.underline = true, + 7 => self.char_attr.reverse = true, + 9 => self.char_attr.strikethrough = true, + 24 => self.char_attr.underline = false, + 27 => self.char_attr.reverse = false, + 29 => self.char_attr.strikethrough = false, + 30...37 | 90...97 => self.char_attr.foreground = unsafe { transmute(param - 30) }, + 40...47 | 100...107 => self.char_attr.background = unsafe { transmute(param - 40) }, + _ => { /* unimplemented!() */ } + } + } + } + + /// See a character during parsing. + pub fn parse(&mut self, byte: u8) -> bool { + assert!(self.status != ParseStatus::Text); + match self.status { + ParseStatus::BeginEscapeSequence => match byte { + b'[' => { + self.status = ParseStatus::ParsingCSI; + self.current_param = Some(0); + self.params.clear(); + return true; + } + _ => { /* unimplemented!() */ } + }, + ParseStatus::ParsingCSI => match byte { + b'0'...b'9' => { + let digit = (byte - b'0') as u32; + if let Some(param) = self.current_param { + let res: u32 = param as u32 * 10 + digit; + self.current_param = if res <= 0xFF { Some(res as u8) } else { None }; + } + return true; + } + b';' => { + if let Some(param) = self.current_param { + self.params.push(param); + } + self.current_param = Some(0); + return true; + } + // @A–Z[\]^_`a–z{|}~ + 0x40...0x7E => { + if let Some(param) = self.current_param { + self.params.push(param); + } + match byte { + b'm' => self.parse_sgr_params(), + _ => { /* unimplemented!() */ } + } + self.status = ParseStatus::Text; + self.current_param = None; + self.params.clear(); + return true; + } + _ => {} + }, + ParseStatus::Text => {} + } + self.status = ParseStatus::Text; + self.current_param = None; + self.params.clear(); + false + } + + pub fn char_attribute(&self) -> CharacterAttribute { + self.char_attr + } +} diff --git a/kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs b/kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs index d62518c..89ffe67 100644 --- a/kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs +++ b/kernel/src/arch/aarch64/driver/console/fonts/font8x16.rs @@ -4622,6 +4622,9 @@ impl Font for Font8x16 { const HEIGHT: usize = 16; const WIDTH: usize = 8; + const UNDERLINE: usize = 13; + const STRIKETHROUGH: usize = 8; + #[inline] fn get(byte: u8, x: usize, y: usize) -> bool { Self::DATA[byte as usize * 16 + y] & (1 << (7 - x)) != 0 diff --git a/kernel/src/arch/aarch64/driver/console/fonts/mod.rs b/kernel/src/arch/aarch64/driver/console/fonts/mod.rs index 277f477..fde1f9a 100644 --- a/kernel/src/arch/aarch64/driver/console/fonts/mod.rs +++ b/kernel/src/arch/aarch64/driver/console/fonts/mod.rs @@ -8,5 +8,9 @@ pub trait Font { const HEIGHT: usize; const WIDTH: usize; + const UNDERLINE: usize; + const STRIKETHROUGH: usize; + + /// Whether the character `byte` is visible at `(x, y)`. fn get(byte: u8, x: usize, y: usize) -> bool; } diff --git a/kernel/src/arch/aarch64/driver/console/mod.rs b/kernel/src/arch/aarch64/driver/console/mod.rs index 89d9135..90fc38a 100644 --- a/kernel/src/arch/aarch64/driver/console/mod.rs +++ b/kernel/src/arch/aarch64/driver/console/mod.rs @@ -1,9 +1,11 @@ //! Framebuffer console display driver for ARM64 mod color; +mod escape_parser; mod fonts; -use self::color::{ConsoleColor, ConsoleColor::*, FramebufferColor}; +use self::color::FramebufferColor; +use self::escape_parser::{CharacterAttribute, EscapeParser}; use self::fonts::{Font, Font8x16}; use super::fb::{ColorDepth::*, FramebufferInfo, FRAME_BUFFER}; @@ -14,28 +16,18 @@ use lazy_static::lazy_static; use log::*; use spin::Mutex; -#[repr(C)] -#[derive(Debug, Clone, Copy, PartialEq)] -struct ColorPair { - foreground: C, - background: C, -} - #[repr(C)] #[derive(Debug, Clone, Copy, PartialEq)] pub struct ConsoleChar { ascii_char: u8, - color: ColorPair, + attr: CharacterAttribute, } impl Default for ConsoleChar { fn default() -> Self { ConsoleChar { - ascii_char: b' ', - color: ColorPair { - foreground: Black, - background: Black, - }, + ascii_char: 0, + attr: CharacterAttribute::default(), } } } @@ -60,24 +52,40 @@ impl ConsoleBuffer { /// Write one character at `(row, col)`. fn write(&mut self, row: usize, col: usize, ch: ConsoleChar) { + if self.buf[row][col] == ch { + return; + } self.buf[row][col] = ch; let off_x = col * F::WIDTH; let off_y = row * F::HEIGHT; if let Some(fb) = FRAME_BUFFER.lock().as_mut() { - let (foreground, background) = match fb.color_depth { + let (mut foreground, mut background) = match fb.color_depth { ColorDepth16 => ( - ch.color.foreground.pack16() as u32, - ch.color.background.pack16() as u32, + ch.attr.foreground.pack16() as u32, + ch.attr.background.pack16() as u32, ), ColorDepth32 => ( - ch.color.foreground.pack32(), - ch.color.background.pack32(), + ch.attr.foreground.pack32(), + ch.attr.background.pack32(), ), }; + if ch.attr.reverse { + core::mem::swap(&mut foreground, &mut background); + } + let underline_y = if ch.attr.underline { + F::UNDERLINE + } else { + F::HEIGHT + }; + let strikethrough_y = if ch.attr.strikethrough { + F::STRIKETHROUGH + } else { + F::HEIGHT + }; for y in 0..F::HEIGHT { for x in 0..F::WIDTH { - let pixel = if F::get(ch.ascii_char, x, y) { + let pixel = if y == underline_y || y == strikethrough_y || F::get(ch.ascii_char, x, y) { foreground } else { background @@ -98,18 +106,11 @@ impl ConsoleBuffer { fn new_line(&mut self) { for i in 1..self.num_row { for j in 0..self.num_col { - if self.buf[i - 1][j] != self.buf[i][j] { - self.write(i - 1, j, self.buf[i][j]); - } + self.write(i - 1, j, self.buf[i][j]); } } for j in 0..self.num_col { - self.buf[self.num_row - 1][j] = ConsoleChar::default(); - } - - if let Some(fb) = FRAME_BUFFER.lock().as_mut() { - let rowbytes = F::HEIGHT * fb.fb_info.pitch as usize; - fb.fill(rowbytes * (self.num_row - 1), rowbytes, 0); + self.write(self.num_row - 1, j, ConsoleChar::default()); } } @@ -128,12 +129,12 @@ impl ConsoleBuffer { /// Console structure pub struct Console { - /// current color - color: ColorPair, /// cursor row row: usize, /// cursor column col: usize, + /// escape sequence parser + parser: EscapeParser, /// character buffer buf: ConsoleBuffer, } @@ -143,17 +144,21 @@ impl Console { let num_row = fb.yres as usize / F::HEIGHT; let num_col = fb.xres as usize / F::WIDTH; Console { - color: ColorPair { - foreground: BrightWhite, - background: Black, - }, row: 0, col: 0, + parser: EscapeParser::new(), buf: ConsoleBuffer::new(num_row, num_col), } } fn new_line(&mut self) { + let attr_blank = ConsoleChar { + ascii_char: 0, + attr: self.parser.char_attribute(), + }; + for j in self.col..self.buf.num_col { + self.buf.write(self.row, j, attr_blank); + } self.col = 0; if self.row < self.buf.num_row - 1 { self.row += 1; @@ -162,8 +167,12 @@ impl Console { } } - // TODO: pasre color with ANSI escape sequences fn write_byte(&mut self, byte: u8) { + if self.parser.is_parsing() { + if self.parser.parse(byte) { + return; + } + } match byte { b'\x7f' => { if self.col > 0 { @@ -177,6 +186,7 @@ impl Console { } b'\n' => self.new_line(), b'\r' => self.col = 0, + b'\x1b' => self.parser.start_parse(), byte => { if self.col >= self.buf.num_col { self.new_line(); @@ -184,7 +194,7 @@ impl Console { let ch = ConsoleChar { ascii_char: byte, - color: self.color, + attr: self.parser.char_attribute(), }; self.buf.write(self.row, self.col, ch); self.col += 1; @@ -193,12 +203,9 @@ impl Console { } pub fn clear(&mut self) { - self.color = ColorPair { - foreground: BrightWhite, - background: Black, - }; self.row = 0; self.col = 0; + self.parser = EscapeParser::new(); self.buf.clear(); } } From b0915b102a0be1bc530a6daddeaf559e2e86075d Mon Sep 17 00:00:00 2001 From: equation314 Date: Thu, 20 Dec 2018 17:01:56 +0800 Subject: [PATCH 12/14] aarch64/fb: add new rust user program `fantastic_text` --- user/src/bin/fantastic_text.rs | 43 ++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 user/src/bin/fantastic_text.rs diff --git a/user/src/bin/fantastic_text.rs b/user/src/bin/fantastic_text.rs new file mode 100644 index 0000000..40deec9 --- /dev/null +++ b/user/src/bin/fantastic_text.rs @@ -0,0 +1,43 @@ +#![no_std] +#![no_main] + +#[macro_use] +extern crate ucore_ulib; + +macro_rules! color_text { + ($text:expr, $color:expr) => {{ + format_args!("\x1b[{}m{}\x1b[0m", $color, $text) + }}; +} + +// IMPORTANT: Must define main() like this +#[no_mangle] +pub fn main() { + println!( + "{}{}{}{}{} {}{}{}{} {}{}{}{}{}{}", + color_text!("H", 31), + color_text!("e", 32), + color_text!("l", 33), + color_text!("l", 34), + color_text!("o", 35), + color_text!("R", 36), + color_text!("u", 37), + color_text!("s", 90), + color_text!("t", 91), + color_text!("u", 92), + color_text!("C", 93), + color_text!("o", 94), + color_text!("r", 95), + color_text!("e", 96), + color_text!("!", 97), + ); + + let text = "reguler \x1b[4munderline\x1b[24m \x1b[7mreverse\x1b[27m \x1b[9mstrikethrough\x1b[29m"; + println!("\x1b[47m{}\x1b[0m", color_text!(text, 30)); + for i in 31..38 { + println!("{}", color_text!(text, i)); + } + for i in 90..98 { + println!("{}", color_text!(text, i)); + } +} From a55f3b61e6eb08d111d0bc768f0c93dcc1ea29a6 Mon Sep 17 00:00:00 2001 From: equation314 Date: Thu, 20 Dec 2018 17:34:24 +0800 Subject: [PATCH 13/14] add Makefile option `graphic` & cargo feature `nographic` --- kernel/Cargo.toml | 1 + kernel/Makefile | 52 +++++++++++++-------- kernel/src/arch/aarch64/board/raspi3/mod.rs | 1 + 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 6718500..f1040ee 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -12,6 +12,7 @@ no_mmu = [] # Kernel in M-mode (for riscv32) m_mode = ["no_mmu"] # (for aarch64 RaspberryPi3) +nographic = [] board_raspi3 = ["bcm2837"] raspi3_use_generic_timer = ["bcm2837/use_generic_timer"] diff --git a/kernel/Makefile b/kernel/Makefile index 7173184..a6cfb7a 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -1,22 +1,23 @@ # Commands: -# make build Build -# make run Build and run in QEMU -# make justrun Run the last build -# make doc Generate docs -# make asm Open the deassemble file of the last build -# make header Open 'objdump -h' of the last build -# make clean Clean +# make build Build +# make run Build and run in QEMU +# make justrun Run the last build +# make doc Generate docs +# make asm Open the deassemble file of the last build +# make header Open 'objdump -h' of the last build +# make clean Clean # # Options: -# arch = x86_64 | riscv32 | aarch64 -# d = int | in_asm | ... QEMU debug info -# mode = debug | release -# LOG = off | error | warn | info | debug | trace -# SFSIMG = SFS image path of user programs -# smp = 1 | 2 | ... SMP core number -# board = fpga Only available on riscv32, build without bbl, run on board -# | raspi3 Only available on aarch64, run on Raspberry Pi 3 Model B/B+ -# m_mode Only available on riscv32, build for M-Mode, without MMU +# arch = x86_64 | riscv32 | aarch64 +# d = int | in_asm | ... QEMU debug info +# mode = debug | release +# LOG = off | error | warn | info | debug | trace +# SFSIMG = SFS image path of user programs +# smp = 1 | 2 | ... SMP core number +# graphic = on | off enable/disable qemu graphical output +# board = fpga Only available on riscv32, build without bbl, run on board +# | raspi3 Only available on aarch64, run on Raspberry Pi 3 Model B/B+ +# m_mode Only available on riscv32, build for M-Mode, without MMU arch ?= riscv32 board ?= raspi3 @@ -24,7 +25,7 @@ mode ?= debug LOG ?= debug smp ?= 4 # NOTE: crate 'process' use this name 'm_mode' as an environment -# to set interrupt (MIE or SIE) +# to set interrupt (MIE or SIE) m_mode ?= target := $(arch)-blog_os @@ -40,10 +41,15 @@ user_obj := build/$(arch)/user.o export ARCH = $(arch) export SFSIMG = $(user_dir)/build/user-$(arch).img +ifeq ($(arch), aarch64) +graphic ?= on +else +graphic ?= off +endif + ### qemu options ### qemu_opts := \ - -smp cores=$(smp) \ - -nographic + -smp cores=$(smp) ifeq ($(arch), x86_64) qemu_opts += \ @@ -67,6 +73,10 @@ qemu_opts += \ -kernel $(bin) endif +ifneq ($(graphic), on) +qemu_opts += -nographic +endif + ifdef d qemu_opts += -d $(d) endif @@ -78,6 +88,10 @@ features += no_bbl endif endif +ifneq ($(graphic), on) +features += nographic +endif + ifeq ($(board), raspi3) # qemu only has generic timer # TODO: configure system/generic timer automatically diff --git a/kernel/src/arch/aarch64/board/raspi3/mod.rs b/kernel/src/arch/aarch64/board/raspi3/mod.rs index 2bbee12..6954e99 100644 --- a/kernel/src/arch/aarch64/board/raspi3/mod.rs +++ b/kernel/src/arch/aarch64/board/raspi3/mod.rs @@ -22,6 +22,7 @@ pub fn init_serial_early() { /// Initialize raspi3 drivers pub fn init_driver() { + #[cfg(not(feature = "nographic"))] fb::init(); timer::init(); } From f8b48e8b8524bd7f0debac45ebdb0e64836331e9 Mon Sep 17 00:00:00 2001 From: equation314 Date: Thu, 20 Dec 2018 17:36:29 +0800 Subject: [PATCH 14/14] update display configures in raspi-firmware/config.txt --- tools/raspi-firmware/config.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/raspi-firmware/config.txt b/tools/raspi-firmware/config.txt index 89ebfb4..c952e46 100755 --- a/tools/raspi-firmware/config.txt +++ b/tools/raspi-firmware/config.txt @@ -25,8 +25,8 @@ #hdmi_force_hotplug=1 # uncomment to force a specific HDMI mode (this will force VGA) -#hdmi_group=1 -#hdmi_mode=1 +hdmi_group=2 # DMT +hdmi_mode=85 # 1280x720 # uncomment to force a HDMI mode rather than DVI. This can make audio work in # DMT (computer monitor) modes