diff options
author | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-19 06:28:01 +0200 |
---|---|---|
committer | Sebastian Huber <sebastian.huber@embedded-brains.de> | 2018-04-20 13:08:32 +0200 |
commit | d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc (patch) | |
tree | caa54b4229e86a68c84ab5961af34e087dce5302 /bsps/arm | |
parent | bsps/powerpc: Move shared btimer support (diff) | |
download | rtems-d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc.tar.bz2 |
bsps: Move console drivers to bsps
This patch is a part of the BSP source reorganization.
Update #3285.
Diffstat (limited to 'bsps/arm')
42 files changed, 13086 insertions, 0 deletions
diff --git a/bsps/arm/altera-cyclone-v/console/console-config.c b/bsps/arm/altera-cyclone-v/console/console-config.c new file mode 100644 index 0000000000..e4dfec9f62 --- /dev/null +++ b/bsps/arm/altera-cyclone-v/console/console-config.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libchip/ns16550.h> + +#include <rtems/bspIo.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/alt_clock_manager.h> +#include <bsp/console-termios.h> +#include <bsp/socal/alt_rstmgr.h> +#include <bsp/socal/socal.h> +#include <bsp/socal/alt_uart.h> +#include <bsp/socal/hps.h> + +#ifdef BSP_USE_UART_INTERRUPTS + #define DEVICE_FNS &ns16550_handler_interrupt +#else + #define DEVICE_FNS &ns16550_handler_polled +#endif + +static uint8_t altera_cyclone_v_uart_get_register(uintptr_t addr, uint8_t i) +{ + volatile uint32_t *reg = (volatile uint32_t *) addr; + + return (uint8_t) reg [i]; +} + +static void altera_cyclone_v_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val) +{ + volatile uint32_t *reg = (volatile uint32_t *) addr; + + reg [i] = val; +} + +static bool altera_cyclone_v_uart_probe( + rtems_termios_device_context *base, + uint32_t uart_set_mask +) +{ + ns16550_context *ctx = (ns16550_context *) base; + bool ret = true; + uint32_t ucr; + ALT_STATUS_CODE sc; + void* location = (void *) ctx->port; + + /* The ALT_CLK_L4_SP is required for all SoCFPGA UARTs. + * Check that it's enabled. */ + if ( alt_clk_is_enabled(ALT_CLK_L4_SP) != ALT_E_TRUE ) { + ret = false; + } + + if ( ret ) { + sc = alt_clk_freq_get(ALT_CLK_L4_SP, &ctx->clock); + if ( sc != ALT_E_SUCCESS ) { + ret = false; + } + } + + if ( ret ) { + // Bring UART out of reset. + alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, uart_set_mask); + + // Verify the UCR (UART Component Version) + ucr = alt_read_word( ALT_UART_UCV_ADDR( location ) ); + if ( ucr != ALT_UART_UCV_UART_COMPONENT_VER_RESET ) { + ret = false; + } + } + + if ( ret ) { + // Write SRR::UR (Shadow Reset Register :: UART Reset) + alt_write_word( ALT_UART_SRR_ADDR( location ), ALT_UART_SRR_UR_SET_MSK ); + + // Read the MSR to work around case:119085. + (void)alt_read_word( ALT_UART_MSR_ADDR( location ) ); + + ret = ns16550_probe( base ); + } + + return ret; +} + +#ifdef CYCLONE_V_CONFIG_CONSOLE +static bool altera_cyclone_v_uart_probe_0(rtems_termios_device_context *base) +{ + return altera_cyclone_v_uart_probe(base, ALT_RSTMGR_PERMODRST_UART0_SET_MSK); +} + +static ns16550_context altera_cyclone_v_uart_context_0 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"), + .get_reg = altera_cyclone_v_uart_get_register, + .set_reg = altera_cyclone_v_uart_set_register, + .port = (uintptr_t) ALT_UART0_ADDR, + .irq = ALT_INT_INTERRUPT_UART0, + .initial_baud = CYCLONE_V_UART_BAUD +}; +#endif + +#ifdef CYCLONE_V_CONFIG_UART_1 +static bool altera_cyclone_v_uart_probe_1(rtems_termios_device_context *base) +{ + return altera_cyclone_v_uart_probe(base, ALT_RSTMGR_PERMODRST_UART1_SET_MSK); +} + +static ns16550_context altera_cyclone_v_uart_context_1 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"), + .get_reg = altera_cyclone_v_uart_get_register, + .set_reg = altera_cyclone_v_uart_set_register, + .port = (uintptr_t) ALT_UART1_ADDR, + .irq = ALT_INT_INTERRUPT_UART1, + .initial_baud = CYCLONE_V_UART_BAUD +}; +#endif + +const console_device console_device_table[] = { + #ifdef CYCLONE_V_CONFIG_CONSOLE + { + .device_file = "/dev/ttyS0", + .probe = altera_cyclone_v_uart_probe_0, + .handler = DEVICE_FNS, + .context = &altera_cyclone_v_uart_context_0.base + }, + #endif + #ifdef CYCLONE_V_CONFIG_UART_1 + { + .device_file = "/dev/ttyS1", + .probe = altera_cyclone_v_uart_probe_1, + .handler = DEVICE_FNS, + .context = &altera_cyclone_v_uart_context_1.base + }, + #endif +}; + +const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table); + +static void output_char(char c) +{ + rtems_termios_device_context *ctx = console_device_table[0].context; + + ns16550_polled_putchar( ctx, c ); +} + +BSP_output_char_function_type BSP_output_char = output_char; + +BSP_polling_getchar_function_type BSP_poll_char = NULL; diff --git a/bsps/arm/atsam/console/console.c b/bsps/arm/atsam/console/console.c new file mode 100644 index 0000000000..d51d2ace7d --- /dev/null +++ b/bsps/arm/atsam/console/console.c @@ -0,0 +1,526 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/fatal.h> +#include <rtems/console.h> + +#include <rtems/termiostypes.h> + +#include <chip.h> + +#include <unistd.h> + +typedef struct { + rtems_termios_device_context base; + Usart *regs; + rtems_vector_number irq; + uint32_t id; + bool console; +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + bool transmitting; +#endif +} atsam_usart_context; + +static atsam_usart_context atsam_usart_instances[] = { + { + .regs = USART0, + .irq = USART0_IRQn, + .id = ID_USART0 + } +#ifdef USART1 + , { + .regs = USART1, + .irq = USART1_IRQn, + .id = ID_USART1 + } +#endif +#ifdef USART2 + , { + .regs = USART2, + .irq = USART2_IRQn, + .id = ID_USART2 + } +#endif +}; + +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS +static void atsam_usart_interrupt(void *arg) +{ + rtems_termios_tty *tty = arg; + atsam_usart_context *ctx = rtems_termios_get_device_context(tty); + Usart *regs = ctx->regs; + uint32_t csr = regs->US_CSR; + + while ((csr & US_CSR_RXRDY) != 0) { + char c = (char) regs->US_RHR; + + rtems_termios_enqueue_raw_characters(tty, &c, 1); + + csr = regs->US_CSR; + } + + if (ctx->transmitting && (csr & US_CSR_TXEMPTY) != 0) { + rtems_termios_dequeue_characters(tty, 1); + } +} +#endif + +static bool atsam_usart_set_attributes( + rtems_termios_device_context *base, + const struct termios *term +) +{ + atsam_usart_context *ctx = (atsam_usart_context *) base; + Usart *regs = ctx->regs; + rtems_termios_baud_t baud; + uint32_t mr; + + baud = rtems_termios_baud_to_number(term->c_ospeed); + regs->US_BRGR = (BOARD_MCK / baud) / 16; + + if ((term->c_cflag & CREAD) != 0) { + regs->US_CR = US_CR_RXEN | US_CR_TXEN; + } else { + regs->US_CR = US_CR_TXEN; + } + + mr = US_MR_USART_MODE_NORMAL | US_MR_USCLKS_MCK; + + switch (term->c_cflag & CSIZE) { + case CS5: + mr |= US_MR_CHRL_5_BIT; + break; + case CS6: + mr |= US_MR_CHRL_6_BIT; + break; + case CS7: + mr |= US_MR_CHRL_7_BIT; + break; + default: + mr |= US_MR_CHRL_8_BIT; + break; + } + + if ((term->c_cflag & PARENB) != 0) { + if ((term->c_cflag & PARODD) != 0) { + mr |= US_MR_PAR_ODD; + } else { + mr |= US_MR_PAR_EVEN; + } + } else { + mr |= US_MR_PAR_NO; + } + + if ((term->c_cflag & CSTOPB) != 0) { + mr |= US_MR_NBSTOP_2_BIT; + } else { + mr |= US_MR_NBSTOP_1_BIT; + } + + regs->US_MR = mr; + + return true; +} + +static bool atsam_usart_first_open( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + struct termios *term, + rtems_libio_open_close_args_t *args +) +{ + atsam_usart_context *ctx = (atsam_usart_context *) base; + Usart *regs = ctx->regs; +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + rtems_status_code sc; +#endif + + regs->US_CR = US_CR_RSTRX | US_CR_RSTTX | US_CR_RSTSTA; + regs->US_IDR = 0xffffffff; + + PMC_EnablePeripheral(ctx->id); + + rtems_termios_set_initial_baud(tty, ATSAM_CONSOLE_BAUD); + atsam_usart_set_attributes(base, term); + +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + regs->US_IER = US_IDR_RXRDY; + sc = rtems_interrupt_handler_install( + ctx->irq, + "USART", + RTEMS_INTERRUPT_SHARED, + atsam_usart_interrupt, + tty + ); + if (sc != RTEMS_SUCCESSFUL) { + return false; + } +#endif + + return true; +} + +static void atsam_usart_last_close( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + rtems_libio_open_close_args_t *args +) +{ + atsam_usart_context *ctx = (atsam_usart_context *) base; + +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + rtems_interrupt_handler_remove(ctx->irq, atsam_usart_interrupt, tty); +#endif + + if (!ctx->console) { + PMC_DisablePeripheral(ctx->id); + } +} + +static void atsam_usart_write( + rtems_termios_device_context *base, + const char *buf, + size_t len +) +{ + atsam_usart_context *ctx = (atsam_usart_context *) base; + Usart *regs = ctx->regs; + +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + if (len > 0) { + ctx->transmitting = true; + regs->US_THR = buf[0]; + regs->US_IER = US_IDR_TXEMPTY; + } else { + ctx->transmitting = false; + regs->US_IDR = US_IDR_TXEMPTY; + } +#else + size_t i; + + for (i = 0; i < len; ++i) { + while ((regs->US_CSR & US_CSR_TXEMPTY) == 0) { + /* Wait */ + } + + regs->US_THR = buf[i]; + } +#endif +} + +#ifndef ATSAM_CONSOLE_USE_INTERRUPTS +static int atsam_usart_read(rtems_termios_device_context *base) +{ + atsam_usart_context *ctx = (atsam_usart_context *) base; + Usart *regs = ctx->regs; + + if ((regs->US_CSR & US_CSR_RXRDY) != 0) { + return (char) regs->US_RHR; + } else { + return -1; + } +} +#endif + +static const rtems_termios_device_handler atsam_usart_handler = { + .first_open = atsam_usart_first_open, + .last_close = atsam_usart_last_close, + .write = atsam_usart_write, + .set_attributes = atsam_usart_set_attributes, +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + .mode = TERMIOS_IRQ_DRIVEN +#else + .poll_read = atsam_usart_read, + .mode = TERMIOS_POLLED +#endif +}; + +typedef struct { + rtems_termios_device_context base; + Uart *regs; + rtems_vector_number irq; + uint32_t id; + bool console; +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + bool transmitting; +#endif +} atsam_uart_context; + +static atsam_uart_context atsam_uart_instances[] = { + { + .regs = UART0, + .irq = UART0_IRQn, + .id = ID_UART0 + } +#ifdef UART1 + , { + .regs = UART1, + .irq = UART1_IRQn, + .id = ID_UART1 + } +#endif +#ifdef UART2 + , { + .regs = UART2, + .irq = UART2_IRQn, + .id = ID_UART2 + } +#endif +#ifdef UART3 + , { + .regs = UART3, + .irq = UART3_IRQn, + .id = ID_UART3 + } +#endif +#ifdef UART4 + , { + .regs = UART4, + .irq = UART4_IRQn, + .id = ID_UART4 + } +#endif +}; + +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS +static void atsam_uart_interrupt(void *arg) +{ + rtems_termios_tty *tty = arg; + atsam_uart_context *ctx = rtems_termios_get_device_context(tty); + Uart *regs = ctx->regs; + uint32_t sr = regs->UART_SR; + + while ((sr & UART_SR_RXRDY) != 0) { + char c = (char) regs->UART_RHR; + + rtems_termios_enqueue_raw_characters(tty, &c, 1); + + sr = regs->UART_SR; + } + + if (ctx->transmitting && (sr & UART_SR_TXEMPTY) != 0) { + rtems_termios_dequeue_characters(tty, 1); + } +} +#endif + +static bool atsam_uart_set_attributes( + rtems_termios_device_context *base, + const struct termios *term +) +{ + atsam_uart_context *ctx = (atsam_uart_context *) base; + Uart *regs = ctx->regs; + rtems_termios_baud_t baud; + uint32_t mr; + + baud = rtems_termios_baud_to_number(term->c_ospeed); + regs->UART_BRGR = (BOARD_MCK / baud) / 16; + + if ((term->c_cflag & CREAD) != 0) { + regs->UART_CR = UART_CR_RXEN | UART_CR_TXEN; + } else { + regs->UART_CR = UART_CR_TXEN; + } + + mr = UART_MR_FILTER_DISABLED | UART_MR_BRSRCCK_PERIPH_CLK; + + if ((term->c_cflag & CSIZE) != CS8) { + return false; + } + + if ((term->c_cflag & PARENB) != 0) { + if ((term->c_cflag & PARODD) != 0) { + mr |= UART_MR_PAR_ODD; + } else { + mr |= UART_MR_PAR_EVEN; + } + } else { + mr |= UART_MR_PAR_NO; + } + + if ((term->c_cflag & CSTOPB) != 0) { + return false; + } + + regs->UART_MR = mr; + + return true; +} + +static bool atsam_uart_first_open( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + struct termios *term, + rtems_libio_open_close_args_t *args +) +{ + atsam_uart_context *ctx = (atsam_uart_context *) base; + Uart *regs = ctx->regs; +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + rtems_status_code sc; +#endif + + regs->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RSTSTA; + regs->UART_IDR = 0xffffffff; + + PMC_EnablePeripheral(ctx->id); + + rtems_termios_set_initial_baud(tty, ATSAM_CONSOLE_BAUD); + atsam_uart_set_attributes(base, term); + +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + regs->UART_IER = UART_IDR_RXRDY; + sc = rtems_interrupt_handler_install( + ctx->irq, + "UART", + RTEMS_INTERRUPT_SHARED, + atsam_uart_interrupt, + tty + ); + if (sc != RTEMS_SUCCESSFUL) { + return false; + } +#endif + + return true; +} + +static void atsam_uart_last_close( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + rtems_libio_open_close_args_t *args +) +{ + atsam_uart_context *ctx = (atsam_uart_context *) base; + +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + rtems_interrupt_handler_remove(ctx->irq, atsam_uart_interrupt, tty); +#endif + + if (!ctx->console) { + PMC_DisablePeripheral(ctx->id); + } +} + +static void atsam_uart_write( + rtems_termios_device_context *base, + const char *buf, + size_t len +) +{ + atsam_uart_context *ctx = (atsam_uart_context *) base; + Uart *regs = ctx->regs; + +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + if (len > 0) { + ctx->transmitting = true; + regs->UART_THR = buf[0]; + regs->UART_IER = UART_IDR_TXEMPTY; + } else { + ctx->transmitting = false; + regs->UART_IDR = UART_IDR_TXEMPTY; + } +#else + size_t i; + + for (i = 0; i < len; ++i) { + while ((regs->UART_SR & UART_SR_TXEMPTY) == 0) { + /* Wait */ + } + + regs->UART_THR = buf[i]; + } +#endif +} + +#ifndef ATSAM_CONSOLE_USE_INTERRUPTS +static int atsam_uart_read(rtems_termios_device_context *base) +{ + atsam_uart_context *ctx = (atsam_uart_context *) base; + Uart *regs = ctx->regs; + + if ((regs->UART_SR & UART_SR_RXRDY) != 0) { + return (char) regs->UART_RHR; + } else { + return -1; + } +} +#endif + +static const rtems_termios_device_handler atsam_uart_handler = { + .first_open = atsam_uart_first_open, + .last_close = atsam_uart_last_close, + .write = atsam_uart_write, + .set_attributes = atsam_uart_set_attributes, +#ifdef ATSAM_CONSOLE_USE_INTERRUPTS + .mode = TERMIOS_IRQ_DRIVEN +#else + .poll_read = atsam_uart_read, + .mode = TERMIOS_POLLED +#endif +}; + +rtems_status_code console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + size_t i; + + rtems_termios_initialize(); + + for (i = 0; i < RTEMS_ARRAY_SIZE(atsam_usart_instances); ++i) { + char usart[] = "/dev/ttyUSARTX"; + + usart[sizeof(usart) - 2] = (char) ('0' + i); + rtems_termios_device_install( + &usart[0], + &atsam_usart_handler, + NULL, + &atsam_usart_instances[i].base + ); + +#if ATSAM_CONSOLE_DEVICE_TYPE == 0 + if (i == ATSAM_CONSOLE_DEVICE_INDEX) { + atsam_usart_instances[i].console = true; + link(&usart[0], CONSOLE_DEVICE_NAME); + } +#endif + } + + for (i = 0; i < RTEMS_ARRAY_SIZE(atsam_uart_instances); ++i) { + char uart[] = "/dev/ttyUARTX"; + + uart[sizeof(uart) - 2] = (char) ('0' + i); + rtems_termios_device_install( + &uart[0], + &atsam_uart_handler, + NULL, + &atsam_uart_instances[i].base + ); + +#if ATSAM_CONSOLE_DEVICE_TYPE == 1 + if (i == ATSAM_CONSOLE_DEVICE_INDEX) { + atsam_uart_instances[i].console = true; + link(&uart[0], CONSOLE_DEVICE_NAME); + } +#endif + } + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/atsam/console/debug-console.c b/bsps/arm/atsam/console/debug-console.c new file mode 100644 index 0000000000..a405fe9665 --- /dev/null +++ b/bsps/arm/atsam/console/debug-console.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/bspIo.h> +#include <rtems/sysinit.h> + +#include <bsp/atsam-clock-config.h> +#include <chip.h> +#include <include/dbg_console.h> + +static void atsam_debug_console_out(char c) +{ + DBG_PutChar((uint8_t) c); +} + +static void atsam_debug_console_init(void) +{ + DBG_Configure(115200, BOARD_MCK); + BSP_output_char = atsam_debug_console_out; +} + +static void atsam_debug_console_early_init(char c) +{ + atsam_debug_console_init(); + atsam_debug_console_out(c); +} + +static int atsam_debug_console_in(void) +{ + return (int) DBG_GetChar(); +} + +BSP_output_char_function_type BSP_output_char = atsam_debug_console_early_init; + +BSP_polling_getchar_function_type BSP_poll_char = atsam_debug_console_in; + +RTEMS_SYSINIT_ITEM( + atsam_debug_console_init, + RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_LAST +); diff --git a/bsps/arm/beagle/console/console-config.c b/bsps/arm/beagle/console/console-config.c new file mode 100644 index 0000000000..78af5f6a93 --- /dev/null +++ b/bsps/arm/beagle/console/console-config.c @@ -0,0 +1,152 @@ +/** + * @file + * + * @ingroup arm_beagle + * + * @brief Console configuration. + */ + +/* + * Copyright (c) 2012 Claas Ziemke. All rights reserved. + * + * Claas Ziemke + * Kernerstrasse 11 + * 70182 Stuttgart + * Germany + * <claas.ziemke@gmx.net> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * Modified by Ben Gras <beng@shrike-systems.com> to make + * interrupt-driven uart i/o work for beagleboards; beaglebone support added. + */ + +#include <libchip/serial.h> +#include <libchip/ns16550.h> + +#include <rtems/bspIo.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/uart-output-char.h> + +#define CONSOLE_UART_THR (*(volatile unsigned int *)BSP_CONSOLE_UART_BASE) +#define CONSOLE_UART_RHR (*(volatile unsigned int *)BSP_CONSOLE_UART_BASE) +#define CONSOLE_UART_LSR (*(volatile unsigned int *)(BSP_CONSOLE_UART_BASE+0x14)) +#define CONSOLE_SYSC (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x54)) +#define CONSOLE_SYSS (*(volatile uint32_t *) (BSP_CONSOLE_UART_BASE + 0x58)) + +#define TX_FIFO_E (1<<5) +#define RX_FIFO_E (1<<0) + +static uint8_t beagle_uart_get_register(uintptr_t addr, uint8_t i) +{ + uint8_t v; + volatile uint32_t *reg_r = (volatile uint32_t *) addr + i; + + if(reg_r == (uint32_t*) BSP_CONSOLE_UART_BASE /* reading RHR */ ) { + /* check there should be anything in the RHR before accessing it */ + if(!(CONSOLE_UART_LSR & 0x01)) { + return 0; + } + } + + v = (uint8_t) *reg_r; + + return v; +} + +static void beagle_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val) +{ + volatile uint32_t *reg = (volatile uint32_t *) addr; + + reg [i] = val; +} + +console_tbl Console_Configuration_Ports [] = { + { + .sDeviceName = "/dev/ttyS0", + .deviceType = SERIAL_NS16550, +#if CONSOLE_POLLED /* option to facilitate running the tests */ + .pDeviceFns = &ns16550_fns_polled, +#else + .pDeviceFns = &ns16550_fns, +#endif + .ulMargin = 16, + .ulHysteresis = 8, + .pDeviceParams = (void *) CONSOLE_BAUD, + .ulCtrlPort1 = BSP_CONSOLE_UART_BASE, + .ulDataPort = BSP_CONSOLE_UART_BASE, + .ulIntVector = BSP_CONSOLE_UART_IRQ, + .getRegister = beagle_uart_get_register, + .setRegister = beagle_uart_set_register, + .ulClock = UART_CLOCK, /* 48MHz base clock */ + }, +}; + +unsigned long Console_Configuration_Count = 1; + +static int init_needed = 1; // don't rely on bss being 0 + +static void beagle_console_init(void) +{ + if(init_needed) { + const uint32_t div = UART_CLOCK / 16 / CONSOLE_BAUD; + CONSOLE_SYSC = 2; + while ((CONSOLE_SYSS & 1) == 0) + ; + if ((CONSOLE_LSR & (CONSOLE_LSR_THRE | CONSOLE_LSR_TEMT)) == CONSOLE_LSR_THRE) { + CONSOLE_LCR = 0x83; + CONSOLE_DLL = div; + CONSOLE_DLM = (div >> 8) & 0xff; + CONSOLE_LCR = 0x03; + CONSOLE_ACR = 0x00; + } + + while ((CONSOLE_LSR & CONSOLE_LSR_TEMT) == 0) + ; + + CONSOLE_LCR = 0x80 | 0x03; + CONSOLE_DLL = 0x00; + CONSOLE_DLM = 0x00; + CONSOLE_LCR = 0x03; + CONSOLE_MCR = 0x03; + CONSOLE_FCR = 0x07; + CONSOLE_LCR = 0x83; + CONSOLE_DLL = div; + CONSOLE_DLM = (div >> 8) & 0xff; + CONSOLE_LCR = 0x03; + CONSOLE_ACR = 0x00; + init_needed = 0; + } +} + +#define CONSOLE_THR8 (*(volatile uint8_t *) (BSP_CONSOLE_UART_BASE + 0x00)) + +static void uart_write_polled( char c ) +{ + if(init_needed) beagle_console_init(); + + while( ( CONSOLE_LSR & TX_FIFO_E ) == 0 ) + ; + CONSOLE_THR8 = c; +} + +static void _BSP_put_char( char c ) { + uart_write_polled( c ); +} + +static int _BSP_get_char(void) +{ + if ((CONSOLE_LSR & CONSOLE_LSR_RDR) != 0) { + return CONSOLE_RBR; + } else { + return -1; + } +} + +BSP_output_char_function_type BSP_output_char = _BSP_put_char; + +BSP_polling_getchar_function_type BSP_poll_char = _BSP_get_char; diff --git a/bsps/arm/csb336/console/uart.c b/bsps/arm/csb336/console/uart.c new file mode 100644 index 0000000000..8d8a0c1ed0 --- /dev/null +++ b/bsps/arm/csb336/console/uart.c @@ -0,0 +1,476 @@ +/* + * Console driver for MC9328XML UARTs. + * + * Written Jay Monkman <jtm@lopingdog.com> + * Copyright (c) 2005 by Loping Dog Embedded Systems + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license + */ +#include <bsp.h> +#include <rtems/libio.h> +#include <libchip/sersupp.h> +#include <rtems/error.h> +#include <rtems/bspIo.h> +#include <assert.h> +#include <termios.h> +#include <rtems/irq.h> +#include <bsp/irq.h> +#include <mc9328mxl.h> +#include <rtems/console.h> +#include <inttypes.h> + +/* Define this to use interrupt driver UART driver */ +#define USE_INTERRUPTS 1 + +/* How many serial ports? */ +#define NUM_DEVS 2 +#define poll_write(c) imx_uart_poll_write_char(0, c) +#define poll_read() imx_uart_poll_read_char(0) + +static int imx_uart_first_open(int, int, void *); +static int imx_uart_last_close(int, int, void *); +static int imx_uart_poll_read(int); +static int imx_uart_set_attrs(int, const struct termios *); +static void imx_uart_init(int minor); +static void imx_uart_set_baud(int, int); +static ssize_t imx_uart_poll_write(int, const char *, size_t); +static int imx_uart_poll_read_char(int minor); +static void imx_uart_poll_write_char(int minor, char c); +static void _BSP_output_char(char c); +static int _BSP_poll_char(void); + +#if USE_INTERRUPTS +static void imx_uart_tx_isr(void *); +static void imx_uart_rx_isr(void *); +static void imx_uart_isr_on(rtems_vector_number); +static void imx_uart_isr_off(rtems_vector_number); +static ssize_t imx_uart_intr_write(int, const char *, size_t); +static rtems_vector_number imx_uart_name_transmit(int minor); +static rtems_vector_number imx_uart_name_receive(int minor); +#endif + +/* TERMIOS callbacks */ +#if USE_INTERRUPTS +rtems_termios_callbacks imx_uart_cbacks = { + .firstOpen = imx_uart_first_open, + .lastClose = imx_uart_last_close, + .pollRead = NULL, + .write = imx_uart_intr_write, + .setAttributes = imx_uart_set_attrs, + .stopRemoteTx = NULL, + .startRemoteTx = NULL, + .outputUsesInterrupts = 1, +}; +#else +rtems_termios_callbacks imx_uart_cbacks = { + .firstOpen = imx_uart_first_open, + .lastClose = imx_uart_last_close, + .pollRead = imx_uart_poll_read, + .write = imx_uart_poll_write, + .setAttributes = imx_uart_set_attrs, + .stopRemoteTx = NULL, + .startRemoteTx = NULL, + .outputUsesInterrupts = 0, +}; +#endif + +typedef struct { + int minor; + mc9328mxl_uart_regs_t * regs; + volatile const char *buf; + volatile int len; + volatile int idx; + void *tty; +} imx_uart_data_t; + +static imx_uart_data_t imx_uart_data[NUM_DEVS]; + +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + int i; + + for (i = 0; i < NUM_DEVS; i++) { + imx_uart_init(i); + } + + rtems_termios_initialize(); + + /* /dev/console and /dev/tty0 are the same */ + status = rtems_io_register_name("/dev/console", major, 0); + if (status != RTEMS_SUCCESSFUL) { + rtems_panic("%s:%d Error registering /dev/console :: %d\n", + __FUNCTION__, __LINE__, status); + } + + status = rtems_io_register_name("/dev/tty0", major, 0); + if (status != RTEMS_SUCCESSFUL) { + rtems_panic("%s:%d Error registering /dev/tty0 :: %d\n", + __FUNCTION__, __LINE__, status); + } + + status = rtems_io_register_name("/dev/tty1", major, 1); + if (status != RTEMS_SUCCESSFUL) { + rtems_panic("%s:%d Error registering /dev/tty1 :: %d\n", + __FUNCTION__, __LINE__, status); + } + return RTEMS_SUCCESSFUL; +} + +rtems_device_driver console_open( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + rtems_status_code rc; + + if (minor > (NUM_DEVS - 1)) { + return RTEMS_INVALID_NUMBER; + } + + rc = rtems_termios_open(major, minor, arg, &imx_uart_cbacks); + + return rc; +} + +rtems_device_driver console_close( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_close(arg); +} + +rtems_device_driver console_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_read(arg); +} + +rtems_device_driver console_write( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_write(arg); +} + +rtems_device_driver console_control( + rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return rtems_termios_ioctl(arg); +} + +static void imx_uart_init(int minor) +{ + imx_uart_data[minor].minor = minor; + imx_uart_data[minor].buf = NULL; + imx_uart_data[minor].len = 0; + imx_uart_data[minor].idx = 0; + + if (minor == 0) { + imx_uart_data[minor].regs = + (mc9328mxl_uart_regs_t *) MC9328MXL_UART1_BASE; + } else if (minor == 1) { + imx_uart_data[minor].regs = + (mc9328mxl_uart_regs_t *) MC9328MXL_UART2_BASE; + } else { + rtems_panic("%s:%d Unknown UART minor number %d\n", + __FUNCTION__, __LINE__, minor); + } + + imx_uart_data[minor].regs->cr1 = ( + MC9328MXL_UART_CR1_UARTCLKEN | + MC9328MXL_UART_CR1_UARTEN); + + imx_uart_data[minor].regs->cr2 = ( + MC9328MXL_UART_CR2_IRTS | + MC9328MXL_UART_CR2_WS | + MC9328MXL_UART_CR2_TXEN | + MC9328MXL_UART_CR2_RXEN | + MC9328MXL_UART_CR2_SRST); + + imx_uart_data[minor].regs->cr3 = 0; + + imx_uart_data[minor].regs->cr4 = 0; + + imx_uart_data[minor].regs->fcr = ( + MC9328MXL_UART_FCR_TXTL(32) | + MC9328MXL_UART_FCR_RFDIV_1 | + MC9328MXL_UART_FCR_RXTL(1)); + + imx_uart_set_baud(minor, 38400); + +} + +static int imx_uart_first_open(int major, int minor, void *arg) +{ + rtems_libio_open_close_args_t *args = arg; + rtems_status_code status = RTEMS_SUCCESSFUL; + + imx_uart_data[minor].tty = args->iop->data1; + +#if USE_INTERRUPTS + status = rtems_interrupt_handler_install( + imx_uart_name_transmit(minor), + "UART", + RTEMS_INTERRUPT_UNIQUE, + imx_uart_tx_isr, + &imx_uart_data[minor] + ); + assert(status == RTEMS_SUCCESSFUL); + imx_uart_isr_on(imx_uart_name_transmit(minor)); + + status = rtems_interrupt_handler_install( + imx_uart_name_receive(minor), + "UART", + RTEMS_INTERRUPT_UNIQUE, + imx_uart_rx_isr, + &imx_uart_data[minor] + ); + assert(status == RTEMS_SUCCESSFUL); + imx_uart_isr_on(imx_uart_name_receive(minor)); + + imx_uart_data[minor].regs->cr1 |= MC9328MXL_UART_CR1_RRDYEN; +#endif + + return 0; +} + +static int imx_uart_last_close(int major, int minor, void *arg) +{ +#if USE_INTERRUPTS + rtems_status_code status = RTEMS_SUCCESSFUL; + + imx_uart_isr_off(imx_uart_name_transmit(minor)); + status = rtems_interrupt_handler_remove( + imx_uart_name_transmit(minor), + imx_uart_tx_isr, + &imx_uart_data[minor] + ); + assert(status == RTEMS_SUCCESSFUL); + + imx_uart_isr_off(imx_uart_name_receive(minor)); + status = rtems_interrupt_handler_remove( + imx_uart_name_receive(minor), + imx_uart_rx_isr, + &imx_uart_data[minor] + ); + assert(status == RTEMS_SUCCESSFUL); +#endif + + return 0; +} + +static int imx_uart_poll_read(int minor) +{ + if (imx_uart_data[minor].regs->sr2 & MC9328MXL_UART_SR2_RDR) { + return imx_uart_data[minor].regs->rxd & 0xff; + } else { + return -1; + } +} + + +static ssize_t imx_uart_poll_write(int minor, const char *buf, size_t len) +{ + int i; + for (i = 0; i < len; i++) { + /* Wait for there to be room in the fifo */ + while (!(imx_uart_data[minor].regs->sr2 & MC9328MXL_UART_SR2_TXDC)) { + continue; + } + + imx_uart_data[minor].regs->txd = buf[i]; + } + return 1; + +} + +#if USE_INTERRUPTS +static ssize_t imx_uart_intr_write(int minor, const char *buf, size_t len) +{ + if (len > 0) { + imx_uart_data[minor].buf = buf; + imx_uart_data[minor].len = len; + imx_uart_data[minor].idx = 0; + + imx_uart_data[minor].regs->cr1 |= MC9328MXL_UART_CR1_TXMPTYEN; + } + + return 1; +} +#endif + + +/* This is for setting baud rate, bits, etc. */ +static int imx_uart_set_attrs(int minor, const struct termios *t) +{ + int baud; + + baud = rtems_termios_baud_to_number(t->c_ospeed); + imx_uart_set_baud(minor, baud); + + return 0; +} + +#if USE_INTERRUPTS +static void imx_uart_isr_on(rtems_vector_number name) +{ + MC9328MXL_AITC_INTENNUM = name; +} +static void imx_uart_isr_off(rtems_vector_number name) +{ + MC9328MXL_AITC_INTDISNUM = name; +} + +static void imx_uart_rx_isr(void * param) +{ + imx_uart_data_t *uart_data = param; + char buf[32]; + int i=0; + + while (uart_data->regs->sr2 & MC9328MXL_UART_SR2_RDR) { + buf[i] = uart_data->regs->rxd & 0xff; + i++; + } + + rtems_termios_enqueue_raw_characters(uart_data->tty, buf, i); +} + +static void imx_uart_tx_isr(void * param) +{ + imx_uart_data_t *uart_data = param; + int len; + int minor = uart_data->minor; + + + if (uart_data->idx < uart_data->len) { + while ( (uart_data->regs->sr1 & MC9328MXL_UART_SR1_TRDY) && + (uart_data->idx < uart_data->len)) { + uart_data->regs->txd = uart_data->buf[uart_data->idx]; + uart_data->idx++; + } + } else { + len = uart_data->len; + uart_data->len = 0; + imx_uart_data[minor].regs->cr1 &= ~MC9328MXL_UART_CR1_TXMPTYEN; + rtems_termios_dequeue_characters(uart_data->tty, len); + } +} + +static rtems_vector_number imx_uart_name_transmit(int minor) +{ + if (minor == 0) { + return BSP_INT_UART1_TX; + } else if (minor == 1) { + return BSP_INT_UART2_TX; + } + + assert(0); +} + +static rtems_vector_number imx_uart_name_receive(int minor) +{ + if (minor == 0) { + return BSP_INT_UART1_RX; + } else if (minor == 1) { + return BSP_INT_UART2_RX; + } + + assert(0); +} +#endif + +/* + * Set the UART's baud rate. The calculation is: + * (baud * 16) / ref_freq = num/demom + * + * ref_freq = perclk1 / RFDIV[2:0] + * BIR = num - 1 + * BMR = demom - 1 + * + * Setting 'num' to 16 yields this equation: + * demom = ref_freq / baud + */ +static void imx_uart_set_baud(int minor, int baud) +{ + unsigned int perclk1; + unsigned int denom; + unsigned int ref_freq = 0; + uint32_t fcr; + + perclk1 = get_perclk1_freq(); + fcr = imx_uart_data[minor].regs->fcr; + + switch(fcr & MC9328MXL_UART_FCR_RFDIV_MASK) { + case MC9328MXL_UART_FCR_RFDIV_1: ref_freq = perclk1/1; break; + case MC9328MXL_UART_FCR_RFDIV_2: ref_freq = perclk1/2; break; + case MC9328MXL_UART_FCR_RFDIV_3: ref_freq = perclk1/3; break; + case MC9328MXL_UART_FCR_RFDIV_4: ref_freq = perclk1/4; break; + case MC9328MXL_UART_FCR_RFDIV_5: ref_freq = perclk1/5; break; + case MC9328MXL_UART_FCR_RFDIV_6: ref_freq = perclk1/6; break; + case MC9328MXL_UART_FCR_RFDIV_7: ref_freq = perclk1/7; break; + default: + rtems_panic("%s:%d Unknown RFDIV: 0x%" PRIx32, + __FUNCTION__, __LINE__, + fcr & MC9328MXL_UART_FCR_RFDIV_MASK); + break; + } + + denom = ref_freq / baud; + + imx_uart_data[minor].regs->bir = 0xf; + imx_uart_data[minor].regs->bmr = denom; +} + + +/* + * Polled, non-blocking read from UART + */ +static int imx_uart_poll_read_char(int minor) +{ + return imx_uart_poll_read(minor); +} + +/* + * Polled, blocking write from UART + */ +static void imx_uart_poll_write_char(int minor, char c) +{ + imx_uart_poll_write(minor, &c, 1); +} + +/* + * Functions for printk() and friends. + */ +static void _BSP_output_char(char c) +{ + poll_write(c); +} + +BSP_output_char_function_type BSP_output_char = _BSP_output_char; + +static int _BSP_poll_char(void) +{ + return poll_read(); +} + +BSP_polling_getchar_function_type BSP_poll_char = _BSP_poll_char; + + diff --git a/bsps/arm/csb337/console/dbgu.c b/bsps/arm/csb337/console/dbgu.c new file mode 100644 index 0000000000..1a16762e32 --- /dev/null +++ b/bsps/arm/csb337/console/dbgu.c @@ -0,0 +1,223 @@ +/* + * Console driver for AT91RM9200 DBGU port + * + * This driver uses the shared console driver in + * ...../libbsp/shared/console.c + * + * Copyright (c) 2003 by Cogent Computer Systems + * Written by Mike Kelly <mike@cogcomp.com> + * and Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ +#include <bsp.h> +#include <rtems/libio.h> +#include <termios.h> + +#include <at91rm9200.h> +#include <at91rm9200_dbgu.h> +#include <at91rm9200_pmc.h> +#include <rtems/bspIo.h> +#include <libchip/serial.h> +#include <libchip/sersupp.h> + +volatile int dbg_dly; + +/* static function prototypes */ +static int dbgu_first_open(int major, int minor, void *arg); +static int dbgu_last_close(int major, int minor, void *arg); +static int dbgu_read(int minor); +static ssize_t dbgu_write(int minor, const char *buf, size_t len); +static void dbgu_init(int minor); +static void dbgu_write_polled(int minor, char c); +static int dbgu_set_attributes(int minor, const struct termios *t); + +/* Pointers to functions for handling the UART. */ +const console_fns dbgu_fns = +{ + libchip_serial_default_probe, + dbgu_first_open, + dbgu_last_close, + dbgu_read, + dbgu_write, + dbgu_init, + dbgu_write_polled, /* not used in this driver */ + dbgu_set_attributes, + FALSE /* TRUE if interrupt driven, FALSE if not. */ +}; +/*********************************************************************/ +/* Functions called via callbacks (i.e. the ones in uart_fns */ +/*********************************************************************/ + +/* + * This is called the first time each device is opened. Since + * the driver is polled, we don't have to do anything. If the driver + * were interrupt driven, we'd enable interrupts here. + */ +static int dbgu_first_open(int major, int minor, void *arg) +{ + return 0; +} + + +/* + * This is called the last time each device is closed. Since + * the driver is polled, we don't have to do anything. If the driver + * were interrupt driven, we'd disable interrupts here. + */ +static int dbgu_last_close(int major, int minor, void *arg) +{ + return 0; +} + + +/* + * Read one character from UART. + * + * return -1 if there's no data, otherwise return + * the character in lowest 8 bits of returned int. + */ +static int dbgu_read(int minor) +{ + char c; + console_tbl *console_entry; + at91rm9200_dbgu_regs_t *dbgu; + + console_entry = BSP_get_uart_from_minor(minor); + + if (console_entry == NULL) { + return -1; + } + + dbgu = (at91rm9200_dbgu_regs_t *)console_entry->ulCtrlPort1; + + if (!(dbgu->sr & DBGU_INT_RXRDY)) { + return -1; + } + + c = dbgu->rhr & 0xff; + + return c; +} + + +/* + * Write buffer to UART + * + * return 1 on success, -1 on error + */ +static ssize_t dbgu_write(int minor, const char *buf, size_t len) +{ + int i, x; + char c; + console_tbl *console_entry; + at91rm9200_dbgu_regs_t *dbgu; + + console_entry = BSP_get_uart_from_minor(minor); + + if (console_entry == NULL) { + return -1; + } + + dbgu = (at91rm9200_dbgu_regs_t *)console_entry->ulCtrlPort1; + + for (i = 0; i < len; i++) { + /* Wait for fifo to have room */ + while(1) { + if (dbgu->sr & DBGU_INT_TXRDY) { + break; + } + } + + c = (char) buf[i]; + dbgu->thr = c; + + /* the TXRDY flag does not seem to update right away (is this true?) */ + /* so we wait a bit before continuing */ + for (x = 0; x < 100; x++) { + dbg_dly++; /* using a global so this doesn't get optimized out */ + } + } + + return 1; +} + + +/* Set up the UART. */ +static void dbgu_init(int minor) +{ + console_tbl *console_entry; + at91rm9200_dbgu_regs_t *dbgu; + + console_entry = BSP_get_uart_from_minor(minor); + + if (console_entry == NULL) { + return; + } + + dbgu = (at91rm9200_dbgu_regs_t *)console_entry->ulCtrlPort1; + + /* Clear error bits, and reset */ + dbgu->cr = (DBGU_CR_RSTSTA | DBGU_CR_RSTTX | DBGU_CR_RSTRX); + + /* Clear pending interrupts */ + dbgu->idr = DBGU_INT_ALL; + dbgu->imr = 0; + + /* Set port to no parity, no loopback */ + dbgu->mr = DBGU_MR_PAR_NONE | DBGU_MR_CHMODE_NORM; + + /* Set the baud rate */ + dbgu->brgr = (at91rm9200_get_mck() / 16) / BSP_get_baud(); + + /* Enable the DBGU */ + dbgu->cr = (DBGU_CR_TXEN | DBGU_CR_RXEN); +} + +/* This is used for getchark support */ +static void dbgu_write_polled(int minor, char c) +{ + dbgu_write(minor, &c, 1); +} + +/* This is for setting baud rate, bits, etc. */ +static int dbgu_set_attributes(int minor, const struct termios *t) +{ + return 0; +} + +/***********************************************************************/ +/* + * The following functions are not used by TERMIOS, but other RTEMS + * functions use them instead. + */ +/***********************************************************************/ +/* + * Read from UART. This is used in the exit code, and can't + * rely on interrupts. + */ +static int dbgu_poll_read(int minor) +{ + return dbgu_read(minor); +} + + +/* + * Write a character to the console. This is used by printk() and + * maybe other low level functions. It should not use interrupts or any + * RTEMS system calls. It needs to be very simple + */ +static void _BSP_put_char( char c ) { + dbgu_write_polled(0, c); +} + +BSP_output_char_function_type BSP_output_char = _BSP_put_char; + +static int _BSP_poll_char(void) +{ + return dbgu_poll_read(0); +} + +BSP_polling_getchar_function_type BSP_poll_char = _BSP_poll_char; diff --git a/bsps/arm/csb337/console/fbcons.c b/bsps/arm/csb337/console/fbcons.c new file mode 100644 index 0000000000..62e840938d --- /dev/null +++ b/bsps/arm/csb337/console/fbcons.c @@ -0,0 +1,125 @@ +/* + * LCD Console Output Driver for CSBx37 + */ + +/* + * COPYRIGHT (c) 1989-2014. + * On-Line Applications Research Corporation (OAR). + * + * Modified by Fernando Nicodemos <fgnicodemos@terra.com.br> + * from NCB - Sistemas Embarcados Ltda. (Brazil) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <rtems/libio.h> +#include <termios.h> + +#include <rtems/bspIo.h> +#include <libchip/serial.h> +#include <libchip/sersupp.h> +#include "sed1356.h" + +/* static function prototypes */ +static int fbcons_first_open(int major, int minor, void *arg); +static int fbcons_last_close(int major, int minor, void *arg); +static int fbcons_read(int minor); +static ssize_t fbcons_write(int minor, const char *buf, size_t len); +static void fbcons_init(int minor); +static void fbcons_write_polled(int minor, char c); +static int fbcons_set_attributes(int minor, const struct termios *t); + +/* Pointers to functions for handling the UART. */ +const console_fns fbcons_fns = +{ + libchip_serial_default_probe, + fbcons_first_open, + fbcons_last_close, + fbcons_read, + fbcons_write, + fbcons_init, + fbcons_write_polled, /* not used in this driver */ + fbcons_set_attributes, + FALSE /* TRUE if interrupt driven, FALSE if not. */ +}; +/*********************************************************************/ +/* Functions called via callbacks (i.e. the ones in uart_fns */ +/*********************************************************************/ + +/* + * This is called the first time each device is opened. Since + * the driver is polled, we don't have to do anything. If the driver + * were interrupt driven, we'd enable interrupts here. + */ +static int fbcons_first_open(int major, int minor, void *arg) +{ + /* printk( "Frame buffer -- first open\n" ); */ + return 0; +} + + +/* + * This is called the last time each device is closed. Since + * the driver is polled, we don't have to do anything. If the driver + * were interrupt driven, we'd disable interrupts here. + */ +static int fbcons_last_close(int major, int minor, void *arg) +{ + /* printk( "Frame buffer -- last close\n" ); */ + return 0; +} + + +/* + * Read one character from UART. + * + * return -1 if there's no data, otherwise return + * the character in lowest 8 bits of returned int. + */ +static int fbcons_read(int minor) +{ + /* printk( "Frame buffer -- read\n" ); */ + return -1; +} + + +/* + * Write buffer to LCD + * + * return 1 on success, -1 on error + */ +static ssize_t fbcons_write(int minor, const char *buf, size_t len) +{ + int i; + + /* printk( "Frame buffer -- write\n" ); */ + for ( i=0 ; i<len ; i++ ) + sed_putchar( buf[i] ); + + return 1; +} + + +/* Set up the LCD controller. */ +static void fbcons_init(int minor) +{ + /* printk( "Initializing frame buffer\n" ); */ + sed_init(); +} + +/* This is used for putchark support */ +static void fbcons_write_polled(int minor, char c) +{ + /* printk( "frame buffer -- write polled\n" ); */ + sed_putchar( c ); +} + +/* This is for setting baud rate, bits, etc. */ +static int fbcons_set_attributes(int minor, const struct termios *t) +{ + /* printk( "frame buffer -- set attributes\n" ); */ + return 0; +} diff --git a/bsps/arm/csb337/console/sed1356.c b/bsps/arm/csb337/console/sed1356.c new file mode 100644 index 0000000000..f87a322a01 --- /dev/null +++ b/bsps/arm/csb337/console/sed1356.c @@ -0,0 +1,461 @@ +/* + * SED1356 Support for KIT637_V6 (CSB637) + * + * Based upon code from MicroMonitor 1.17 from http://www.umonfw.com/ + * which includes this notice: + */ + +/* + ************************************************************************** + * General notice: + * This code is part of a boot-monitor package developed as a generic base + * platform for embedded system designs. As such, it is likely to be + * distributed to various projects beyond the control of the original + * author. Please notify the author of any enhancements made or bugs found + * so that all may benefit from the changes. In addition, notification back + * to the author will allow the new user to pick up changes that may have + * been made by other users after this version of the code was distributed. + * + * Note1: the majority of this code was edited with 4-space tabs. + * Note2: as more and more contributions are accepted, the term "author" + * is becoming a mis-representation of credit. + * + * Original author: Ed Sutter + * Email: esutter@alcatel-lucent.com + * Phone: 908-582-2351 + ************************************************************************** + * + * Ed Sutter has been informed that this code is being used in RTEMS. + * + * This code was reformatted by Joel Sherrill from OAR Corporation and + * Fernando Nicodemos <fgnicodemos@terra.com.br> from NCB - Sistemas + * Embarcados Ltda. (Brazil) to be more compliant with RTEMS coding + * standards and to eliminate C++ style comments. + */ + +#include <bsp.h> + +#include <stdlib.h> +#include <stdio.h> +#include "sed1356.h" +#include "font8x16.h" + +int mode900lq; +long PIXELS_PER_ROW; +long PIXELS_PER_COL; +long COLS_PER_SCREEN; +long ROWS_PER_SCREEN; +long SED_HOR_PULSE_WIDTH_LCD; +long SED_VER_PULSE_START_LCD; +long SED_HOR_PULSE_START_LCD; +long SED_HOR_NONDISP_LCD; +long SED_VER_NONDISP_LCD; +long SED_VER_PULSE_WIDTH_LCD; + +/* globals to keep track of foreground, background colors and x,y position */ +int sed_color_depth; /* 4, 8 or 16 */ +int sed_fg_color; /* 0 to 15, used as lookup into VGA color table */ +int sed_bg_color; /* 0 to 15, used as lookup into VGA color table */ +int sed_col; /* current column, 0 to COLS_PER_SCREEN - 1 */ +int sed_row; /* current row, 0 to (ROWS_PER_SCREEN * 2) - 1 */ +int sed_disp_mode_crt; /* CRT=1, LCD=0 */ +int sed135x_ok; +int sed135x_tst; +uint32_t sed_fb_offset; /* current offset into frame buffer for sed_putchar */ + +void sed_writechar(uint8_t c); +void sed_scroll(void); + +#define SED_REG_BASE 0x30000000 /* *CS2 */ +#define SED_MEM_BASE (SED_REG_BASE + 0x00200000) +#define SED_STEP 1 /* 16-bit port on 16-bit boundry */ + +#define SED_REG16(_x_) *(volatile uint16_t *)((uint32_t)SED_REG_BASE + (((uint32_t)_x_ * SED_STEP) ^ 0)) /* Control/Status Registers, 16-bit mode */ +#define RD_FB16(_reg_,_val_) ((_val_) = *((volatile uint16_t *)(((uint32_t)SED_MEM_BASE + ((uint32_t)(_reg_ * SED_STEP) ^ 0))))) +#define WR_FB16(_reg_,_val_) (*((volatile uint16_t *)(((uint32_t)SED_MEM_BASE + ((uint32_t)(_reg_ * SED_STEP) ^ 0)))) = (_val_)) + +#if 0 +#define SED1356_REG_LCD_HOR_DISP SED_REG16(0x32) +#define SED1356_REG_LCD_HOR_NONDISP_and_START SED_REG16(0x34) +#define SED1356_REG_LCD_HOR_PULSE SED_REG16(0x36) +#define SED1356_REG_LCD_VER_DISP_HT_LO_and_HI SED_REG16(0x38) +#define SED1356_REG_LCD_VER_NONDISP_and_START SED_REG16(0x3a) +#define SED1356_REG_LCD_VER_PULSE SED_REG16(0x3c) +#define SED1356_REG_LCD_DISP_MODE_and_MISC SED_REG16(0x40) +#define SED1356_REG_LCD_DISP_START_LO_and_MID SED_REG16(0x42) +#define SED1356_REG_LCD_DISP_START_HI SED_REG16(0x44) +#define SED1356_REG_LCD_ADD_OFFSET_LO_and_HI SED_REG16(0x46) +#define SED1356_REG_LCD_PIXEL_PAN SED_REG16(0x48) +#define SED1356_REG_LCD_FIFO_THRESH_LO_and_HI SED_REG16(0x4a) +#endif + + +#define H2SED(_x_) (_x_) + +#define FB_SIZE (640 * 480) +#define SED_ROW_SIZE(_depth_) ((PIXELS_PER_ROW * _depth_) / 8) +#define SED_FB_SIZE(_depth_) (((PIXELS_PER_COL * PIXELS_PER_ROW) * _depth_) / 8) + +#define FONT_WIDTH 8 +#define FONT_HEIGHT 16 + +#define SED_GET_ADD(_row_, _col_, _depth_) \ + (((((_row_ * PIXELS_PER_ROW) * FONT_HEIGHT) \ + + (_col_ * FONT_WIDTH)) \ + * _depth_) / 8) + + +#define SED_GET_PHYS_ADD(_reg_) \ + (volatile unsigned long)(SED_MEM_BASE + ((_reg_ * SED_STEP) ^ 0)) + + +#include "sed1356_16bit.h" + +/* #define SED_DBG */ +int sed135x_tst = 0; + +void sed_write_frame_buffer( + uint32_t i, + uint16_t wr16 +) +{ + WR_FB16(i, wr16); +} + +int sed_frame_buffer_size(void) +{ + return SED_FB_SIZE(sed_color_depth); +} + +void sed_clr_row(int char_row) +{ + unsigned long sed_mem_add; + int i; + uint16_t wr16; + + /* clear the desired row */ + sed_mem_add = SED_GET_ADD(char_row, 0, sed_color_depth); + +#ifdef SED_DBG + sed135x_tst = 1; + printf("SED Clear Row %d, FB Add 0x%08lx, CPU Add 0x%08lx.\n ", char_row, sed_mem_add, SED_GET_PHYS_ADD(sed_mem_add)); + sed135x_tst = 0; +#endif + + switch (sed_color_depth) + { + case 4: + wr16 = ((sed_bg_color << 12) | (sed_bg_color << 8) | (sed_bg_color << 4) | (sed_bg_color << 0)); +#ifdef SED_DBG + sed135x_tst = 1; + printf("SED Clear Row %d, FB Add 0x%08lx to 0x%08lx.\n ", char_row, sed_mem_add, sed_mem_add + ((PIXELS_PER_ROW * FONT_HEIGHT) / 2)); + sed135x_tst = 0; +#endif + for (i = 0; i < ((PIXELS_PER_ROW * FONT_HEIGHT) / 2); i += 2){ + WR_FB16(sed_mem_add, wr16); + sed_mem_add += 2; + } /* for font_row */ + break; + case 8: + wr16 = ((sed_bg_color << 8) | (sed_bg_color << 0)); + for (i = 0; i < (PIXELS_PER_ROW * FONT_HEIGHT); i += 2){ + WR_FB16(sed_mem_add, wr16); + sed_mem_add += 2; + } /* for font_row */ + break; + case 16: + wr16 = ((vga_lookup[sed_bg_color])); + for (i = 0; i < ((PIXELS_PER_ROW * FONT_HEIGHT) * 2); i += 2){ + WR_FB16(sed_mem_add, wr16); + sed_mem_add += 2; + } /* for font_row */ + break; + } /* switch sed_color_depth */ +} /* sed_clr_row */ + +void sed_init(void) +{ + mode900lq = 0; + PIXELS_PER_ROW = 640; + PIXELS_PER_COL = 480; + COLS_PER_SCREEN = 80; + ROWS_PER_SCREEN = 30; + SED_HOR_PULSE_WIDTH_LCD = 0x0b; + SED_HOR_NONDISP_LCD = 0x13; + SED_VER_PULSE_WIDTH_LCD = 0x01; + SED_VER_PULSE_START_LCD = 0x09; + SED_VER_NONDISP_LCD = 0x2c; + + sed_color_depth = 16; /* 16 => vga lookup */ + sed_fg_color = 14; /* Bright Yellow */ + sed_bg_color = 1; /* Blue */ + sed_disp_mode_crt = 0; /* default to LCD */ + sed_fb_offset = 0x00; + sed_row = 0; + sed_col = 0; + + sed135x_ok = 1; + sed135x_tst = 0; + sed_clearscreen(); +} + +/* + * sed_putchar() + * + * This routine parses the character and calls sed_writechar if it is a + * printable character + */ +void sed_putchar(char c) +{ + + if ((sed135x_ok == 0) || (sed135x_tst == 1)) return; + + /* First parse the character to see if it printable or an + * acceptable control character. + */ + switch (c) { + case '\r': + sed_col = 0; + return; + case '\n': + sed_col = 0; + sed_scroll(); + return; + case '\b': + sed_col--; + if (sed_col < 0) { + sed_row--; + if (sed_row < 0) + sed_row = 0; + sed_col = COLS_PER_SCREEN - 1; + } + c = 0; /* erase the character */ + sed_writechar(c); + break; + default: + if (((uint8_t)c < FIRST_CHAR) || ((uint8_t)c > LAST_CHAR)) + return; /* drop anything we can't print */ + c -= FIRST_CHAR; /* get aligned to the first printable character */ + sed_writechar(c); + /* advance to next column */ + sed_col++; + if (sed_col == COLS_PER_SCREEN) { + sed_col = 0; + sed_scroll(); + } + break; + } + +} /* sed_putchar() */ + +/* + * sed_writechar() + * + * This routine writes the character to the screen at the current cursor + * location. + */ +void sed_writechar(uint8_t c) +{ + uint32_t sed_mem_add; + int font_row, font_col; + uint8_t font_data8; + uint16_t wr16; + + /* Convert the current row,col and color depth values + * into an address + */ + sed_mem_add = SED_GET_ADD(sed_row, sed_col, sed_color_depth); + +#ifdef SED_DBG + sed135x_tst = 1; + printf("SED writechar at row %d, col %d, FB Add 0x%08lx, CPU Add 0x%08lx.\n ", sed_row, sed_col, sed_mem_add, SED_GET_PHYS_ADD(sed_mem_add)); + sed135x_tst = 0; +#endif + + if (FONT_WIDTH == 8) { + switch (sed_color_depth) { + case 4: + /* Now render the font by painting one font row at a time */ + for (font_row = 0; font_row < FONT_HEIGHT; font_row++) { + /* get the font row of data */ + font_data8 = font8x16[(c * FONT_HEIGHT) + font_row]; + + + for (font_col = 0; font_col < 8; font_col += 4) + { + /* get a words worth of pixels */ + wr16 = (((font_data8 & 0x80) ? sed_fg_color << 12 : sed_bg_color << 12) + | ((font_data8 & 0x40) ? sed_fg_color << 8 : sed_bg_color << 8) + | ((font_data8 & 0x20) ? sed_fg_color << 4 : sed_bg_color << 4) + | ((font_data8 & 0x10) ? sed_fg_color << 0 : sed_bg_color << 0)); + font_data8 = font_data8 << 4; + WR_FB16(sed_mem_add, wr16); + /* if we are in the 2nd frame buffer, write to the 1st + * frame buffer also + */ + if (sed_row > (ROWS_PER_SCREEN - 1)) { + WR_FB16((sed_mem_add - SED_FB_SIZE(sed_color_depth)), wr16); + } + sed_mem_add += 2; + } /* for font_col */ + /* go to the next pixel row */ + sed_mem_add += (SED_ROW_SIZE(sed_color_depth) - ((FONT_WIDTH * sed_color_depth) / 8)); + } /* for font_row */ + break; + + case 8: + /* Now render the font by painting one font row at a time */ + for (font_row = 0; font_row < FONT_HEIGHT; font_row++) { + /* get the font row of data */ + font_data8 = font8x16[(c * FONT_HEIGHT) + font_row]; + for (font_col = 0; font_col < 8; font_col += 2) + { + /* get a words worth of pixels */ + wr16 = (((font_data8 & 0x80) ? sed_fg_color << 8 : sed_bg_color << 8) + | ((font_data8 & 0x40) ? sed_fg_color << 0 : sed_bg_color << 0)); + font_data8 = font_data8 << 2; + WR_FB16(sed_mem_add, wr16); + /* if we are in the 2nd frame buffer, write to the 1st + * frame buffer also + */ + if (sed_row > (ROWS_PER_SCREEN - 1)) { + WR_FB16((sed_mem_add - SED_FB_SIZE(sed_color_depth)), wr16); + } + sed_mem_add += 2; + } /* for font_col */ + /* go to the next pixel row */ + sed_mem_add += (SED_ROW_SIZE(sed_color_depth) - ((FONT_WIDTH * sed_color_depth) / 8)); + } /* for font_row */ + break; + + case 16: + /* Now render the font by painting one font row at a time */ + for (font_row = 0; font_row < FONT_HEIGHT; font_row++) { + /* get the font row of data */ + font_data8 = font8x16[(c * FONT_HEIGHT) + font_row]; + for (font_col = 0; font_col < 8; font_col++) + { + /* get a words worth of pixels */ + wr16 = ((font_data8 & 0x80) ? + vga_lookup[sed_fg_color] : vga_lookup[sed_bg_color]); + font_data8 = font_data8 << 1; + WR_FB16(sed_mem_add, wr16); + /* if we are in the 2nd frame buffer, write to the 1st + * frame buffer also. + */ + if (sed_row > (ROWS_PER_SCREEN - 1)) { + WR_FB16((sed_mem_add - SED_FB_SIZE(sed_color_depth)), wr16); + } + sed_mem_add += 2; + } /* for font_col */ + /* go to the next pixel row */ + sed_mem_add += (SED_ROW_SIZE(sed_color_depth) - ((FONT_WIDTH * sed_color_depth) / 8)); + } /* for font_row */ + break; + + } /* switch sed_color depth */ + } /* FONT_WIDTH == 8 */ + else + { + return; + } +} /* sed_writechar() */ + +static void sed_update_fb_offset(void) +{ + /* write the new sed_fb_offset value */ + if (sed_disp_mode_crt) { + /* before we change the address offset, wait for the display to + * go from active to non-active, unless the display is not enabled + */ + if (SED1356_REG_DISP_MODE & H2SED(SED1356_DISP_MODE_CRT)) { /* CRT is on */ + while ((SED1356_REG_CRT_VER_NONDISP_and_START & H2SED(SED1356_VER_NONDISP)) == 0) {} + while ((SED1356_REG_CRT_VER_NONDISP_and_START & H2SED(SED1356_VER_NONDISP)) == 1) {} + } + SED1356_REG_CRT_DISP_START_LO_and_MID = H2SED(((sed_fb_offset & 0x00ffff) >> 0)); + SED1356_REG_CRT_DISP_START_HI = H2SED(((sed_fb_offset & 0x070000) >> 16)); + } + else /* LCD */ + { + if (SED1356_REG_DISP_MODE & H2SED(SED1356_DISP_MODE_LCD)) { /* LCD is on */ + while ((SED1356_REG_LCD_VER_NONDISP_and_START & H2SED(SED1356_VER_NONDISP)) == 0) {} + while ((SED1356_REG_LCD_VER_NONDISP_and_START & H2SED(SED1356_VER_NONDISP)) == 1) {} + } + SED1356_REG_LCD_DISP_START_LO_and_MID = H2SED(((sed_fb_offset & 0x00ffff) >> 0)); + SED1356_REG_LCD_DISP_START_HI = H2SED(((sed_fb_offset & 0x070000) >> 16)); + } +} + +/* sed_scroll() + * + * Because we are most likely running out of FLASH and probably also with + * cache disabled, a brute force memcpy of the whole screen would be very + * slow, even with reduced color depths. Instead, we define a frame buffer + * that is twice the size of our actual display. This does limit us to a + * 1Mbyte active display size, but 640 x 480 @ 16-bits/pixel = 614K so it + * works just fine. 800 x 600 can be had by reducing the color depth to + * 8-bits/pixel and using the look up tables. + * + * With the double buffering, we always write to the first buffer, even + * when the second buffer is active. This allows us to scroll by adjusting + * the starting and ending addresses in the SED135x by one row. When we + * reach the end of our virtual buffer, we reset the starting and ending + * addresses to the first buffer. Note that we can not adjust the SED135x + * registers until it is in vertical retrace. That means we have to wait + * until it is in active display, then goes to non-display, unless the + * screen is blanked, in which case we can update immediately. + */ +void sed_scroll(void) +{ + sed_row++; + + /* clear the new row(s) */ + sed_clr_row(sed_row); + if (sed_row > (ROWS_PER_SCREEN - 1)) { + sed_clr_row(sed_row - ROWS_PER_SCREEN); + } + /* when sed_y_pos is greater than ROWS_PER_SCREEN we just adjust the + * start and end addresses in the SED135x. If it is equal to 2 * + * ROWS_PER_SCREEN, we reset the start and end addresses to SED_MEM_BASE. + */ + if (sed_row > (ROWS_PER_SCREEN - 1)) { + if (sed_row > ((ROWS_PER_SCREEN * 2) - 1)) { + sed_fb_offset = 0x00; + sed_row = 0; + sed_clearscreen(); + } else { + /* calculate the new offset address of the frame buffer in words */ + sed_fb_offset += (SED_GET_ADD(1, 0, sed_color_depth) / 2); + } + sed_update_fb_offset(); + } /* if (sed_row > (ROWS_PER_SCREEN - 1)) */ +} + +void sed_putstring(char *s) +{ + char *p = s; + while (*p) + sed_putchar(*p++); +} + +void sed_clearscreen(void) +{ + int i; + uint16_t wr16; + int bg = sed_bg_color; + int fbsize = sed_frame_buffer_size(); + + /* we double buffer so clear ALL of memory */ + fbsize *= 2; + + /* fill the frame buffer with incrementing color values */ + switch (sed_color_depth){ + case 4: wr16 = bg | bg << 4 | bg << 8 | bg << 12; break; + case 8: wr16 = bg | bg << 8; break; + /* 16-bits bypasses the lookup table */ + default: wr16 = vga_lookup[bg]; break; + } + for (i = 0; i < fbsize; i += 2){ + sed_write_frame_buffer(i, wr16); + } +} diff --git a/bsps/arm/csb337/console/uarts.c b/bsps/arm/csb337/console/uarts.c new file mode 100644 index 0000000000..b705a477b7 --- /dev/null +++ b/bsps/arm/csb337/console/uarts.c @@ -0,0 +1,243 @@ +/* + * Console driver for for KIT637_V6 (CSB637) + * + * This driver uses the shared console driver in + * ...../libbsp/shared/console.c + * + * Copyright (c) 2003 by Cogent Computer Systems + * Written by Jay Monkman <jtm@lopingdog.com> + * + * Modified by Fernando Nicodemos <fgnicodemos@terra.com.br> + * from NCB - Sistemas Embarcados Ltda. (Brazil) + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * Modified and FrameBuffer Console Device Support added by + * Joel Sherrill, 2009. + */ + +#include <bsp.h> +#include <rtems/libio.h> +#include <termios.h> +#include <rtems/bspIo.h> + +#include <at91rm9200.h> +#include <at91rm9200_dbgu.h> +#include <libchip/serial.h> +#include <libchip/sersupp.h> +#include <bspopts.h> + +extern const console_fns dbgu_fns; + +#if ENABLE_LCD + extern const console_fns fbcons_fns; + #define LCD_DEV 1 +#else + #define LCD_DEV 0 +#endif + +#if (ENABLE_UMON && ENABLE_UMON_CONSOLE) + extern const console_fns umoncons_fns; + #define UMON_CONS_DEV 1 +#else + #define UMON_CONS_DEV 0 +#endif + +#if ENABLE_USART0 || ENABLE_USART1 || ENABLE_USART2 || ENABLE_USART3 + extern const console_fns usart_polling_fns; +#endif + +#if ENABLE_USART0 + #define USART0_DEV 1 +#else + #define USART0_DEV 0 +#endif + +#if ENABLE_USART1 + #define USART1_DEV 1 +#else + #define USART1_DEV 0 +#endif + +#if ENABLE_USART2 + #define USART2_DEV 1 +#else + #define USART2_DEV 0 +#endif + +#if ENABLE_USART3 + #define USART3_DEV 1 +#else + #define USART3_DEV 0 +#endif + +#define NUM_DEVS \ + (1 + LCD_DEV + UMON_CONS_DEV + \ + USART0_DEV + USART1_DEV + USART2_DEV + USART3_DEV) + +/* These are used by code in console.c */ +unsigned long Console_Configuration_Count = NUM_DEVS; + +/* + * There's one item in array for each UART. + * + * Some of these fields are marked "NOT USED". They are not used + * by console.c, but may be used by drivers in libchip + * + * when we add other types of UARTS we will need to move this + * structure to a generic uart.c file with only this in it + */ +console_tbl Console_Configuration_Ports[] = { + { + "/dev/com0", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &dbgu_fns, /* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 0, /* ulMargin - NOT USED */ + 0, /* ulHysteresis - NOT USED */ + NULL, /* pDeviceParams */ + DBGU_BASE, /* ulCtrlPort1 - Pointer to DBGU regs */ + 0, /* ulCtrlPort2 - NOT USED */ + 0, /* ulDataPort - NOT USED */ + NULL, /* getRegister - NOT USED */ + NULL, /* setRegister - NOT USED */ + NULL, /* getData - NOT USED */ + NULL, /* setData - NOT USED */ + 0, /* ulClock - NOT USED */ + 0 /* ulIntVector - NOT USED */ + }, +#if ENABLE_LCD + { + "/dev/fbcons", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &fbcons_fns, /* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 0, /* ulMargin - NOT USED */ + 0, /* ulHysteresis - NOT USED */ + NULL, /* pDeviceParams */ + 0, /* ulCtrlPort1 - Pointer to DBGU regs */ + 0, /* ulCtrlPort2 - NOT USED */ + 0, /* ulDataPort - NOT USED */ + NULL, /* getRegister - NOT USED */ + NULL, /* setRegister - NOT USED */ + NULL, /* getData - NOT USED */ + NULL, /* setData - NOT USED */ + 0, /* ulClock - NOT USED */ + 0 /* ulIntVector - NOT USED */ + }, +#endif +#if (ENABLE_UMON && ENABLE_UMON_CONSOLE) + { + "/dev/umon", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &umoncons_fns, /* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 0, /* ulMargin - NOT USED */ + 0, /* ulHysteresis - NOT USED */ + NULL, /* pDeviceParams */ + 0, /* ulCtrlPort1 - Pointer to UMON regs */ + 0, /* ulCtrlPort2 - NOT USED */ + 0, /* ulDataPort - NOT USED */ + NULL, /* getRegister - NOT USED */ + NULL, /* setRegister - NOT USED */ + NULL, /* getData - NOT USED */ + NULL, /* setData - NOT USED */ + 0, /* ulClock - NOT USED */ + 0 /* ulIntVector - NOT USED */ + }, +#endif +#if ENABLE_USART0 + { + "/dev/com1", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &usart_polling_fns,/* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 0, /* ulMargin - NOT USED */ + 0, /* ulHysteresis - NOT USED */ + NULL, /* pDeviceParams */ + USART0_BASE, /* ulCtrlPort1 - Pointer to USART 0 regs */ + 0, /* ulCtrlPort2 - NOT USED */ + 0, /* ulDataPort - NOT USED */ + NULL, /* getRegister - NOT USED */ + NULL, /* setRegister - NOT USED */ + NULL, /* getData - NOT USED */ + NULL, /* setData - NOT USED */ + 0, /* ulClock - NOT USED */ + 0 /* ulIntVector - NOT USED */ + }, +#endif +#if ENABLE_USART1 + { + "/dev/com2", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &usart_polling_fns,/* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 0, /* ulMargin - NOT USED */ + 0, /* ulHysteresis - NOT USED */ + NULL, /* pDeviceParams */ + USART1_BASE, /* ulCtrlPort1 - Pointer to USART 1 regs */ + 0, /* ulCtrlPort2 - NOT USED */ + 0, /* ulDataPort - NOT USED */ + NULL, /* getRegister - NOT USED */ + NULL, /* setRegister - NOT USED */ + NULL, /* getData - NOT USED */ + NULL, /* setData - NOT USED */ + 0, /* ulClock - NOT USED */ + 0 /* ulIntVector - NOT USED */ + }, +#endif +#if ENABLE_USART2 + { + "/dev/com3", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &usart_polling_fns,/* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 0, /* ulMargin - NOT USED */ + 0, /* ulHysteresis - NOT USED */ + NULL, /* pDeviceParams */ + USART2_BASE, /* ulCtrlPort1 - Pointer to USART 2 regs */ + 0, /* ulCtrlPort2 - NOT USED */ + 0, /* ulDataPort - NOT USED */ + NULL, /* getRegister - NOT USED */ + NULL, /* setRegister - NOT USED */ + NULL, /* getData - NOT USED */ + NULL, /* setData - NOT USED */ + 0, /* ulClock - NOT USED */ + 0 /* ulIntVector - NOT USED */ + }, +#endif +#if ENABLE_USART3 + { + "/dev/com4", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &usart_polling_fns,/* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 0, /* ulMargin - NOT USED */ + 0, /* ulHysteresis - NOT USED */ + NULL, /* pDeviceParams */ + USART3_BASE, /* ulCtrlPort1 - Pointer to USART 3 regs */ + 0, /* ulCtrlPort2 - NOT USED */ + 0, /* ulDataPort - NOT USED */ + NULL, /* getRegister - NOT USED */ + NULL, /* setRegister - NOT USED */ + NULL, /* getData - NOT USED */ + NULL, /* setData - NOT USED */ + 0, /* ulClock - NOT USED */ + 0 /* ulIntVector - NOT USED */ + } +#endif +}; + +console_tbl *BSP_get_uart_from_minor(int minor) +{ + return Console_Port_Tbl[minor]; +} diff --git a/bsps/arm/csb337/console/usart.c b/bsps/arm/csb337/console/usart.c new file mode 100644 index 0000000000..23b877ce64 --- /dev/null +++ b/bsps/arm/csb337/console/usart.c @@ -0,0 +1,261 @@ +/* + * Driver for AT91RM9200 USART ports + */ + +/* + * COPYRIGHT (c) 2006-2009. + * NCB - Sistemas Embarcados Ltda. (Brazil) + * Fernando Nicodemos <fgnicodemos@terra.com.br> + * + * and + * + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. +*/ + +#include <bsp.h> +#include <rtems/libio.h> +#include <termios.h> + +#include <at91rm9200.h> +#include <at91rm9200_usart.h> +#include <at91rm9200_pmc.h> +#include <rtems/bspIo.h> +#include <libchip/serial.h> +#include <libchip/sersupp.h> + +/* static function prototypes */ +static int usart_first_open(int major, int minor, void *arg); +static int usart_last_close(int major, int minor, void *arg); +static int usart_read_polled(int minor); +static ssize_t usart_write_polled_support(int minor, const char *buf, size_t len); +static void usart_init(int minor); +static void usart_write_polled(int minor, char c); +static int usart_set_attributes(int minor, const struct termios *t); +at91rm9200_usart_regs_t *usart_get_base(int minor); + +/* Pointers to functions for handling the UART polled. */ +const console_fns usart_polling_fns = { + libchip_serial_default_probe, /* deviceProbe */ + usart_first_open, /* deviceFirstOpen */ + usart_last_close, /* deviceLastClose */ + usart_read_polled, /* deviceRead */ + usart_write_polled_support, /* deviceWrite */ + usart_init, /* deviceInitialize */ + usart_write_polled, /* deviceWritePolled */ + usart_set_attributes, /* deviceSetAttributes */ + FALSE /* TRUE if interrupt driven, FALSE if not. */ +}; + +at91rm9200_usart_regs_t *usart_get_base(int minor) +{ + console_tbl *console_entry; + at91rm9200_usart_regs_t *port; + + console_entry = BSP_get_uart_from_minor(minor); + + if (console_entry == NULL) + return 0; + + port = (at91rm9200_usart_regs_t *) console_entry->ulCtrlPort1; + //printk( "minor=%d entry=%p port=%p\n", minor, console_entry, port ); + + return port; +} + +/* + * Functions called via callbacks (i.e. the ones in uart_fns + */ + +/* + * This is called the first time each device is opened. Since + * the driver is polled, we don't have to do anything. If the driver + * were interrupt driven, we'd enable interrupts here. + */ +static int usart_first_open(int major, int minor, void *arg) +{ + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return -1; + + /* XXX port isn't being initialized or enabled */ + + /* XXX I hope this is enough */ + usart->cr = (US_CR_RXEN | US_CR_TXEN); + return 0; +} + +/* + * This is called the last time each device is closed. Since + * the driver is polled, we don't have to do anything. If the driver + * were interrupt driven, we'd disable interrupts here. + */ +static int usart_last_close(int major, int minor, void *arg) +{ + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return -1; + + return 0; +} + +/* + * Read one character from UART. + * + * return -1 if there's no data, otherwise return + * the character in lowest 8 bits of returned int. + */ +static int usart_read_polled(int minor) +{ + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return -1; + + /* if nothing ready return -1 */ + if ( (usart->sr & US_IER_RXRDY) == 0 ) + return -1; + + return usart->rhr; +} + + +/* + * Write character out + */ +static void usart_write_polled(int minor, char c) +{ + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return; + + /* delay until TX empty */ + while ( (usart->sr & US_IER_TXEMPTY) == 0 ) + ; + + usart->thr = c; +} + +/* + * Write buffer to UART + * + * return 1 on success, -1 on error + */ +static ssize_t usart_write_polled_support(int minor, const char *buf, size_t len) +{ + at91rm9200_usart_regs_t *usart; + int nwrite=0; + + /* + * Verify the minor number + */ + usart = usart_get_base(minor); + if ( !usart ) + return -1; + + /* + * poll each byte in the string out of the port. + */ + while (nwrite < len) { + usart_write_polled(minor, *buf++); + nwrite++; + } + + /* + * return the number of bytes written. + */ + return nwrite; + + return 1; +} + + +/* Set up the UART. */ +static void usart_init(int minor) +{ + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return; + +} + + +/* This is for setting baud rate, bits, etc. */ +static int usart_set_attributes(int minor, const struct termios *t) +{ + uint32_t brgr; + uint32_t mode, baud, baud_requested; + at91rm9200_usart_regs_t *usart; + + usart = usart_get_base(minor); + if ( !usart ) + return -1; + + /* Get current mode register */ + mode = usart->mr & ~(US_MR_USMODE | US_MR_USCLKS | US_MR_CHRL + | US_MR_PAR | US_MR_NBSTOP); + + /* Byte size */ + switch (t->c_cflag & CSIZE){ + case CS5: + mode |= US_MR_CHRL_5; + break; + case CS6: + mode |= US_MR_CHRL_6; + break; + case CS7: + mode |= US_MR_CHRL_7; + break; + default: + mode |= US_MR_CHRL_8; + break; + } + + /* Stop bits */ + if (t->c_cflag & CSTOPB){ + mode |= US_MR_NBSTOP_2; /* 2 stop bits */ + } else + mode |= US_MR_NBSTOP_1; /* 1 stop bits */ + + /* Parity */ + if (t->c_cflag & PARENB){ + /* Mark or Space parity */ + if (t->c_cflag & PARODD){ + mode |= US_MR_PAR_ODD; + } else + mode |= US_MR_PAR_EVEN; + } else + mode |= US_MR_PAR_NONE; + + baud_requested = t->c_ospeed; + + /* If not, set the dbgu console baud as USART baud default */ + if (!baud_requested) + baud_requested = BSP_get_baud(); + + baud = rtems_termios_baud_to_number(baud_requested); + + brgr = (at91rm9200_get_mck() / 16) / baud; + + if (brgr > 65535){ /* BRGR is 16-bit, so switch to slower clock */ + brgr /= 8; + mode |= US_MR_USCLKS_MCK_DIV8; + } + + usart->mr = mode; + usart->brgr = brgr; + return 0; +} diff --git a/bsps/arm/edb7312/console/uart.c b/bsps/arm/edb7312/console/uart.c new file mode 100644 index 0000000000..4ba71c8cc2 --- /dev/null +++ b/bsps/arm/edb7312/console/uart.c @@ -0,0 +1,169 @@ +/* + * Cirrus EP7312 Console Driver + * + * Copyright (c) 2002 by Jay Monkman <jtm@smoothsmoothie.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> /* Must be before libio.h */ +#include <rtems/libio.h> +#include <termios.h> +#include <rtems/bspIo.h> + +#include <ep7312.h> +#include <libchip/serial.h> +#include <libchip/sersupp.h> + +#define NUM_DEVS 1 +int uart_poll_read(int minor); + +static int uart_first_open(int major, int minor, void *arg); +static int uart_last_close(int major, int minor, void *arg); +static int uart_read(int minor); +static ssize_t uart_write(int minor, const char *buf, size_t len); +static void uart_init(int minor); +static void uart_write_polled(int minor, char c); +static int uart_set_attributes(int minor, const struct termios *t); + +unsigned long Console_Configuration_Count = NUM_DEVS; + +const console_fns uart_fns = +{ + libchip_serial_default_probe, + uart_first_open, + uart_last_close, + uart_read, + uart_write, + uart_init, + uart_write_polled, + uart_set_attributes, + FALSE +}; +console_tbl Console_Configuration_Ports[] = { + { + "/dev/com0", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &uart_fns, /* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 16, /* ulMargin */ + 8, /* ulHysteresis */ + NULL, /* pDeviceParams */ + (uint32_t)EP7312_UARTCR1, /* ulCtrlPort1 */ + (uint32_t)EP7312_SYSFLG1, /* ulCtrlPort2 */ + (uint32_t)EP7312_UARTDR1, /* ulDataPort */ + 0, /* getRegister */ + 0, /* setRegister */ + 0, /* getData */ + 0, /* setData */ + 0, /* ulClock */ + 0 /* ulIntVector */ + }}; + +static int uart_first_open(int major, int minor, void *arg) {return 0;} +static int uart_last_close(int major, int minor, void *arg) {return 0;} +static int uart_read(int minor) +{ + return uart_poll_read(minor); +} + +static void uart_write_polled(int minor, char c) +{ + uart_write(minor, &c, 1); +} + +static int uart_set_attributes(int minor, const struct termios *t) +{ + return 0; +} + +int uart_poll_read(int minor) +{ + volatile uint32_t *data_reg; + volatile uint32_t *ctrl_reg2; + char c; + int err; + + data_reg = (uint32_t *)Console_Port_Tbl[minor]->ulDataPort; + ctrl_reg2 = (uint32_t *)Console_Port_Tbl[minor]->ulCtrlPort2; + + if ((*ctrl_reg2 & EP7312_UART_URXFE1) != 0) { + return -1; + } + + err = *data_reg; + c = err & 0xff; + err &= (EP7312_UART_FRMERR | EP7312_UART_PARERR | EP7312_UART_OVERR); + + return c; +} + +static ssize_t uart_do_write( + volatile uint32_t *uartdr, + const char *buf, + size_t len, + volatile uint32_t *sysflg +) +{ + size_t i; + + for (i = 0; i < len; i++) { + /* Wait for fifo to have room */ + while ((*sysflg & EP7312_UART_UTXFF1) != 0) { + continue; + } + + *uartdr = buf[i]; + } + + return len; +} + +static ssize_t uart_write(int minor, const char *buf, size_t len) +{ + volatile uint32_t *data_reg; + volatile uint32_t *ctrl_reg2; + + data_reg = (uint32_t *)Console_Port_Tbl[minor]->ulDataPort; + ctrl_reg2 = (uint32_t *)Console_Port_Tbl[minor]->ulCtrlPort2; + + return uart_do_write(data_reg, buf, len, ctrl_reg2); +} + +static void uart_init(int minor) +{ + volatile uint32_t *ctrl_reg1; + + ctrl_reg1 = (uint32_t *)Console_Port_Tbl[minor]->ulCtrlPort1; + + /* *ctrl_reg = (BSP_UART_DATA8 | + BSP_UART_STOP1 | + BSP_UART_PARITY_NONE | + EP7312_UART_FIFOEN | + BSP_UART_BAUD_9600); + */ + *ctrl_reg1 = (EP7312_UART_WRDLEN8 | + EP7312_UART_FIFOEN | + 0x17); /* 9600 baud */ + +} + +/* + * Debug IO support + */ +static void _BSP_null_char(char c) +{ + uart_do_write(EP7312_UARTDR1, &c, 1, EP7312_SYSFLG1); +} + +static int _BSP_get_char(void) +{ + return uart_poll_read(0); +} + +BSP_output_char_function_type BSP_output_char = _BSP_null_char; + +BSP_polling_getchar_function_type BSP_poll_char = _BSP_get_char; diff --git a/bsps/arm/gdbarmsim/console/console-io.c b/bsps/arm/gdbarmsim/console/console-io.c new file mode 100644 index 0000000000..8bea74d934 --- /dev/null +++ b/bsps/arm/gdbarmsim/console/console-io.c @@ -0,0 +1,58 @@ +/* + * COPYRIGHT (c) 1989-2009. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/console-polled.h> +#include <rtems/libio.h> +#include <stdlib.h> +#include <assert.h> + +/* + * console_initialize_hardware + * + * This routine initializes the console hardware. + * + */ +void console_initialize_hardware(void) +{ + return; +} + +/* + * console_outbyte_polled + * + * This routine transmits a character using polling. + */ +void console_outbyte_polled( + int port, + char ch +) +{ + gdbarmsim_writec(ch); +} + +/* + * console_inbyte_nonblocking + * + * This routine polls for a character. + */ + +int console_inbyte_nonblocking( + int port +) +{ + return -1; +} + +#include <rtems/bspIo.h> + +static void MyBSP_output_char(char c) { console_outbyte_polled( 0, c ); } + +BSP_output_char_function_type BSP_output_char = MyBSP_output_char; +BSP_polling_getchar_function_type BSP_poll_char = NULL; diff --git a/bsps/arm/gumstix/console/ffuart.c b/bsps/arm/gumstix/console/ffuart.c new file mode 100644 index 0000000000..335fc6f4de --- /dev/null +++ b/bsps/arm/gumstix/console/ffuart.c @@ -0,0 +1,227 @@ +/* + * Console driver for pxa255 full function port by Yang Xi <hiyangxi@gmail.com> + * Copyright (c) 2004 by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <rtems/libio.h> +#include <termios.h> + +#include <pxa255.h> +#include <ffuart.h> +#include <rtems/bspIo.h> +#include <libchip/serial.h> +#include <libchip/sersupp.h> + +volatile int dbg_dly; + +/* static function prototypes */ +static int ffuart_first_open(int major, int minor, void *arg); +static int ffuart_last_close(int major, int minor, void *arg); +static int ffuart_read(int minor); +static ssize_t ffuart_write(int minor, const char *buf, size_t len); +static void ffuart_init(int minor); +static void ffuart_write_polled(int minor, char c); +static int ffuart_set_attributes(int minor, const struct termios *t); + +/* Pointers to functions for handling the UART. */ +const console_fns ffuart_fns = +{ + libchip_serial_default_probe, + ffuart_first_open, + ffuart_last_close, + ffuart_read, + ffuart_write, + ffuart_init, + ffuart_write_polled, /* not used in this driver */ + ffuart_set_attributes, + FALSE /* TRUE if interrupt driven, FALSE if not. */ +}; + + +/* + * This is called the first time each device is opened. Since + * the driver is polled, we don't have to do anything. If the driver + * were interrupt driven, we'd enable interrupts here. + */ +static int ffuart_first_open(int major, int minor, void *arg) +{ + return 0; +} + + +/* + * This is called the last time each device is closed. Since + * the driver is polled, we don't have to do anything. If the driver + * were interrupt driven, we'd disable interrupts here. + */ +static int ffuart_last_close(int major, int minor, void *arg) +{ + return 0; +} + + +/* + * Read one character from UART. + * + * return -1 if there's no data, otherwise return + * the character in lowest 8 bits of returned int. + */ +static int ffuart_read(int minor) +{ + char c; + console_tbl *console_entry; + ffuart_reg_t *ffuart; + + console_entry = BSP_get_uart_from_minor(minor); + + if (console_entry == NULL) { + return -1; + } + + ffuart = (ffuart_reg_t *)console_entry->ulCtrlPort1; + + if (!(ffuart->lsr & FULL_RECEIVE)) { + return -1; + } + + c = ffuart->rbr & 0xff; + + return c; +} + + +/* + * Write buffer to UART + * + * return 1 on success, -1 on error + */ +static ssize_t ffuart_write(int minor, const char *buf, size_t len) +{ + size_t i, x; + char c; + console_tbl *console_entry; + ffuart_reg_t *ffuart; + + console_entry = BSP_get_uart_from_minor(minor); + + if (console_entry == NULL) { + return -1; + } + + ffuart = (ffuart_reg_t *)console_entry->ulCtrlPort1; + + for (i = 0; i < len; i++) { + + while(1) { + if (ffuart->lsr & SEND_EMPTY) { + break; + } + } + + c = (char) buf[i]; +#if ON_SKYEYE != 1 + if(c=='\n'){ + ffuart->rbr = '\r'; + for (x = 0; x < 100; x++) { + dbg_dly++; /* using a global so this doesn't get optimized out */ + } + while(1){ + if(ffuart->lsr & SEND_EMPTY){ + break; + } + } + } +#endif + ffuart->rbr = c; + + /* the TXRDY flag does not seem to update right away (is this true?) */ + /* so we wait a bit before continuing */ + for (x = 0; x < 100; x++) { + dbg_dly++; /* using a global so this doesn't get optimized out */ + } + } + + return 1; +} + + +static void ffuart_init(int minor) +{ + + + console_tbl *console_entry; + ffuart_reg_t *ffuart; + unsigned int divisor; + + console_entry = BSP_get_uart_from_minor(minor); + + + + if (console_entry == NULL) { + return; + } + + ffuart = (ffuart_reg_t *)console_entry->ulCtrlPort1; + ffuart->lcr |= DLAB; + /*Set the Bound*/ + ffuart->lcr |= DLAB; + divisor = FREQUENCY_UART / (115200*16); + ffuart->rbr = divisor & 0xff; + ffuart->ier = (divisor >> 8)&0xff; + /*Disable FIFO*/ + ffuart->iir = 0; + ffuart->lcr &=~DLAB; + /*Enable UART*/ + ffuart->ier = 0x40; + ffuart->lcr = EIGHT_BITS_NOPARITY_1STOPBIT; + +} + +/* I'm not sure this is needed for the shared console driver. */ +static void ffuart_write_polled(int minor, char c) +{ + ffuart_write(minor, &c, 1); +} + +/* This is for setting baud rate, bits, etc. */ +static int ffuart_set_attributes(int minor, const struct termios *t) +{ + return 0; +} + +/***********************************************************************/ +/* + * The following functions are not used by TERMIOS, but other RTEMS + * functions use them instead. + */ +/***********************************************************************/ +/* + * Read from UART. This is used in the exit code, and can't + * rely on interrupts. + */ +static int ffuart_poll_read(int minor) +{ + return ffuart_read(minor); +} + + +/* + * Write a character to the console. This is used by printk() and + * maybe other low level functions. It should not use interrupts or any + * RTEMS system calls. It needs to be very simple + */ +static void _BSP_put_char( char c ) { + ffuart_write_polled(0, c); +} + +static int _BSP_poll_char(void) { + return ffuart_poll_read(0); +} + +BSP_output_char_function_type BSP_output_char = _BSP_put_char; +BSP_polling_getchar_function_type BSP_poll_char = _BSP_poll_char; diff --git a/bsps/arm/gumstix/console/uarts.c b/bsps/arm/gumstix/console/uarts.c new file mode 100644 index 0000000000..08408695e0 --- /dev/null +++ b/bsps/arm/gumstix/console/uarts.c @@ -0,0 +1,66 @@ +/* + * Console driver for GUMSTIX by Yang Xi <hiyangxi@gmail.com> + * + * This driver uses the shared console driver in + * ...../libbsp/shared/console.c + * + * Copyright (c) 2003 by Cogent Computer Systems + * Written by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <rtems/libio.h> +#include <termios.h> +#include <rtems/bspIo.h> + +#include <pxa255.h> +#include <libchip/serial.h> +#include <libchip/sersupp.h> + +/* How many serial ports? */ +#define NUM_DEVS 1 + +/* These are used by code in console.c */ +unsigned long Console_Configuration_Count = NUM_DEVS; + +extern const console_fns ffuart_fns; + +/* + * There's one item in array for each UART. + * + * Some of these fields are marked "NOT USED". They are not used + * by console.c, but may be used by drivers in libchip + * + * when we add other types of UARTS we will need to move this + * structure to a generic uart.c file with only this in it + */ +console_tbl Console_Configuration_Ports[] = { + { + "/dev/com0", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &ffuart_fns, /* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 0, /* ulMargin - NOT USED */ + 0, /* ulHysteresis - NOT USED */ + NULL, /* pDeviceParams */ + FFUART_BASE, /* ulCtrlPort1 - Pointer to DBGU regs */ + 0, /* ulCtrlPort2 - NOT USED */ + 0, /* ulDataPort - NOT USED */ + NULL, /* getRegister - NOT USED */ + NULL, /* setRegister - NOT USED */ + NULL, /* getData - NOT USED */ + NULL, /* setData - NOT USED */ + 0, /* ulClock - NOT USED */ + 0 /* ulIntVector - NOT USED */ + }}; + + +console_tbl *BSP_get_uart_from_minor(int minor) +{ + return Console_Port_Tbl[minor]; +} diff --git a/bsps/arm/imx/console/console-config.c b/bsps/arm/imx/console/console-config.c new file mode 100644 index 0000000000..0731446f08 --- /dev/null +++ b/bsps/arm/imx/console/console-config.c @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <sys/param.h> + +#include <rtems/bspIo.h> +#include <rtems/console.h> +#include <rtems/sysinit.h> +#include <rtems/termiostypes.h> + +#include <bsp.h> +#include <bsp/fdt.h> +#include <bsp/irq.h> + +#include <arm/freescale/imx/imx_ccmvar.h> +#include <arm/freescale/imx/imx_uartreg.h> + +#include <libfdt.h> + +#define IMX_UART_TX_FIFO_LEVEL 16 + +typedef struct { + rtems_termios_device_context base; + volatile imx_uart *regs; +#ifdef CONSOLE_USE_INTERRUPTS + rtems_vector_number irq; + int tx_in_progress; +#endif +} imx_uart_context; + +static imx_uart_context imx_uart_instances[7]; + +static imx_uart_context *imx_uart_console = &imx_uart_instances[0]; + +static volatile imx_uart *imx_uart_get_regs(rtems_termios_device_context *base) +{ + imx_uart_context *ctx; + + ctx = (imx_uart_context *) base; + return ctx->regs; +} + +static void imx_uart_write_polled(rtems_termios_device_context *base, char c) +{ + volatile imx_uart *regs; + + regs = imx_uart_get_regs(base); + + while ((regs->usr1 & IMX_UART_USR1_TRDY) == 0) { + /* Wait */ + } + + regs->utxd = IMX_UART_UTXD_TX_DATA(c); +} + +void imx_uart_console_drain(void) +{ + volatile imx_uart *regs; + + regs = imx_uart_get_regs(&imx_uart_console->base); + + if (regs != NULL) { + while ((regs->usr2 & IMX_UART_USR2_TXFE) == 0) { + /* Wait */ + } + } +} + +static void imx_output_char(char c) +{ + imx_uart_write_polled(&imx_uart_console->base, c); +} + +static void imx_uart_init_context( + imx_uart_context *ctx, + const char *fdt, + const char *serial +) +{ + int node; + + rtems_termios_device_context_initialize(&ctx->base, "UART"); + node = fdt_path_offset(fdt, serial); + ctx->regs = imx_get_reg_of_node(fdt, node); +#ifdef CONSOLE_USE_INTERRUPTS + ctx->irq = imx_get_irq_of_node(fdt, node, 0); +#endif +} + +static void imx_uart_probe(void) +{ + const void *fdt; + int node; + int offset; + const char *console; + size_t i; + + fdt = bsp_fdt_get(); + node = fdt_path_offset(fdt, "/chosen"); + + console = fdt_getprop(fdt, node, "stdout-path", NULL); + if (console == NULL) { + console = ""; + } + + node = fdt_path_offset(fdt, "/aliases"); + offset = fdt_first_property_offset(fdt, node); + i = 0; + + while (offset >= 0 && i < RTEMS_ARRAY_SIZE(imx_uart_instances)) { + const struct fdt_property *prop; + + prop = fdt_get_property_by_offset(fdt, offset, NULL); + + if (prop != NULL) { + const char *name; + + name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); + if (strstr(name, "serial") != NULL) { + imx_uart_context *ctx; + const char *serial; + + ctx = &imx_uart_instances[i]; + serial = prop->data; + + if (strcmp(serial, console) == 0) { + imx_uart_console = ctx; + } + + imx_uart_init_context(ctx, fdt, serial); + ++i; + } + } + + offset = fdt_next_property_offset(fdt, offset); + } + + BSP_output_char = imx_output_char; +} + +static void imx_output_char_init(char c) +{ + imx_uart_probe(); + imx_output_char(c); +} + +BSP_output_char_function_type BSP_output_char = imx_output_char_init; + +BSP_polling_getchar_function_type BSP_poll_char = NULL; + +#ifdef CONSOLE_USE_INTERRUPTS +static void imx_uart_interrupt(void *arg) +{ + rtems_termios_tty *tty; + imx_uart_context *ctx; + volatile imx_uart *regs; + uint32_t usr2; + + tty = arg; + ctx = rtems_termios_get_device_context(tty); + regs = ctx->regs; + usr2 = regs->usr2; + + regs->usr1 = IMX_UART_USR1_AGTIM; + + while ((usr2 & IMX_UART_USR2_RDR) != 0) { + char c; + + c = IMX_UART_URXD_RX_DATA_GET(regs->urxd); + rtems_termios_enqueue_raw_characters(tty, &c, 1); + usr2 = regs->usr2; + } + + if (ctx->tx_in_progress > 0 && (regs->usr1 & IMX_UART_USR1_TRDY) != 0) { + rtems_termios_dequeue_characters(tty, ctx->tx_in_progress); + } +} +#endif + +static bool imx_uart_set_attributes( + rtems_termios_device_context *base, + const struct termios *term +) +{ + imx_uart_context *ctx; + volatile imx_uart *regs; + uint32_t ufcr; + uint32_t baud; + + ctx = (imx_uart_context *) base; + regs = imx_uart_get_regs(&ctx->base); + + baud = rtems_termios_baud_to_number(term->c_ospeed); + + if (baud != 0) { + ufcr = regs->ufcr; + ufcr = IMX_UART_UFCR_RFDIV_SET(ufcr, 0x5); + regs->ufcr = ufcr; + regs->ubir = 15; + regs->ubmr = imx_ccm_uart_hz() / baud - 1; + } + + return true; +} + +static bool imx_uart_first_open( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + struct termios *term, + rtems_libio_open_close_args_t *args +) +{ + imx_uart_context *ctx; + volatile imx_uart *regs; +#ifdef CONSOLE_USE_INTERRUPTS + rtems_status_code sc; + uint32_t ufcr; +#endif + + ctx = (imx_uart_context *) base; + regs = imx_uart_get_regs(&ctx->base); + + regs->ucr1 = IMX_UART_UCR1_UARTEN; + regs->ucr2 = IMX_UART_UCR2_IRTS | IMX_UART_UCR2_WS | IMX_UART_UCR2_RXEN + | IMX_UART_UCR2_TXEN | IMX_UART_UCR2_SRST; + + rtems_termios_set_initial_baud(tty, 115200); + imx_uart_set_attributes(base, term); + +#ifdef CONSOLE_USE_INTERRUPTS + ufcr = regs->ufcr; + ufcr = IMX_UART_UFCR_RXTL_SET(ufcr, 16); + ufcr = IMX_UART_UFCR_TXTL_SET(ufcr, IMX_UART_TX_FIFO_LEVEL); + regs->ufcr = ufcr; + regs->ucr1 |= IMX_UART_UCR1_RRDYEN; + regs->ucr2 |= IMX_UART_UCR2_ATEN; + sc = rtems_interrupt_handler_install( + ctx->irq, + "UART", + RTEMS_INTERRUPT_SHARED, + imx_uart_interrupt, + tty + ); + if (sc != RTEMS_SUCCESSFUL) { + return false; + } +#endif + + return true; +} + +static void imx_uart_last_close( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + rtems_libio_open_close_args_t *args +) +{ +#ifdef CONSOLE_USE_INTERRUPTS + imx_uart_context *ctx; + + ctx = (imx_uart_context *) base; + rtems_interrupt_handler_remove(ctx->irq, imx_uart_interrupt, tty); +#endif +} + +static void imx_uart_write( + rtems_termios_device_context *base, + const char *buf, + size_t len +) +{ +#ifdef CONSOLE_USE_INTERRUPTS + imx_uart_context *ctx; + volatile imx_uart *regs; + int n; + uint32_t ucr1; + + ctx = (imx_uart_context *) base; + regs = imx_uart_get_regs(&ctx->base); + ucr1 = regs->ucr1; + + if (len > 0) { + int i; + + n = (int) MIN(len, IMX_UART_TX_FIFO_LEVEL); + ucr1 |= IMX_UART_UCR1_TRDYEN; + + for (i = 0; i < n; ++i) { + regs->utxd = IMX_UART_UTXD_TX_DATA(buf[i]); + } + } else { + n = 0; + ucr1 &= ~IMX_UART_UCR1_TRDYEN; + } + + regs->ucr1 = ucr1; + ctx->tx_in_progress = n; +#else + size_t i; + + for (i = 0; i < len; ++i) { + imx_uart_write_polled(base, buf[i]); + } +#endif +} + +#ifndef CONSOLE_USE_INTERRUPTS +static int imx_uart_read(rtems_termios_device_context *base) +{ + volatile imx_uart *regs; + + regs = imx_uart_get_regs(base); + + if ((regs->usr2 & IMX_UART_USR2_RDR) != 0) { + return IMX_UART_URXD_RX_DATA_GET(regs->urxd); + } else { + return -1; + } +} +#endif + +static const rtems_termios_device_handler imx_uart_handler = { + .first_open = imx_uart_first_open, + .last_close = imx_uart_last_close, + .write = imx_uart_write, + .set_attributes = imx_uart_set_attributes, +#ifdef CONSOLE_USE_INTERRUPTS + .mode = TERMIOS_IRQ_DRIVEN +#else + .poll_read = imx_uart_read, + .mode = TERMIOS_POLLED +#endif +}; + +rtems_status_code console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + char path[] = "/dev/ttyS?"; + size_t i; + + rtems_termios_initialize(); + + for (i = 0; i < RTEMS_ARRAY_SIZE(imx_uart_instances); ++i) { + imx_uart_context *ctx; + + ctx = &imx_uart_instances[i]; + path[sizeof(path) - 2] = (char) ('0' + i); + + rtems_termios_device_install( + path, + &imx_uart_handler, + NULL, + &ctx->base + ); + + if (ctx == imx_uart_console) { + link(path, CONSOLE_DEVICE_NAME); + } + } + + return RTEMS_SUCCESSFUL; +} + +RTEMS_SYSINIT_ITEM( + imx_uart_probe, + RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_LAST +); diff --git a/bsps/arm/lm3s69xx/console/console-config.c b/bsps/arm/lm3s69xx/console/console-config.c new file mode 100644 index 0000000000..b702f0cd66 --- /dev/null +++ b/bsps/arm/lm3s69xx/console/console-config.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2013 Eugeniy Meshcheryakov <eugen@debian.org> + * + * Copyright (c) 2011 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/bspIo.h> + +#include <libchip/serial.h> + +#include <bspopts.h> +#include <bsp/irq.h> +#include <bsp/uart.h> +#include <bsp/lm3s69xx.h> + +console_tbl Console_Configuration_Ports [] = { + #ifdef LM3S69XX_ENABLE_UART_0 + { + .sDeviceName = "/dev/ttyS0", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &lm3s69xx_uart_fns, + .ulCtrlPort1 = LM3S69XX_UART_0_BASE, + .ulClock = LM3S69XX_UART_BAUD, + .ulIntVector = LM3S69XX_IRQ_UART_0, + .pDeviceParams = (void *)0 + }, + #endif + #ifdef LM3S69XX_ENABLE_UART_1 + { + .sDeviceName = "/dev/ttyS1", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &lm3s69xx_uart_fns, + .ulCtrlPort1 = LM3S69XX_UART_1_BASE, + .ulClock = LM3S69XX_UART_BAUD, + .ulIntVector = LM3S69XX_IRQ_UART_1, + .pDeviceParams = (void *)1 + }, + #endif + #ifdef LM3S69XX_ENABLE_UART_2 + { + .sDeviceName = "/dev/ttyS2", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &lm3s69xx_uart_fns, + .ulCtrlPort1 = LM3S69XX_UART_2_BASE, + .ulClock = LM3S69XX_UART_BAUD, + .ulIntVector = LM3S69XX_IRQ_UART_2, + .pDeviceParams = (void *)2 + } + #endif +}; + +#define PORT_COUNT \ + (sizeof(Console_Configuration_Ports) \ + / sizeof(Console_Configuration_Ports [0])) + +unsigned long Console_Configuration_Count = PORT_COUNT; + +static void output_char(char c) +{ + const console_fns *con = + Console_Configuration_Ports [Console_Port_Minor].pDeviceFns; + + con->deviceWritePolled((int) Console_Port_Minor, c); +} + +BSP_output_char_function_type BSP_output_char = output_char; + +BSP_polling_getchar_function_type BSP_poll_char = NULL; diff --git a/bsps/arm/lm3s69xx/console/uart.c b/bsps/arm/lm3s69xx/console/uart.c new file mode 100644 index 0000000000..67a85f4e96 --- /dev/null +++ b/bsps/arm/lm3s69xx/console/uart.c @@ -0,0 +1,167 @@ +/* + * Copyright © 2013 Eugeniy Meshcheryakov <eugen@debian.org> + * + * Copyright (c) 2011 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bspopts.h> +#include <bsp/uart.h> +#include <libchip/sersupp.h> +#include <bsp/syscon.h> +#include <bsp/lm3s69xx.h> +#include <rtems/irq-extension.h> +#include <assert.h> + +#define LM3S69XX_UART_FIFO_DEPTH 16 + +static volatile lm3s69xx_uart *get_uart_regs(int minor) +{ + console_tbl *ct = Console_Port_Tbl [minor]; + + return (lm3s69xx_uart *) ct->ulCtrlPort1; +} + +static unsigned int get_uart_number(int minor) +{ + console_tbl *ct = Console_Port_Tbl [minor]; + + return (unsigned int)ct->pDeviceParams; +} + +/* + * Returns both integer and fractional parts as one number. + */ +static uint32_t get_baud_div(uint32_t baud) +{ + uint32_t clock4 = LM3S69XX_SYSTEM_CLOCK * 4; + return (clock4 + baud - 1) / baud; +} + +static void irq_handler(void *arg) +{ + int minor = (int)arg; + console_data *cd = &Console_Port_Data [minor]; + volatile lm3s69xx_uart *uart = get_uart_regs(minor); + + do { + char buf[LM3S69XX_UART_FIFO_DEPTH]; + int i = 0; + uint32_t status = uart->fr; + + while (((status & UARTFR_RXFE) == 0) && (i < LM3S69XX_UART_FIFO_DEPTH)) { + uint32_t d = uart->dr; + + if ((d & UARTDR_ERROR_MSK) == 0) { + buf[i] = UARTDR_DATA_GET(d); + i++; + } + + status = uart->fr; + } + + if (i > 0) + rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i); + } while (uart->mis != 0); +} + +static void initialize(int minor) +{ + const console_tbl *ct = Console_Port_Tbl[minor]; + volatile lm3s69xx_uart *uart = get_uart_regs(minor); + unsigned int num = get_uart_number(minor); + + lm3s69xx_syscon_enable_uart_clock(num, true); + + uart->ctl = 0; + + uint32_t brd = get_baud_div(LM3S69XX_UART_BAUD); + uart->ibrd = brd / 64; + uart->fbrd = brd % 64; + + uart->lcrh = UARTLCRH_WLEN(0x3) | UARTLCRH_FEN; + uart->ctl = UARTCTL_RXE | UARTCTL_TXE | UARTCTL_UARTEN; + + int rv = rtems_interrupt_handler_install(ct->ulIntVector, "UART", + RTEMS_INTERRUPT_UNIQUE, irq_handler, (void *)minor); + assert(rv == RTEMS_SUCCESSFUL); +} + +static int first_open(int major, int minor, void *arg) +{ + rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg; + struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1; + console_data *cd = &Console_Port_Data [minor]; + volatile lm3s69xx_uart *uart = get_uart_regs(minor); + + cd->termios_data = tty; + rtems_termios_set_initial_baud(tty, LM3S69XX_UART_BAUD); + + /* Drain the RX FIFO. */ + while ((uart->fr & UARTFR_RXFE) == 0) + (void)uart->dr; + + uart->im = UARTI_RX | UARTI_RT; + + return 0; +} + +static int last_close(int major, int minor, void *arg) +{ + volatile lm3s69xx_uart *uart = get_uart_regs(minor); + uart->im = 0; + + return 0; +} + +static void write_polled(int minor, char c) +{ + volatile lm3s69xx_uart *uart = get_uart_regs(minor); + + while ((uart->fr & UARTFR_TXFF) != 0) { + /* Wait */ + } + + uart->dr = UARTDR_DATA(c); +} + +static ssize_t write_support_polled( + int minor, + const char *s, + size_t n +) +{ + ssize_t i = 0; + + for (i = 0; i < n; ++i) { + write_polled(minor, s [i]); + } + + return n; +} + +static int set_attribues(int minor, const struct termios *term) +{ + return -1; +} + +const console_fns lm3s69xx_uart_fns = { + .deviceProbe = libchip_serial_default_probe, + .deviceFirstOpen = first_open, + .deviceLastClose = last_close, + .deviceRead = NULL, + .deviceWrite = write_support_polled, + .deviceInitialize = initialize, + .deviceWritePolled = write_polled, + .deviceSetAttributes = set_attribues, + .deviceOutputUsesInterrupts = false +}; diff --git a/bsps/arm/lpc176x/console/console-config.c b/bsps/arm/lpc176x/console/console-config.c new file mode 100644 index 0000000000..c80932daf7 --- /dev/null +++ b/bsps/arm/lpc176x/console/console-config.c @@ -0,0 +1,192 @@ +/** + * @file + * + * @ingroup lpc176x + * + * @brief Console configuration. + */ + +/* + * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libchip/ns16550.h> + +#include <bsp.h> +#include <bsp/io.h> +#include <bsp/irq.h> +#include <bsp/console-termios.h> + +/** + * @brief Gets the uart register according to the current address. + * + * @param addr Register address. + * @param i Index register. + * @return Uart register. + */ +static inline uint8_t lpc176x_uart_get_register( + const uintptr_t addr, + const uint8_t i +) +{ + volatile uint32_t *reg = (volatile uint32_t *) addr; + + return (uint8_t) reg[ i ]; +} + +/** + * @brief Sets the uart register address according to the value passed. + * + * @param addr Register address. + * @param i Index register. + * @param val Value to set. + */ +static inline void lpc176x_uart_set_register( + const uintptr_t addr, + const uint8_t i, + const uint8_t val +) +{ + volatile uint32_t *reg = (volatile uint32_t *) addr; + + reg[ i ] = val; +} + +static bool lpc176x_uart1_probe(rtems_termios_device_context *ctx) +{ + (void)ctx; + + lpc176x_module_enable( LPC176X_MODULE_UART_1, LPC176X_MODULE_PCLK_DEFAULT ); + + lpc176x_pin_select( LPC176X_PIN_UART_1_TXD, LPC176X_PIN_FUNCTION_01 ); + lpc176x_pin_select( LPC176X_PIN_UART_1_RXD, LPC176X_PIN_FUNCTION_01 ); + + return true; +} + +#ifdef LPC176X_CONFIG_UART_2 +static bool lpc176x_uart2_probe(rtems_termios_device_context *ctx) +{ + (void)ctx; + + lpc176x_module_enable( LPC176X_MODULE_UART_2, LPC176X_MODULE_PCLK_DEFAULT ); + + lpc176x_pin_select( LPC176X_PIN_UART_2_TXD, LPC176X_PIN_FUNCTION_01 ); + lpc176x_pin_select( LPC176X_PIN_UART_2_RXD, LPC176X_PIN_FUNCTION_01 ); + + return true; +} +#endif + +#ifdef LPC176X_CONFIG_UART_3 +static bool lpc176x_uart3_probe(rtems_termios_device_context *ctx) +{ + (void)ctx; + + lpc176x_module_enable( LPC176X_MODULE_UART_3, LPC176X_MODULE_PCLK_DEFAULT ); + + lpc176x_pin_select( LPC176X_PIN_UART_3_TXD, LPC176X_PIN_FUNCTION_10 ); + lpc176x_pin_select( LPC176X_PIN_UART_3_RXD, LPC176X_PIN_FUNCTION_10 ); + + return true; +} +#endif + +#ifdef LPC176X_CONFIG_CONSOLE +static ns16550_context lpc176x_uart_context_0 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"), + .get_reg = lpc176x_uart_get_register, + .set_reg = lpc176x_uart_set_register, + .port = UART0_BASE_ADDR, + .irq = LPC176X_IRQ_UART_0, + .clock = LPC176X_PCLK, + .initial_baud = LPC176X_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +#ifdef LPC176X_CONFIG_UART_1 +static ns16550_context lpc176x_uart_context_1 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"), + .get_reg = lpc176x_uart_get_register, + .set_reg = lpc176x_uart_set_register, + .port = UART1_BASE_ADDR, + .irq = LPC176X_IRQ_UART_1, + .clock = LPC176X_PCLK, + .initial_baud = LPC176X_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +#ifdef LPC176X_CONFIG_UART_2 +static ns16550_context lpc176x_uart_context_2 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"), + .get_reg = lpc176x_uart_get_register, + .set_reg = lpc176x_uart_set_register, + .port = UART2_BASE_ADDR, + .irq = LPC176X_IRQ_UART_2, + .clock = LPC176X_PCLK, + .initial_baud = LPC176X_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +#ifdef LPC176X_CONFIG_UART_3 +static ns16550_context lpc176x_uart_context_3 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"), + .get_reg = lpc176x_uart_get_register, + .set_reg = lpc176x_uart_set_register, + .port = UART3_BASE_ADDR, + .irq = LPC176X_IRQ_UART_3, + .clock = LPC176X_PCLK, + .initial_baud = LPC176X_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +const console_device console_device_table[] = { + #ifdef LPC176X_CONFIG_CONSOLE + { + .device_file = "/dev/ttyS0", + .probe = console_device_probe_default, + .handler = &ns16550_handler_interrupt, + .context = &lpc176x_uart_context_0.base + }, + #endif + #ifdef LPC176X_CONFIG_UART_1 + { + .device_file = "/dev/ttyS1", + .probe = lpc176x_uart1_probe, + .handler = &ns16550_handler_interrupt, + .context = &lpc176x_uart_context_1.base + }, + #endif + #ifdef LPC176X_CONFIG_UART_2 + { + .device_file = "/dev/ttyS2", + .probe = lpc176x_uart2_probe, + .handler = &ns16550_handler_interrupt, + .context = &lpc176x_uart_context_2.base + }, + #endif + #ifdef LPC176X_CONFIG_UART_3 + { + .device_file = "/dev/ttyS3", + .probe = lpc176x_uart3_probe, + .handler = &ns16550_handler_interrupt, + .context = &lpc176x_uart_context_3.base + }, + #endif +}; + +const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table); diff --git a/bsps/arm/lpc24xx/console/console-config.c b/bsps/arm/lpc24xx/console/console-config.c new file mode 100644 index 0000000000..de94552c27 --- /dev/null +++ b/bsps/arm/lpc24xx/console/console-config.c @@ -0,0 +1,134 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief Console configuration. + */ + +/* + * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/console.h> + +#include <libchip/ns16550.h> + +#include <bsp.h> +#include <bsp/lpc24xx.h> +#include <bsp/irq.h> +#include <bsp/io.h> +#include <bsp/console-termios.h> + +static uint8_t lpc24xx_uart_get_register(uintptr_t addr, uint8_t i) +{ + volatile uint32_t *reg = (volatile uint32_t *) addr; + + return (uint8_t) reg [i]; +} + +static void lpc24xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val) +{ + volatile uint32_t *reg = (volatile uint32_t *) addr; + + reg [i] = val; +} + +#ifdef LPC24XX_CONFIG_CONSOLE +static ns16550_context lpc24xx_uart_context_0 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"), + .get_reg = lpc24xx_uart_get_register, + .set_reg = lpc24xx_uart_set_register, + .port = UART0_BASE_ADDR, + .irq = LPC24XX_IRQ_UART_0, + .clock = LPC24XX_PCLK, + .initial_baud = LPC24XX_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +#ifdef LPC24XX_CONFIG_UART_1 +static ns16550_context lpc24xx_uart_context_1 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"), + .get_reg = lpc24xx_uart_get_register, + .set_reg = lpc24xx_uart_set_register, + .port = UART1_BASE_ADDR, + .irq = LPC24XX_IRQ_UART_1, + .clock = LPC24XX_PCLK, + .initial_baud = LPC24XX_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +#ifdef LPC24XX_CONFIG_UART_2 +static ns16550_context lpc24xx_uart_context_2 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"), + .get_reg = lpc24xx_uart_get_register, + .set_reg = lpc24xx_uart_set_register, + .port = UART2_BASE_ADDR, + .irq = LPC24XX_IRQ_UART_2, + .clock = LPC24XX_PCLK, + .initial_baud = LPC24XX_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +#ifdef LPC24XX_CONFIG_UART_3 +static ns16550_context lpc24xx_uart_context_3 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"), + .get_reg = lpc24xx_uart_get_register, + .set_reg = lpc24xx_uart_set_register, + .port = UART3_BASE_ADDR, + .irq = LPC24XX_IRQ_UART_3, + .clock = LPC24XX_PCLK, + .initial_baud = LPC24XX_UART_BAUD, + .has_fractional_divider_register = true +}; +#endif + +const console_device console_device_table[] = { + #ifdef LPC24XX_CONFIG_CONSOLE + { + .device_file = "/dev/ttyS0", + .probe = console_device_probe_default, + .handler = &ns16550_handler_interrupt, + .context = &lpc24xx_uart_context_0.base + }, + #endif + #ifdef LPC24XX_CONFIG_UART_1 + { + .device_file = "/dev/ttyS1", + .probe = lpc24xx_uart_probe_1, + .handler = &ns16550_handler_interrupt, + .context = &lpc24xx_uart_context_1.base + }, + #endif + #ifdef LPC24XX_CONFIG_UART_2 + { + .device_file = "/dev/ttyS2", + .probe = lpc24xx_uart_probe_2, + .handler = &ns16550_handler_interrupt, + .context = &lpc24xx_uart_context_2.base + }, + #endif + #ifdef LPC24XX_CONFIG_UART_3 + { + .device_file = "/dev/ttyS3", + .probe = lpc24xx_uart_probe_3, + .handler = &ns16550_handler_interrupt, + .context = &lpc24xx_uart_context_3.base + }, + #endif +}; + +const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table); diff --git a/bsps/arm/lpc24xx/console/uart-probe-1.c b/bsps/arm/lpc24xx/console/uart-probe-1.c new file mode 100644 index 0000000000..3b5f08059f --- /dev/null +++ b/bsps/arm/lpc24xx/console/uart-probe-1.c @@ -0,0 +1,40 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief UART 1 probe. + */ + +/* + * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libchip/ns16550.h> + +#include <bsp.h> +#include <bsp/io.h> + +bool lpc24xx_uart_probe_1(rtems_termios_device_context *context) +{ + static const lpc24xx_pin_range pins [] = { + LPC24XX_PIN_UART_1_TXD_P0_15, + LPC24XX_PIN_UART_1_RXD_P0_16, + LPC24XX_PIN_TERMINAL + }; + + lpc24xx_module_enable(LPC24XX_MODULE_UART_1, LPC24XX_MODULE_PCLK_DEFAULT); + lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION); + + return ns16550_probe(context); +} diff --git a/bsps/arm/lpc24xx/console/uart-probe-2.c b/bsps/arm/lpc24xx/console/uart-probe-2.c new file mode 100644 index 0000000000..d45dbb755b --- /dev/null +++ b/bsps/arm/lpc24xx/console/uart-probe-2.c @@ -0,0 +1,40 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief UART 2 probe. + */ + +/* + * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libchip/ns16550.h> + +#include <bsp.h> +#include <bsp/io.h> + +bool lpc24xx_uart_probe_2(rtems_termios_device_context *context) +{ + static const lpc24xx_pin_range pins [] = { + LPC24XX_PIN_UART_2_TXD_P0_10, + LPC24XX_PIN_UART_2_RXD_P0_11, + LPC24XX_PIN_TERMINAL + }; + + lpc24xx_module_enable(LPC24XX_MODULE_UART_2, LPC24XX_MODULE_PCLK_DEFAULT); + lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION); + + return ns16550_probe(context); +} diff --git a/bsps/arm/lpc24xx/console/uart-probe-3.c b/bsps/arm/lpc24xx/console/uart-probe-3.c new file mode 100644 index 0000000000..fad932ef9e --- /dev/null +++ b/bsps/arm/lpc24xx/console/uart-probe-3.c @@ -0,0 +1,40 @@ +/** + * @file + * + * @ingroup lpc24xx + * + * @brief UART 3 probe. + */ + +/* + * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libchip/ns16550.h> + +#include <bsp.h> +#include <bsp/io.h> + +bool lpc24xx_uart_probe_3(rtems_termios_device_context *context) +{ + static const lpc24xx_pin_range pins [] = { + LPC24XX_PIN_UART_3_TXD_P0_0, + LPC24XX_PIN_UART_3_RXD_P0_1, + LPC24XX_PIN_TERMINAL + }; + + lpc24xx_module_enable(LPC24XX_MODULE_UART_3, LPC24XX_MODULE_PCLK_DEFAULT); + lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION); + + return ns16550_probe(context); +} diff --git a/bsps/arm/lpc32xx/console/console-config.c b/bsps/arm/lpc32xx/console/console-config.c new file mode 100644 index 0000000000..17e6b0af8f --- /dev/null +++ b/bsps/arm/lpc32xx/console/console-config.c @@ -0,0 +1,225 @@ +/** + * @file + * + * @ingroup arm_lpc32xx + * + * @brief Console configuration. + */ + +/* + * Copyright (c) 2009-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libchip/ns16550.h> + +#include <bsp.h> +#include <bsp/lpc32xx.h> +#include <bsp/irq.h> +#include <bsp/hsu.h> +#include <bsp/console-termios.h> + +static uint8_t lpc32xx_uart_get_register(uintptr_t addr, uint8_t i) +{ + volatile uint32_t *reg = (volatile uint32_t *) addr; + + return (uint8_t) reg [i]; +} + +static void lpc32xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val) +{ + volatile uint32_t *reg = (volatile uint32_t *) addr; + + reg [i] = val; +} + +#ifdef LPC32XX_UART_3_BAUD + static bool lpc32xx_uart_probe_3(rtems_termios_device_context *context) + { + LPC32XX_UARTCLK_CTRL |= BSP_BIT32(0); + LPC32XX_U3CLK = LPC32XX_CONFIG_U3CLK; + LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 4, 5); + + return ns16550_probe(context); + } +#endif + +#ifdef LPC32XX_UART_4_BAUD + static bool lpc32xx_uart_probe_4(rtems_termios_device_context *context) + { + volatile lpc32xx_gpio *gpio = &lpc32xx.gpio; + + /* + * Set GPO_21/U4_TX/LCDVD[3] to U4_TX. This works only if LCD module is + * disabled. + */ + gpio->p2_mux_set = BSP_BIT32(2); + + LPC32XX_UARTCLK_CTRL |= BSP_BIT32(1); + LPC32XX_U4CLK = LPC32XX_CONFIG_U4CLK; + LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 6, 7); + + return ns16550_probe(context); + } +#endif + +#ifdef LPC32XX_UART_6_BAUD + static bool lpc32xx_uart_probe_6(rtems_termios_device_context *context) + { + /* Bypass the IrDA modulator/demodulator */ + LPC32XX_UART_CTRL |= BSP_BIT32(5); + + LPC32XX_UARTCLK_CTRL |= BSP_BIT32(3); + LPC32XX_U6CLK = LPC32XX_CONFIG_U6CLK; + LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 10, 11); + + return ns16550_probe(context); + } +#endif + +/* FIXME: Console selection */ + +#ifdef LPC32XX_UART_5_BAUD +static ns16550_context lpc32xx_uart_context_5 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 5"), + .get_reg = lpc32xx_uart_get_register, + .set_reg = lpc32xx_uart_set_register, + .port = LPC32XX_BASE_UART_5, + .irq = LPC32XX_IRQ_UART_5, + .clock = 16 * LPC32XX_UART_5_BAUD, + .initial_baud = LPC32XX_UART_5_BAUD +}; +#endif + +#ifdef LPC32XX_UART_3_BAUD +static ns16550_context lpc32xx_uart_context_3 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"), + .get_reg = lpc32xx_uart_get_register, + .set_reg = lpc32xx_uart_set_register, + .port = LPC32XX_BASE_UART_3, + .irq = LPC32XX_IRQ_UART_3, + .clock = 16 * LPC32XX_UART_3_BAUD, + .initial_baud = LPC32XX_UART_3_BAUD +}; +#endif + +#ifdef LPC32XX_UART_4_BAUD +static ns16550_context lpc32xx_uart_context_4 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 4"), + .get_reg = lpc32xx_uart_get_register, + .set_reg = lpc32xx_uart_set_register, + .port = LPC32XX_BASE_UART_4, + .irq = LPC32XX_IRQ_UART_4, + .clock = 16 * LPC32XX_UART_4_BAUD, + .initial_baud = LPC32XX_UART_4_BAUD +}; +#endif + +#ifdef LPC32XX_UART_6_BAUD +static ns16550_context lpc32xx_uart_context_6 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 6"), + .get_reg = lpc32xx_uart_get_register, + .set_reg = lpc32xx_uart_set_register, + .port = LPC32XX_BASE_UART_6, + .irq = LPC32XX_IRQ_UART_6, + .clock = 16 * LPC32XX_UART_6_BAUD, + .initial_baud = LPC32XX_UART_6_BAUD +}; +#endif + +#ifdef LPC32XX_UART_1_BAUD +static lpc32xx_hsu_context lpc32xx_uart_context_1 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"), + .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_1, + .irq = LPC32XX_IRQ_UART_1, + .initial_baud = LPC32XX_UART_1_BAUD +}; +#endif + +#ifdef LPC32XX_UART_2_BAUD +static lpc32xx_hsu_context lpc32xx_uart_context_2 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"), + .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_2, + .irq = LPC32XX_IRQ_UART_2, + .initial_baud = LPC32XX_UART_2_BAUD +}; +#endif + +#ifdef LPC32XX_UART_7_BAUD +static lpc32xx_hsu_context lpc32xx_uart_context_7 = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 7"), + .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_7, + .irq = LPC32XX_IRQ_UART_7, + .initial_baud = LPC32XX_UART_7_BAUD +}; +#endif + +const console_device console_device_table[] = { + #ifdef LPC32XX_UART_5_BAUD + { + .device_file = "/dev/ttyS5", + .probe = console_device_probe_default, + .handler = &ns16550_handler_interrupt, + .context = &lpc32xx_uart_context_5.base + }, + #endif + #ifdef LPC32XX_UART_3_BAUD + { + .device_file = "/dev/ttyS3", + .probe = lpc32xx_uart_probe_3, + .handler = &ns16550_handler_interrupt, + .context = &lpc32xx_uart_context_3.base + }, + #endif + #ifdef LPC32XX_UART_4_BAUD + { + .device_file = "/dev/ttyS4", + .probe = lpc32xx_uart_probe_4, + .handler = &ns16550_handler_interrupt, + .context = &lpc32xx_uart_context_4.base + }, + #endif + #ifdef LPC32XX_UART_6_BAUD + { + .device_file = "/dev/ttyS6", + .probe = lpc32xx_uart_probe_6, + .handler = &ns16550_handler_interrupt, + .context = &lpc32xx_uart_context_6.base + }, + #endif + #ifdef LPC32XX_UART_1_BAUD + { + .device_file = "/dev/ttyS1", + .probe = lpc32xx_hsu_probe, + .handler = &lpc32xx_hsu_fns, + .context = &lpc32xx_uart_context_1.base + }, + #endif + #ifdef LPC32XX_UART_2_BAUD + { + .device_file = "/dev/ttyS2", + .probe = lpc32xx_hsu_probe, + .handler = &lpc32xx_hsu_fns, + .context = &lpc32xx_uart_context_2.base + }, + #endif + #ifdef LPC32XX_UART_7_BAUD + { + .device_file = "/dev/ttyS7", + .probe = lpc32xx_hsu_probe, + .handler = &lpc32xx_hsu_fns, + .context = &lpc32xx_uart_context_7.base + }, + #endif +}; + +const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table); diff --git a/bsps/arm/lpc32xx/console/hsu.c b/bsps/arm/lpc32xx/console/hsu.c new file mode 100644 index 0000000000..b2044e0753 --- /dev/null +++ b/bsps/arm/lpc32xx/console/hsu.c @@ -0,0 +1,208 @@ +/** + * @file + * + * @ingroup arm_lpc32xx + * + * @brief High speed UART driver (14-clock). + */ + +/* + * Copyright (c) 2010-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> +#include <bsp/lpc32xx.h> +#include <bsp/irq.h> +#include <bsp/hsu.h> + +#define HSU_FIFO_SIZE 64 + +#define HSU_LEVEL_RX_MASK 0xffU +#define HSU_LEVEL_TX_MASK 0xff00U +#define HSU_LEVEL_TX_SHIFT 8 + +#define HSU_RX_DATA_MASK 0xffU +#define HSU_RX_EMPTY (1U << 8) +#define HSU_RX_ERROR (1U << 9) +#define HSU_RX_BREAK (1U << 10) + +#define HSU_IIR_TX (1U << 0) +#define HSU_IIR_RX_TRIG (1U << 1) +#define HSU_IIR_RX_TIMEOUT (1U << 2) + +#define HSU_CTRL_INTR_DISABLED 0x1280fU +#define HSU_CTRL_RX_INTR_ENABLED 0x1284fU +#define HSU_CTRL_RX_AND_TX_INTR_ENABLED 0x1286fU + +/* We are interested in RX timeout, RX trigger and TX trigger interrupts */ +#define HSU_IIR_MASK 0x7U + +bool lpc32xx_hsu_probe(rtems_termios_device_context *base) +{ + lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base; + volatile lpc32xx_hsu *hsu = ctx->hsu; + + hsu->ctrl = HSU_CTRL_INTR_DISABLED; + + /* Drain FIFOs */ + while (hsu->level != 0) { + hsu->fifo; + } + + return true; +} + +static void lpc32xx_hsu_interrupt_handler(void *arg) +{ + rtems_termios_tty *tty = arg; + lpc32xx_hsu_context *ctx = rtems_termios_get_device_context(tty); + volatile lpc32xx_hsu *hsu = ctx->hsu; + + /* Iterate until no more interrupts are pending */ + do { + int rv = 0; + int i = 0; + char buf [HSU_FIFO_SIZE]; + + /* Enqueue received characters */ + while (i < HSU_FIFO_SIZE) { + uint32_t in = hsu->fifo; + + if ((in & HSU_RX_EMPTY) == 0) { + if ((in & HSU_RX_BREAK) == 0) { + buf [i] = in & HSU_RX_DATA_MASK; + ++i; + } + } else { + break; + } + } + rtems_termios_enqueue_raw_characters(tty, buf, i); + + /* Dequeue transmitted characters */ + rv = rtems_termios_dequeue_characters(tty, (int) ctx->chars_in_transmission); + if (rv == 0) { + /* Nothing to transmit */ + } + } while ((hsu->iir & HSU_IIR_MASK) != 0); +} + +static bool lpc32xx_hsu_first_open( + struct rtems_termios_tty *tty, + rtems_termios_device_context *base, + struct termios *term, + rtems_libio_open_close_args_t *args +) +{ + lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base; + volatile lpc32xx_hsu *hsu = ctx->hsu; + rtems_status_code sc; + bool ok; + + sc = rtems_interrupt_handler_install( + ctx->irq, + "HSU", + RTEMS_INTERRUPT_UNIQUE, + lpc32xx_hsu_interrupt_handler, + tty + ); + ok = sc == RTEMS_SUCCESSFUL; + + if (ok) { + rtems_termios_set_initial_baud(tty, ctx->initial_baud); + hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED; + } + + return ok; +} + +static void lpc32xx_hsu_last_close( + struct rtems_termios_tty *tty, + rtems_termios_device_context *base, + rtems_libio_open_close_args_t *args +) +{ + lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base; + volatile lpc32xx_hsu *hsu = ctx->hsu; + + hsu->ctrl = HSU_CTRL_INTR_DISABLED; + + rtems_interrupt_handler_remove( + ctx->irq, + lpc32xx_hsu_interrupt_handler, + tty + ); +} + +static void lpc32xx_hsu_write( + rtems_termios_device_context *base, + const char *buf, + size_t len +) +{ + lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base; + volatile lpc32xx_hsu *hsu = ctx->hsu; + size_t tx_level = (hsu->level & HSU_LEVEL_TX_MASK) >> HSU_LEVEL_TX_SHIFT; + size_t tx_free = HSU_FIFO_SIZE - tx_level; + size_t i = 0; + size_t out = len > tx_free ? tx_free : len; + + for (i = 0; i < out; ++i) { + hsu->fifo = buf [i]; + } + + ctx->chars_in_transmission = out; + + if (len > 0) { + hsu->ctrl = HSU_CTRL_RX_AND_TX_INTR_ENABLED; + } else { + hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED; + hsu->iir = HSU_IIR_TX; + } +} + +static bool lpc32xx_hsu_set_attributes( + rtems_termios_device_context *base, + const struct termios *term +) +{ + lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base; + volatile lpc32xx_hsu *hsu = ctx->hsu; + int baud_flags = term->c_ospeed; + + if (baud_flags != 0) { + int32_t baud = rtems_termios_baud_to_number(baud_flags); + + if (baud > 0) { + uint32_t baud_divisor = 14 * (uint32_t) baud; + uint32_t rate = LPC32XX_PERIPH_CLK / baud_divisor; + uint32_t remainder = LPC32XX_PERIPH_CLK - rate * baud_divisor; + + if (2 * remainder >= baud_divisor) { + ++rate; + } + + hsu->rate = rate - 1; + } + } + + return true; +} + +const rtems_termios_device_handler lpc32xx_hsu_fns = { + .first_open = lpc32xx_hsu_first_open, + .last_close = lpc32xx_hsu_last_close, + .write = lpc32xx_hsu_write, + .set_attributes = lpc32xx_hsu_set_attributes, + .mode = TERMIOS_IRQ_DRIVEN +}; diff --git a/bsps/arm/raspberrypi/console/console-config.c b/bsps/arm/raspberrypi/console/console-config.c new file mode 100644 index 0000000000..d2186c918b --- /dev/null +++ b/bsps/arm/raspberrypi/console/console-config.c @@ -0,0 +1,68 @@ +/** + * @file + * + * @ingroup raspberrypi_usart + * + * @brief Console Configuration. + */ + +/* + * Copyright (c) 2015 Yang Qiao + * based on work by: + * Copyright (c) 2013 Alan Cudmore + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.rtems.org/license/LICENSE + * + */ + +#include <rtems/bspIo.h> + +#include <libchip/serial.h> + +#include <bspopts.h> +#include <bsp/irq.h> +#include <bsp/usart.h> +#include <bsp/raspberrypi.h> +#include <bsp/fbcons.h> + +console_tbl Console_Configuration_Ports [] = { + { + .sDeviceName = "/dev/ttyS0", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &bcm2835_usart_fns, + .deviceProbe = NULL, + .pDeviceFlow = NULL, + .ulCtrlPort1 = BCM2835_UART0_BASE, + .ulCtrlPort2 = 0, + .ulClock = USART0_DEFAULT_BAUD, + .ulIntVector = BCM2835_IRQ_ID_UART + }, + { + .sDeviceName ="/dev/fbcons", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &fbcons_fns, + .deviceProbe = fbcons_probe, + .pDeviceFlow = NULL, + }, +}; + +#define PORT_COUNT \ + (sizeof(Console_Configuration_Ports) \ + / sizeof(Console_Configuration_Ports [0])) + +unsigned long Console_Configuration_Count = PORT_COUNT; + +static void output_char(char c) +{ + const console_fns *con = + Console_Configuration_Ports [Console_Port_Minor].pDeviceFns; + + con->deviceWritePolled((int) Console_Port_Minor, c); +} + +BSP_output_char_function_type BSP_output_char = output_char; + +BSP_polling_getchar_function_type BSP_poll_char = NULL; diff --git a/bsps/arm/raspberrypi/console/console_select.c b/bsps/arm/raspberrypi/console/console_select.c new file mode 100644 index 0000000000..bd246ca868 --- /dev/null +++ b/bsps/arm/raspberrypi/console/console_select.c @@ -0,0 +1,114 @@ +/** + * @file + * + * @ingroup raspberrypi_console + * + * @brief console select + */ + +/* + * Copyright (c) 2015 Yang Qiao + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.rtems.org/license/LICENSE + * + */ + +#include <bsp.h> +#include <bsp/fatal.h> +#include <rtems/libio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <termios.h> + +#include <rtems/termiostypes.h> +#include <libchip/serial.h> +#include "../../shared/dev/serial/legacy-console.h" +#include <bsp/rpi-fb.h> + +rtems_device_minor_number BSPPrintkPort = 0; + +/* + * Method to return true if the device associated with the + * minor number probs available. + */ +static bool bsp_Is_Available( rtems_device_minor_number minor ) +{ + console_tbl *cptr = Console_Port_Tbl[ minor ]; + + /* + * First perform the configuration dependent probe, then the + * device dependent probe + */ + if ( ( !cptr->deviceProbe || cptr->deviceProbe( minor ) ) && + cptr->pDeviceFns->deviceProbe( minor ) ) { + return true; + } + + return false; +} + +/* + * Method to return the first available device. + */ +static rtems_device_minor_number bsp_First_Available_Device( void ) +{ + rtems_device_minor_number minor; + + for ( minor = 0; minor < Console_Port_Count; minor++ ) { + console_tbl *cptr = Console_Port_Tbl[ minor ]; + + /* + * First perform the configuration dependent probe, then the + * device dependent probe + */ + + if ( ( !cptr->deviceProbe || cptr->deviceProbe( minor ) ) && + cptr->pDeviceFns->deviceProbe( minor ) ) { + return minor; + } + } + + /* + * Error No devices were found. We will want to bail here. + */ + bsp_fatal( BSP_FATAL_CONSOLE_NO_DEV ); +} + +void bsp_console_select( void ) +{ + /* + * Reset Console_Port_Minor and + * BSPPrintkPort here if desired. + * + * This default version allows the bsp to set these + * values at creation and will not touch them again + * unless the selected port number is not available. + */ + const char *opt; + + Console_Port_Minor = BSP_CONSOLE_UART0; + BSPPrintkPort = BSP_CONSOLE_UART0; + + opt = rpi_cmdline_get_arg( "--console=" ); + + if ( opt ) { + if ( strncmp( opt, "fbcons", sizeof( "fbcons" ) - 1 ) == 0 ) { + if ( rpi_video_is_initialized() > 0 ) { + Console_Port_Minor = BSP_CONSOLE_FB; + BSPPrintkPort = BSP_CONSOLE_FB; + } + } + } + + /* + * If the device that was selected isn't available then + * let the user know and select the first available device. + */ + if ( !bsp_Is_Available( Console_Port_Minor ) ) { + Console_Port_Minor = bsp_First_Available_Device(); + } +} diff --git a/bsps/arm/raspberrypi/console/fb.c b/bsps/arm/raspberrypi/console/fb.c new file mode 100644 index 0000000000..815d17e8ca --- /dev/null +++ b/bsps/arm/raspberrypi/console/fb.c @@ -0,0 +1,437 @@ +/** + * @file + * + * @ingroup raspberrypi + * + * @brief framebuffer support. + */ + +/* + * Copyright (c) 2015 Yang Qiao + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.rtems.org/license/LICENSE + * + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> + +#include <bsp.h> +#include <bsp/raspberrypi.h> +#include <bsp/mailbox.h> +#include <bsp/vc.h> +#include <bsp/rpi-fb.h> + +#include <libcpu/arm-cp15.h> + +#include <rtems.h> +#include <rtems/libio.h> +#include <rtems/fb.h> +#include <rtems/framebuffer.h> +#include <rtems/score/atomic.h> +#include <rtems/bspIo.h> + +#define SCREEN_WIDTH 1024 +#define SCREEN_HEIGHT 768 +#define BPP 32 + +/* flag to limit driver to protect against multiple opens */ +static Atomic_Flag driver_mutex; + +/* + * screen information for the driver (fb0). + */ + +static struct fb_var_screeninfo fb_var_info = { + .xres = SCREEN_WIDTH, + .yres = SCREEN_HEIGHT, + .bits_per_pixel = BPP +}; + +static struct fb_fix_screeninfo fb_fix_info = { + .smem_start = (void *) NULL, + .smem_len = 0, + .type = FB_TYPE_PACKED_PIXELS, + .visual = FB_VISUAL_TRUECOLOR, + .line_length = 0 +}; + +typedef enum { + NO_SUITABLE_MODE = -1, + BAD_FORMAT = -2, + AUTO_SELECT = -3, + DONT_INIT = -4, + NO_MODE_REQ = -5, +} mode_err_ret_val; + +int rpi_get_fix_screen_info( struct fb_fix_screeninfo *info ) +{ + *info = fb_fix_info; + return 0; +} + +int rpi_get_var_screen_info( struct fb_var_screeninfo *info ) +{ + *info = fb_var_info; + return 0; +} + +/** + * @brief Find mode given in string format. + * + * expected format + * <resX>x<resY>[-<bpp>] + * numbers <resX>, <resY> and <bpp> are decadic + * + * @param[out] fb_var_ptr pointer to variable mode part filled by function + * @param[in] video_string string to be parsed + * @retval video mode number to be set + * @retval -1 no suitable mode found + * @retval -2 bad format of the video_string + * @retval -3 automatic mode selection requested + * @retval -4 request to not initialize graphics + * @retval -5 no mode requested/empty video string + */ + +static int parse_mode_from_string( + struct fb_var_screeninfo *fb_var_ptr, + const char *video_string +) +{ + const char *opt; + char *endptr; + uint32_t width; + uint32_t height; + uint32_t bpp = 0; + + opt = video_string; + + if ( opt == NULL ) + return NO_MODE_REQ; + + if ( strncmp( opt, "auto", 4 ) == 0 ) + return AUTO_SELECT; + + if ( strncmp( opt, "none", 4 ) == 0 || + strncmp( opt, "off", 3 ) == 0 ) + return DONT_INIT; + + width = strtol( opt, &endptr, 10 ); + + if ( *endptr != 'x' ) { + return BAD_FORMAT; + } + + opt = endptr + 1; + height = strtol( opt, &endptr, 10 ); + + switch ( *endptr ) { + case '-': + opt = endptr + 1; + endptr = NULL; + bpp = strtol( opt, &endptr, 10 ); + + if ( ( endptr == opt ) || ( endptr == NULL ) ) + return BAD_FORMAT; + + if ( *endptr && ( *endptr != ' ' ) ) + return BAD_FORMAT; + + break; + case ' ': + case 0: + break; + default: + return BAD_FORMAT; + } + + fb_var_ptr->xres = width; + fb_var_ptr->yres = height; + + if ( bpp != 0 ) + fb_var_ptr->bits_per_pixel = bpp; + + return 0; +} + +static int find_mode_from_vc( void ) +{ + int res; + unsigned int width; + unsigned int height; + bcm2835_get_display_size_entries entries; + + res = bcm2835_mailbox_get_display_size( &entries ); + + width = entries.width; + height = entries.height; + + if ( width == 0 || height == 0 ) { + fb_var_info.xres = SCREEN_WIDTH; + fb_var_info.yres = SCREEN_HEIGHT; + } else { + fb_var_info.xres = width; + fb_var_info.yres = height; + } + printk("find_mode_from_vc %u x %u, res %d\n", width, height, res); + + return res; +} + +bool rpi_fb_hdmi_is_present( void ) +{ + bcm2835_get_display_size_entries entries; + + memset( &entries, 0, sizeof( entries ) ); + bcm2835_mailbox_get_display_size( &entries ); + + /* Impossible display dimension */ + if ( ( entries.width < 10 ) || ( entries.height < 10 ) ) + return false; + + /* Know default values reported when monitor is not present */ + if ( ( entries.width == 0x290 ) && ( entries.height == 0x1A0 ) ) + return false; + + return true; +} + +int rpi_fb_init( void ) +{ + int res; + int mode_from_cmdline; + bcm2835_init_frame_buffer_entries init_frame_buffer_entries; + + if ( fb_fix_info.smem_start != NULL ) { + return RPI_FB_INIT_ALREADY_INITIALIZED; + } + + if ( rpi_fb_hdmi_is_present() == false ) { + return RPI_FB_INIT_NO_DISPLAY; + } + + mode_from_cmdline = parse_mode_from_string( &fb_var_info, + rpi_cmdline_get_arg( "--video=" ) ); + + switch ( mode_from_cmdline ) { + case BAD_FORMAT: + return RPI_FB_INIT_CMDLINE_BAD_FORMAT; + case AUTO_SELECT: + break; + case DONT_INIT: + return RPI_FB_INIT_CMDLINE_DONT_INIT; + case NO_MODE_REQ: + return RPI_FB_INIT_CMDLINE_NO_MODE_REQ; + } + + if ( mode_from_cmdline ) { + if ( find_mode_from_vc() ) + return RPI_FB_INIT_MODE_PROBE_ERROR; + } + + memset( &init_frame_buffer_entries, 0, sizeof( init_frame_buffer_entries ) ); + init_frame_buffer_entries.xres = fb_var_info.xres; + init_frame_buffer_entries.yres = fb_var_info.yres; + init_frame_buffer_entries.xvirt = fb_var_info.xres; + init_frame_buffer_entries.yvirt = fb_var_info.yres; + init_frame_buffer_entries.depth = fb_var_info.bits_per_pixel; + init_frame_buffer_entries.pixel_order = bcm2835_mailbox_pixel_order_rgb; + init_frame_buffer_entries.alpha_mode = bcm2835_mailbox_alpha_mode_0_opaque; + init_frame_buffer_entries.voffset_x = 0; + init_frame_buffer_entries.voffset_y = 0; + init_frame_buffer_entries.overscan_left = 0; + init_frame_buffer_entries.overscan_right = 0; + init_frame_buffer_entries.overscan_top = 0; + init_frame_buffer_entries.overscan_bottom = 0; + printk("bcm2835_mailbox_init_frame_buffer ...\n"); + res = bcm2835_mailbox_init_frame_buffer( &init_frame_buffer_entries ); + printk("bcm2835_mailbox_init_frame_buffer returned %d\n", res); + if (res != 0) { + printk("bcm2835_mailbox_init_frame_buffer retry ...\n"); + res = bcm2835_mailbox_init_frame_buffer( &init_frame_buffer_entries ); + printk("bcm2835_mailbox_init_frame_buffer returned %d\n", res); + if (res != 0) + return RPI_FB_INIT_SETUP_FAILED; + } + + bcm2835_get_pitch_entries get_pitch_entries; + bcm2835_mailbox_get_pitch( &get_pitch_entries ); + + fb_var_info.xres = init_frame_buffer_entries.xres; + fb_var_info.yres = init_frame_buffer_entries.yres; + fb_var_info.bits_per_pixel = init_frame_buffer_entries.depth; + fb_fix_info.smem_start = (void *) init_frame_buffer_entries.base; + fb_fix_info.smem_len = init_frame_buffer_entries.size; + fb_fix_info.line_length = get_pitch_entries.pitch; + + if ( fb_fix_info.smem_start == NULL ) + return RPI_FB_INIT_START_ADDR_UNKNOWN; + + printk("fb_fix_info.smem_start %p\n", fb_fix_info.smem_start); + + arm_cp15_set_translation_table_entries( (void *) fb_fix_info.smem_start, + (void *) fb_fix_info.smem_start + + fb_fix_info.smem_len, + ARMV7_MMU_DATA_READ_WRITE_CACHED ); + + return RPI_FB_INIT_OK; +} + +/* + * fbds device driver initialize entry point. + */ + +rtems_device_driver frame_buffer_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + + /* register the devices */ + status = rtems_io_register_name( FRAMEBUFFER_DEVICE_0_NAME, major, 0 ); + + if ( status != RTEMS_SUCCESSFUL ) { + printk( "[!] error registering framebuffer\n" ); + rtems_fatal_error_occurred( status ); + } + + _Atomic_Flag_clear( &driver_mutex, ATOMIC_ORDER_RELEASE ); + return RTEMS_SUCCESSFUL; +} + +/* + * fbds device driver open operation. + */ + +rtems_device_driver frame_buffer_open( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + if ( _Atomic_Flag_test_and_set( &driver_mutex, + ATOMIC_ORDER_ACQUIRE ) != 0 ) { + printk( "RaspberryPi framebuffer could not lock driver_mutex\n" ); + return RTEMS_UNSATISFIED; + } + + if ( fb_fix_info.smem_start == NULL ) { + int res; + res = rpi_fb_init(); + if ( (res < RPI_FB_INIT_OK) || (fb_fix_info.smem_start == NULL) ) { + _Atomic_Flag_clear( &driver_mutex, ATOMIC_ORDER_RELEASE ); + printk( "RaspberryPi framebuffer initialization failed\n" ); + return RTEMS_UNSATISFIED; + } + } + + memset( (void *) fb_fix_info.smem_start, 0, fb_fix_info.smem_len ); + return RTEMS_SUCCESSFUL; +} + +/* + * fbds device driver close operation. + */ + +rtems_device_driver frame_buffer_close( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + /* restore previous state. for VGA this means return to text mode. + * leave out if graphics hardware has been initialized in + * frame_buffer_initialize() */ + memset( (void *) fb_fix_info.smem_start, 0, fb_fix_info.smem_len ); + _Atomic_Flag_clear( &driver_mutex, ATOMIC_ORDER_RELEASE ); + return RTEMS_SUCCESSFUL; +} + +/* + * fbds device driver read operation. + */ + +rtems_device_driver frame_buffer_read( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg; + + rw_args->bytes_moved = + ( ( rw_args->offset + rw_args->count ) > fb_fix_info.smem_len ) ? + ( fb_fix_info.smem_len - rw_args->offset ) : rw_args->count; + memcpy( rw_args->buffer, + (const void *) ( fb_fix_info.smem_start + rw_args->offset ), + rw_args->bytes_moved ); + return RTEMS_SUCCESSFUL; +} + +/* + * fbds device driver write operation. + */ + +rtems_device_driver frame_buffer_write( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg; + + rw_args->bytes_moved = + ( ( rw_args->offset + rw_args->count ) > fb_fix_info.smem_len ) ? + ( fb_fix_info.smem_len - rw_args->offset ) : rw_args->count; + memcpy( (void *) ( fb_fix_info.smem_start + rw_args->offset ), + rw_args->buffer, + rw_args->bytes_moved ); + return RTEMS_SUCCESSFUL; +} + +/* + * ioctl entry point. + */ + +rtems_device_driver frame_buffer_control( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_libio_ioctl_args_t *args = arg; + + /* XXX check minor */ + + switch ( args->command ) { + case FBIOGET_VSCREENINFO: + memcpy( args->buffer, &fb_var_info, sizeof( fb_var_info ) ); + args->ioctl_return = 0; + break; + case FBIOGET_FSCREENINFO: + memcpy( args->buffer, &fb_fix_info, sizeof( fb_fix_info ) ); + args->ioctl_return = 0; + break; + case FBIOGETCMAP: + /* no palette - truecolor mode */ + args->ioctl_return = -1; + return RTEMS_UNSATISFIED; + case FBIOPUTCMAP: + /* no palette - truecolor mode */ + args->ioctl_return = -1; + return RTEMS_UNSATISFIED; + default: + args->ioctl_return = -1; + return RTEMS_UNSATISFIED; + } + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/raspberrypi/console/fbcons.c b/bsps/arm/raspberrypi/console/fbcons.c new file mode 100644 index 0000000000..3669ba458d --- /dev/null +++ b/bsps/arm/raspberrypi/console/fbcons.c @@ -0,0 +1,177 @@ +/** + * @file + * + * @ingroup raspberrypi_console + * + * @brief framebuffer graphic console support. + */ + +/* + * Copyright (c) 2015 Yang Qiao + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.rtems.org/license/LICENSE + * + */ + +#include <rtems.h> +#include <rtems/libio.h> + +#include <stdlib.h> + +#include <libchip/serial.h> +#include <libchip/sersupp.h> + +#include <bsp.h> +#include <bsp/fbcons.h> +#include <bsp/vc.h> +#include <bsp/rpi-fb.h> + +/* + * fbcons_init + * + * This function initializes the fb console to a quiecsent state. + */ +static void fbcons_init( int minor ) +{ +} + +/* + * fbcons_open + * + * This function opens a port for communication. + * + * Default state is 9600 baud, 8 bits, No parity, and 1 stop bit. + */ +static int fbcons_open( + int major, + int minor, + void *arg +) +{ + return RTEMS_SUCCESSFUL; +} + +/* + * fbcons_close + * + * This function shuts down the requested port. + */ +static int fbcons_close( + int major, + int minor, + void *arg +) +{ + return ( RTEMS_SUCCESSFUL ); +} + +/* + * fbcons_write_polled + * + * This routine polls out the requested character. + */ +static void fbcons_write_polled( + int minor, + char c +) +{ + rpi_fb_outch( c ); + + if ( c == '\n' ) + rpi_fb_outch( '\r' ); /* LF = LF + CR */ +} + +/* + * fbcons_write_support_polled + * + * Console Termios output entry point when using polled output. + * + */ +static ssize_t fbcons_write_support_polled( + int minor, + const char *buf, + size_t len +) +{ + int nwrite = 0; + + /* + * poll each byte in the string out of the port. + */ + while ( nwrite < len ) { + fbcons_write_polled( minor, *buf++ ); + nwrite++; + } + + /* + * return the number of bytes written. + */ + return nwrite; +} + +/* + * fbcons_inbyte_nonblocking_polled + * + * Console Termios polling input entry point. + */ +static int fbcons_inbyte_nonblocking_polled( int minor ) +{ + // if( rtems_kbpoll() ) { + // int c = getch(); + // return c; + // } + + return -1; +} + +/* + * fbcons_set_attributes + * + * This function sets the UART channel to reflect the requested termios + * port settings. + */ +static int fbcons_set_attributes( + int minor, + const struct termios *t +) +{ + return 0; +} + +bool fbcons_probe( int minor ) +{ + // rtems_status_code status; + static bool firstTime = true; + static bool ret = false; + + /* + * keyboard interrupt should be registered when the keyboard is available + */ + if ( firstTime ) { + if ( !rpi_fb_hdmi_is_present() ) { + ret = false; + } else { + ret = true; + } + } + + firstTime = false; + + return ret; +} + +const console_fns fbcons_fns = +{ + .deviceProbe = libchip_serial_default_probe, /* deviceProbe */ + .deviceFirstOpen = fbcons_open, /* deviceFirstOpen */ + .deviceLastClose = fbcons_close, /* deviceLastClose */ + .deviceRead = fbcons_inbyte_nonblocking_polled, /* deviceRead */ + .deviceWrite = fbcons_write_support_polled, /* deviceWrite */ + .deviceInitialize = fbcons_init, /* deviceInitialize */ + .deviceWritePolled = fbcons_write_polled, /* deviceWritePolled */ + .deviceSetAttributes = fbcons_set_attributes, /* deviceSetAttributes */ + .deviceOutputUsesInterrupts = FALSE, /* deviceOutputUsesInterrupts*/ +}; diff --git a/bsps/arm/raspberrypi/console/font_data.h b/bsps/arm/raspberrypi/console/font_data.h new file mode 100644 index 0000000000..852310cbf9 --- /dev/null +++ b/bsps/arm/raspberrypi/console/font_data.h @@ -0,0 +1,4639 @@ +/** + * @file + * + * @ingroup raspberrypi + * + * @brief graphic text console font file + * + */ +/* + * Copyright (c) 2015 Yang Qiao + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.rtems.org/license/LICENSE + * + */ + +#ifndef LIBBSP_ARM_RASPBERRYPI_FONT_DATA_H +#define LIBBSP_ARM_RASPBERRYPI_FONT_DATA_H + +#define RPI_FONT_CHARS 256 +#define RPI_FONT_WIDTH 8 +#define RPI_FONT_HEIGHT 16 +#define RPI_FONT_SIZE (RPI_FONT_CHARS * RPI_FONT_HEIGHT) + +static unsigned char rpi_font[RPI_FONT_SIZE] = { + + /* 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 */ + +}; + +#endif diff --git a/bsps/arm/raspberrypi/console/outch.c b/bsps/arm/raspberrypi/console/outch.c new file mode 100644 index 0000000000..20601384c7 --- /dev/null +++ b/bsps/arm/raspberrypi/console/outch.c @@ -0,0 +1,463 @@ +/** + * @file + * + * @ingroup raspberrypi + * + * @brief displaying characters on the console + */ + +/** + * + * Copyright (c) 2015 Yang Qiao + * based on work by: + * Copyright (C) 1998 Eric Valette (valette@crf.canon.fr) + * Canon Centre Recherche France. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * Till Straumann <strauman@slac.stanford.edu>, 2003/9: + * - added handling of basic escape sequences (cursor movement + * and erasing; just enough for the line editor 'libtecla' to + * work...) + * + */ + +#include <bsp.h> +#include <bsp/vc.h> +#include <bsp/rpi-fb.h> +#include <rtems/fb.h> + +#include <stdlib.h> +#include <string.h> +#include "font_data.h" + +static void wr_cursor( + int r, + int c +) +{ + /* dummy function for now */ +} + +#define TAB_SPACE 4 +#define CONSOLE_BG_COL 0x00 +#define CONSOLE_FG_COL 0xa0 + +static void *fb_mem = NULL; +static unsigned short maxCol; +static unsigned short maxRow; +static unsigned short bytes_per_pixel; +static unsigned int bytes_per_line; +static unsigned int bytes_per_char_line; +static unsigned char row; +static unsigned char column; +static unsigned int nLines; +static uint32_t fgx, bgx, eorx; +static int rpi_video_initialized; + +static const int video_font_draw_table32[ 16 ][ 4 ] = { + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00000000, 0x00000000, 0x00000000, 0x00ffffff }, + { 0x00000000, 0x00000000, 0x00ffffff, 0x00000000 }, + { 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff }, + { 0x00000000, 0x00ffffff, 0x00000000, 0x00000000 }, + { 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff }, + { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000 }, + { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff }, + { 0x00ffffff, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff }, + { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000 }, + { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff }, + { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000 }, + { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff }, + { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000 }, + { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff } +}; + +static void scroll( void ) +{ + int i, j; /* Counters */ + uint8_t *pt_scroll, *pt_bitmap; /* Pointers on the bit-map */ + + pt_bitmap = fb_mem; + j = 0; + pt_bitmap = pt_bitmap + j; + pt_scroll = pt_bitmap + bytes_per_char_line; + + for ( i = j; i < maxRow - 1; i++ ) { + memcpy( pt_bitmap, pt_scroll, bytes_per_char_line ); + pt_bitmap = pt_bitmap + bytes_per_char_line; + pt_scroll = pt_bitmap + bytes_per_char_line; + } + + /* + * Blank characters are displayed on the last line. + */ + memset( pt_bitmap, 0, bytes_per_char_line ); +} + +static void doCRNL( + int cr, + int nl +) +{ + if ( nl ) { + if ( ++row == maxRow ) { + scroll(); /* Scroll the screen now */ + row = maxRow - 1; + } + + nLines++; + } + + if ( cr ) + column = 0; + + /* Move cursor on the next location */ + if ( cr || nl ) { + wr_cursor( row, column ); + } +} + +static void advanceCursor( void ) +{ + if ( ++column == maxCol ) + doCRNL( 1, 1 ); + else + wr_cursor( row, column ); +} + +static void gotorc( + int r, + int c +) +{ + column = c; + row = r; + wr_cursor( row, column ); +} + +static void video_drawchars( + int r, + int c, + unsigned char ch +) +{ + if ( fb_mem == NULL ) { + return; + } + + uint8_t *cdat, *dest, *dest0; + int rows, offset; + + offset = r * bytes_per_char_line + c * bytes_per_pixel * RPI_FONT_WIDTH; + dest0 = fb_mem + offset; + + /* + * only 32-bit per pixel format is supported for now + */ + cdat = rpi_font + ch * RPI_FONT_HEIGHT; + + for ( rows = RPI_FONT_HEIGHT, dest = dest0; + rows--; dest += bytes_per_line ) { + uint8_t bits = *cdat++; + + ( (uint32_t *) dest )[ 0 ] = + ( video_font_draw_table32 + [ bits >> 4 ][ 0 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 1 ] = + ( video_font_draw_table32 + [ bits >> 4 ][ 1 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 2 ] = + ( video_font_draw_table32 + [ bits >> 4 ][ 2 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 3 ] = + ( video_font_draw_table32 + [ bits >> 4 ][ 3 ] & eorx ) ^ bgx; + + ( (uint32_t *) dest )[ 4 ] = + ( video_font_draw_table32 + [ bits & 15 ][ 0 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 5 ] = + ( video_font_draw_table32 + [ bits & 15 ][ 1 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 6 ] = + ( video_font_draw_table32 + [ bits & 15 ][ 2 ] & eorx ) ^ bgx; + ( (uint32_t *) dest )[ 7 ] = + ( video_font_draw_table32 + [ bits & 15 ][ 3 ] & eorx ) ^ bgx; + } +} + +#define ESC ( (char) 27 ) +/* erase current location without moving the cursor */ +#define BLANK ( (char) 0x7f ) + +static void videoPutChar( char ch ) +{ + switch ( ch ) { + case '\b': { + if ( column ) + column--; + + /* Move cursor on the previous location */ + wr_cursor( row, column ); + return; + } + case '\t': { + int i; + + i = TAB_SPACE - ( column & ( TAB_SPACE - 1 ) ); + + while ( i-- ) { + + video_drawchars( row, column, ' ' ); + column += 1; + + if ( column >= maxCol ) { + doCRNL( 1, 1 ); + return; + } + } + + wr_cursor( row, column ); + + return; + } + case '\n': { + doCRNL( 0, 1 ); + return; + } + case 7: { /* Bell code must be inserted here */ + return; + } + case '\r': { + doCRNL( 1, 0 ); + return; + } + case BLANK: { + video_drawchars( row, column, ' ' ); + + wr_cursor( row, column ); + + return; + } + default: { + // *pt_bitmap = (unsigned char)ch | attribute; + video_drawchars( row, column, ch ); + advanceCursor(); + return; + } + } +} + +/* trivial state machine to handle escape sequences: + * + * --------------------------------- + * | | + * | | + * KEY: esc V [ DCABHKJ esc | + * STATE: 0 -----> 27 -----> '[' ----------> -1 ----- + * ^\ \ \ \ + * KEY: | \other \ other \ other \ other + * <------------------------------------- + * + * in state '-1', the DCABHKJ cases are handled + * + * (cursor motion and screen clearing) + */ + +#define DONE ( -1 ) + +static int handleEscape( + int oldState, + char ch +) +{ + int rval = 0; + int ro, co; + + switch ( oldState ) { + case DONE: /* means the previous char terminated an ESC sequence... */ + case 0: + + if ( 27 == ch ) { + rval = 27; /* START of an ESC sequence */ + } + + break; + + case 27: + + if ( '[' == ch ) { + rval = ch; /* received ESC '[', so far */ + } else { + /* dump suppressed 'ESC'; outch will append the char */ + videoPutChar( ESC ); + } + + break; + + case '[': + /* handle 'ESC' '[' sequences here */ + ro = row; + co = column; + rval = DONE; /* done */ + + switch ( ch ) { + case 'D': /* left */ + + if ( co > 0 ) + co--; + + break; + case 'C': /* right */ + + if ( co < maxCol ) + co++; + + break; + case 'A': /* up */ + + if ( ro > 0 ) + ro--; + + break; + case 'B': /* down */ + + if ( ro < maxRow ) + ro++; + + break; + case 'H': /* home */ + ro = co = 0; + break; + case 'K': /* clear to end of line */ + + while ( column < maxCol - 1 ) + videoPutChar( ' ' ); + + videoPutChar( BLANK ); + break; + case 'J': /* clear to end of screen */ + + while ( ( ( row < maxRow - 1 ) || ( column < maxCol - 1 ) ) ) + videoPutChar( ' ' ); + + videoPutChar( BLANK ); + break; + default: + videoPutChar( ESC ); + videoPutChar( '[' ); + /* DONT move the cursor */ + ro = -1; + rval = 0; + break; + } + + // /* reset cursor */ + if ( ro >= 0 ) + gotorc( ro, co ); + + default: + break; + } + + return rval; +} + +static void clear_screen( void ) +{ + int i, j; + + for ( j = 0; j < maxRow; j++ ) { + for ( i = 0; i < maxCol; i++ ) { + videoPutChar( ' ' ); + } + } + + column = 0; + row = 0; +} + +void rpi_fb_outch( char c ) +{ + static int escaped = 0; + + if ( !( escaped = handleEscape( escaped, c ) ) ) { + if ( '\n' == c ) + videoPutChar( '\r' ); + + videoPutChar( c ); + } +} + +void rpi_video_init( void ) +{ + int ret = rpi_fb_init(); + + if ( ( ret != RPI_FB_INIT_OK ) && + ( ret != RPI_FB_INIT_ALREADY_INITIALIZED ) ) { + rpi_video_initialized = 0; + return; + } + + struct fb_var_screeninfo fb_var_info; + struct fb_fix_screeninfo fb_fix_info; + rpi_get_var_screen_info( &fb_var_info ); + rpi_get_fix_screen_info( &fb_fix_info ); + maxCol = fb_var_info.xres / RPI_FONT_WIDTH; + maxRow = fb_var_info.yres / RPI_FONT_HEIGHT; + bytes_per_pixel = fb_var_info.bits_per_pixel / 8; + bytes_per_line = bytes_per_pixel * fb_var_info.xres; + bytes_per_char_line = RPI_FONT_HEIGHT * bytes_per_line; + fb_mem = RTEMS_DEVOLATILE( void *, fb_fix_info.smem_start ); + column = 0; + row = 0; + nLines = 0; + fgx = ( CONSOLE_FG_COL << 24 ) | + ( CONSOLE_FG_COL << 16 ) | + ( CONSOLE_FG_COL << 8 ) | + CONSOLE_FG_COL; + bgx = ( CONSOLE_BG_COL << 24 ) | + ( CONSOLE_BG_COL << 16 ) | + ( CONSOLE_BG_COL << 8 ) | + CONSOLE_BG_COL; + eorx = fgx ^ bgx; + clear_screen(); + rpi_video_initialized = 1; +} + +int rpi_video_is_initialized( void ) +{ + return rpi_video_initialized; +} + +/* for old DOS compatibility n-curses type of applications */ +void gotoxy( + int x, + int y +); +int whereX( void ); +int whereY( void ); + +void gotoxy( + int x, + int y +) +{ + gotorc( y, x ); +} + +int whereX( void ) +{ + return row; +} + +int whereY( void ) +{ + return column; +} diff --git a/bsps/arm/raspberrypi/console/usart.c b/bsps/arm/raspberrypi/console/usart.c new file mode 100644 index 0000000000..25fb523621 --- /dev/null +++ b/bsps/arm/raspberrypi/console/usart.c @@ -0,0 +1,167 @@ +/** + * @file + * + * @ingroup raspberrypi_usart + * + * @brief USART support. + */ + +/* + * Copyright (c) 2013 Alan Cudmore + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * + * http://www.rtems.org/license/LICENSE + * + */ + +#include <libchip/sersupp.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/usart.h> +#include <bsp/raspberrypi.h> +#include <rtems/bspIo.h> + +static void usart_delay(uint32_t n) +{ + volatile uint32_t i = 0; + + for(i = 0; i < n; i++) + ; +} + +#if 0 +/* + * These will be useful when the driver supports interrupt driven IO. + */ +static rtems_vector_number usart_get_irq_number(const console_tbl *ct) +{ + return ct->ulIntVector; +} + +static uint32_t usart_get_baud(const console_tbl *ct) +{ + return ct->ulClock; +} +#endif + +static void usart_set_baud(int minor, int baud) +{ + /* + * Nothing for now + */ + return; +} + +static void usart_initialize(int minor) +{ + unsigned int gpio_reg; + + /* + ** Program GPIO pins for UART 0 + */ + gpio_reg = BCM2835_REG(BCM2835_GPIO_GPFSEL1); + gpio_reg &= ~(7<<12); /* gpio14 */ + gpio_reg |= (4<<12); /* alt0 */ + gpio_reg &= ~(7<<15); /* gpio15 */ + gpio_reg |= (4<<15); /* alt0 */ + BCM2835_REG(BCM2835_GPIO_GPFSEL1) = gpio_reg; + + BCM2835_REG(BCM2835_GPIO_GPPUD) = 0; + usart_delay(150); + BCM2835_REG(BCM2835_GPIO_GPPUDCLK0) = (1<<14)|(1<<15); + usart_delay(150); + BCM2835_REG(BCM2835_GPIO_GPPUDCLK0) = 0; + + /* + ** Init the PL011 UART + */ + BCM2835_REG(BCM2835_UART0_CR) = 0; + BCM2835_REG(BCM2835_UART0_ICR) = 0x7FF; + BCM2835_REG(BCM2835_UART0_IMSC) = 0; + BCM2835_REG(BCM2835_UART0_IBRD) = 1; + BCM2835_REG(BCM2835_UART0_FBRD) = 40; + BCM2835_REG(BCM2835_UART0_LCRH) = 0x70; + BCM2835_REG(BCM2835_UART0_RSRECR) = 0; + + BCM2835_REG(BCM2835_UART0_CR) = 0x301; + + BCM2835_REG(BCM2835_UART0_IMSC) = BCM2835_UART0_IMSC_RX; + + usart_set_baud(minor, 115000); +} + +static int usart_first_open(int major, int minor, void *arg) +{ + rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg; + struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1; + const console_tbl *ct = Console_Port_Tbl [minor]; + console_data *cd = &Console_Port_Data [minor]; + + cd->termios_data = tty; + rtems_termios_set_initial_baud(tty, ct->ulClock); + + return 0; +} + +static int usart_last_close(int major, int minor, void *arg) +{ + return 0; +} + +static int usart_read_polled(int minor) +{ + if (minor == 0) { + if (((BCM2835_REG(BCM2835_UART0_FR)) & BCM2835_UART0_FR_RXFE) == 0) { + return((BCM2835_REG(BCM2835_UART0_DR)) & 0xFF ); + } else { + return -1; + } + } else { + printk("Unknown console minor number: %d\n", minor); + return -1; + } +} + +static void usart_write_polled(int minor, char c) +{ + while (1) { + if ((BCM2835_REG(BCM2835_UART0_FR) & BCM2835_UART0_FR_TXFF) == 0) + break; + } + BCM2835_REG(BCM2835_UART0_DR) = c; +} + +static ssize_t usart_write_support_polled( + int minor, + const char *s, + size_t n +) +{ + ssize_t i = 0; + + for (i = 0; i < n; ++i) { + usart_write_polled(minor, s [i]); + } + + return n; +} + +static int usart_set_attributes(int minor, const struct termios *term) +{ + return -1; +} + +const console_fns bcm2835_usart_fns = { + .deviceProbe = libchip_serial_default_probe, + .deviceFirstOpen = usart_first_open, + .deviceLastClose = usart_last_close, + .deviceRead = usart_read_polled, + .deviceWrite = usart_write_support_polled, + .deviceInitialize = usart_initialize, + .deviceWritePolled = usart_write_polled, + .deviceSetAttributes = usart_set_attributes, + .deviceOutputUsesInterrupts = false +}; diff --git a/bsps/arm/realview-pbx-a9/console/console-config.c b/bsps/arm/realview-pbx-a9/console/console-config.c new file mode 100644 index 0000000000..66dcfa6803 --- /dev/null +++ b/bsps/arm/realview-pbx-a9/console/console-config.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/serial_mouse.h> +#include <rtems/bspIo.h> + +#include <bsp.h> +#include <bsp/irq.h> +#include <bsp/arm-pl011.h> +#include <bsp/arm-pl050.h> +#include <bsp/console-termios.h> + +static arm_pl011_context pl011_context = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("PL011"), + .regs = (volatile pl011 *) 0x10009000, + .irq = RVPBXA9_IRQ_UART_0, + .initial_baud = 115200 +}; + +static arm_pl050_context pl050_context = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("PL050"), + .regs = (volatile pl050 *) 0x10007000, + .irq = RVPBXA9_IRQ_KMI1, + .initial_baud = 115200 +}; + +static void output_char(char c) +{ + arm_pl011_write_polled(&pl011_context.base, c); +} + +static bool pl011_probe(rtems_termios_device_context *base) +{ + BSP_output_char = output_char; + + return arm_pl011_probe(base); +} + +static void output_char_init(char c) +{ + pl011_probe(&pl011_context.base); + output_char(c); +} + +BSP_output_char_function_type BSP_output_char = output_char_init; + +BSP_polling_getchar_function_type BSP_poll_char = NULL; + +const console_device console_device_table[] = { + { + .device_file = "/dev/ttyS0", + .probe = pl011_probe, + .handler = &arm_pl011_fns, + .context = &pl011_context.base + }, { + .device_file = SERIAL_MOUSE_DEVICE_PS2, + .probe = console_device_probe_default, + .handler = &arm_pl050_fns, + .context = &pl050_context.base + } +}; + +const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table); diff --git a/bsps/arm/rtl22xx/console/lpc22xx_uart.h b/bsps/arm/rtl22xx/console/lpc22xx_uart.h new file mode 100644 index 0000000000..f6ae249672 --- /dev/null +++ b/bsps/arm/rtl22xx/console/lpc22xx_uart.h @@ -0,0 +1,187 @@ +/** + * @file + * @ingroup rtl22xx_uart + * @brief UART support. + */ + +#ifndef LPC22XX_UART_H +#define LPC22XX_UART_H + +/** + * @defgroup rtl22xx_uart UART Support + * @ingroup arm_rtl22xx + * @brief UART (Universal Asynchronous Reciever/Transmitter) Support + * @{ + */ + +#define FIFODEEP 16 + +#define BD115200 115200 +#define BD38400 38400 +#define BD9600 9600 + +/** @brief PINSEL0 Value for UART0 */ +#define U0_PINSEL (0x00000005) +/** @brief PINSEL0 Mask for UART0 */ +#define U0_PINMASK (0x0000000F) +/** @brief PINSEL0 Value for UART1 */ +#define U1_PINSEL (0x00050000) +/** @brief PINSEL0 Mask for UART1 */ +#define U1_PINMASK (0x000F0000) + +/** + * @name Uart line control register bit descriptions + * @{ + */ + +#define LCR_WORDLENTH_BIT 0 +#define LCR_STOPBITSEL_BIT 2 +#define LCR_PARITYENBALE_BIT 3 +#define LCR_PARITYSEL_BIT 4 +#define LCR_BREAKCONTROL_BIT 6 +#define LCR_DLAB_BIT 7 + +/** @} */ + +/** + * @name Line Control Register bit definitions + * @{ + */ + +/** @brief 5-bit character length */ +#define ULCR_CHAR_5 (0 << 0) +/** @brief 6-bit character length */ +#define ULCR_CHAR_6 (1 << 0) +/** @brief 7-bit character length */ +#define ULCR_CHAR_7 (2 << 0) +/** @brief 8-bit character length */ +#define ULCR_CHAR_8 (3 << 0) +/** @brief no stop bits */ +#define ULCR_STOP_0 (0 << 2) +/** @brief 1 stop bit */ +#define ULCR_STOP_1 (1 << 2) +/** @brief No Parity */ +#define ULCR_PAR_NO (0 << 3) +/** @brief Odd Parity */ +#define ULCR_PAR_ODD (1 << 3) +/** @brief Even Parity */ +#define ULCR_PAR_EVEN (3 << 3) +/** @brief MARK "1" Parity */ +#define ULCR_PAR_MARK (5 << 3) +/** @brief SPACE "0" Paruty */ +#define ULCR_PAR_SPACE (7 << 3) +/** @brief Output BREAK line condition */ +#define ULCR_BREAK_ENABLE (1 << 6) +/** @brief Enable Divisor Latch Access */ +#define ULCR_DLAB_ENABLE (1 << 7) + +/** @} */ + +/** + * @name Modem Control Register bit definitions + * @{ + */ + +/** @brief Data Terminal Ready */ +#define UMCR_DTR (1 << 0) +/** @brief Request To Send */ +#define UMCR_RTS (1 << 1) +/** @brief Loopback */ +#define UMCR_LB (1 << 4) + +/** @} */ + +/** + * @name Line Status Register bit definitions + * @{ + */ + +/** @brief Receive Data Ready */ +#define ULSR_RDR (1 << 0) +/** @brief Overrun Error */ +#define ULSR_OE (1 << 1) +/** @brief Parity Error */ +#define ULSR_PE (1 << 2) +/** @brief Framing Error */ +#define ULSR_FE (1 << 3) +/** @brief Break Interrupt */ +#define ULSR_BI (1 << 4) +/** @brief Transmit Holding Register Empty */ +#define ULSR_THRE (1 << 5) +/** @brief Transmitter Empty */ +#define ULSR_TEMT (1 << 6) +/** @brief Error in Receive FIFO */ +#define ULSR_RXFE (1 << 7) +#define ULSR_ERR_MASK 0x1E + +/** @} */ + +/** + * @name Modem Status Register bit definitions + * @{ + */ + +/** @brief Delta Clear To Send */ +#define UMSR_DCTS (1 << 0) +/** @brief Delta Data Set Ready */ +#define UMSR_DDSR (1 << 1) +/** @brief Trailing Edge Ring Indicator */ +#define UMSR_TERI (1 << 2) +/** @brief Delta Data Carrier Detect */ +#define UMSR_DDCD (1 << 3) +/** @brief Clear To Send */ +#define UMSR_CTS (1 << 4) +/** @brief Data Set Ready */ +#define UMSR_DSR (1 << 5) +/** @brief Ring Indicator */ +#define UMSR_RI (1 << 6) +/** @brief Data Carrier Detect */ +#define UMSR_DCD (1 << 7) + +/** @} */ + +/** + * @name Uart Interrupt Identification + * @{ + */ + +#define IIR_RSL 0x3 +#define IIR_RDA 0x2 +#define IIR_CTI 0x6 +#define IIR_THRE 0x1 + +/** @} */ + +/** + * @name Uart Interrupt Enable Type + * @{ + */ + +#define IER_RBR 0x1 +#define IER_THRE 0x2 +#define IER_RLS 0x4 + +/** @} */ + +/** + * @name Uart Receiver Errors + * @{ + */ + +#define RC_FIFO_OVERRUN_ERR 0x1 +#define RC_OVERRUN_ERR 0x2 +#define RC_PARITY_ERR 0x4 +#define RC_FRAMING_ERR 0x8 +#define RC_BREAK_IND 0x10 + +/** @} */ + +typedef enum { + UART0 = 0, + UART1 +} LPC_UartChanel_t; + +/** @} */ + +#endif + diff --git a/bsps/arm/rtl22xx/console/uart.c b/bsps/arm/rtl22xx/console/uart.c new file mode 100644 index 0000000000..2952e74508 --- /dev/null +++ b/bsps/arm/rtl22xx/console/uart.c @@ -0,0 +1,283 @@ +/* + * console driver for RTL22xx UARTs + * + * If you want the driver to be interrupt driven, you + * need to write the ISR, and in the ISR insert the + * chars into termios's queue. + */ + +/* + * Copyright (c) By ray <rayx.cn@gmail.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp.h> /* Must be before libio.h */ +#include <rtems/libio.h> +#include <termios.h> +#include <rtems/bspIo.h> + +/* Put the CPU (or UART) specific header file #include here */ +#include <lpc22xx.h> +#include "lpc22xx_uart.h" + +#include <libchip/serial.h> +#include <libchip/sersupp.h> + +/* How many serial ports? */ +#define NUM_DEVS 1 + +int dbg_dly; + +/* static function prototypes */ +static int uart_first_open(int major, int minor, void *arg); +static int uart_last_close(int major, int minor, void *arg); +static int uart_read(int minor); +static ssize_t uart_write(int minor, const char *buf, size_t len); +static void uart_init(int minor); +static void uart_write_polled(int minor, char c); +static int uart_set_attributes(int minor, const struct termios *t); + +/* These are used by code in console.c */ +unsigned long Console_Configuration_Count = NUM_DEVS; + +/* Pointers to functions for handling the UART. */ +const console_fns uart_fns = { + libchip_serial_default_probe, + uart_first_open, + uart_last_close, + uart_read, + uart_write, + uart_init, + uart_write_polled, /* not used in this driver */ + uart_set_attributes, + FALSE /* TRUE if interrupt driven, FALSE if not. */ +}; + +/* + * There's one item in array for each UART. + * + * Some of these fields are marked "NOT USED". They are not used + * by console.c, but may be used by drivers in libchip + */ +console_tbl Console_Configuration_Ports[] = { +{ + "/dev/com0", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &uart_fns, /* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 0, /* ulMargin - NOT USED */ + 0, /* ulHysteresis - NOT USED */ + NULL, /* pDeviceParams */ + 0, /* ulCtrlPort1 - NOT USED */ + 0, /* ulCtrlPort2 - NOT USED */ + 0, /* ulDataPort - NOT USED */ + NULL, /* getRegister - NOT USED */ + NULL, /* setRegister - NOT USED */ + NULL, /* getData - NOT USED */ + NULL, /* setData - NOT USED */ + 0, /* ulClock - NOT USED */ + 0 /* ulIntVector - NOT USED */ +} +#if 0 +{ + "/dev/com1", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &uart_fns, /* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 0, /* ulMargin - NOT USED */ + 0, /* ulHysteresis - NOT USED */ + NULL, /* pDeviceParams */ + 0, /* ulCtrlPort1 - NOT USED */ + 0, /* ulCtrlPort2 - NOT USED */ + 0, /* ulDataPort - NOT USED */ + NULL, /* getRegister - NOT USED */ + NULL, /* setRegister - NOT USED */ + NULL, /* getData - NOT USED */ + NULL, /* setData - NOT USED */ + 0, /* ulClock - NOT USED */ + 0 /* ulIntVector - NOT USED */ +} +#endif +}; + +/* + * This is called the first time each device is opened. If the driver + * is interrupt driven, you should enable interrupts here. Otherwise, + * it's probably safe to do nothing. + * + * Since micromonitor already set up the UART, we do nothing. + */ +static int uart_first_open(int major, int minor, void *arg) +{ + return 0; +} + +/* + * This is called the last time each device is closed. If the driver + * is interrupt driven, you should disable interrupts here. Otherwise, + * it's probably safe to do nothing. + */ +static int uart_last_close(int major, int minor, void *arg) +{ + return 0; +} + +/* + * Read one character from UART. + * + * Return -1 if there's no data, otherwise return + * the character in lowest 8 bits of returned int. + */ +static int uart_read(int minor) +{ + char c; + + switch (minor) { + case 0: + if (U0LSR & ULSR_RDR) { + c = U0RBR; + return c; + } + return -1; + case 1: + if (U1LSR & ULSR_RDR) { + c = U1RBR; + return c; + } + return -1; + default: + break; + } + printk("Unknown console minor number %d\n", minor); + return -1; +} + +/* + * Write buffer to UART + * + * return 1 on success, -1 on error + */ +static ssize_t uart_write(int minor, const char *buf, size_t len) +{ + size_t i; + + switch (minor) { + case 0: + for (i = 0; i < len; i++) { + while (!(U0LSR & ULSR_THRE)) /* wait for TX buffer to empty*/ + continue; /* also either WDOG() or swap()*/ + U0THR = (char) buf[i]; + } + break; + case 1: + for (i = 0; i < len; i++) { + while (!(U0LSR & ULSR_THRE)) /* wait for TX buffer to empty*/ + continue; /* also either WDOG() or swap()*/ + U0THR = (char) buf[i]; + } + break; + default: + printk("Unknown console minor number %d\n", minor); + return -1; + } + + return len; +} + +/* Set up the UART. */ +static void uart_init(int minor) +{ +#if 0 //init will be done in bspstart.c + int baud=6; + int mode =0x03; + if(minor==0){ + // set port pins for UART0 + PINSEL0 = (PINSEL0 & ~U0_PINMASK) | U0_PINSEL; + + U0IER = 0x00; // disable all interrupts + + // set the baudrate + U0LCR = 1<<7; // select divisor latches + U0DLL = (uint8_t)baud; // set for baud low byte + U0DLM = (uint8_t)(baud >> 8); // set for baud high byte + + // set the number of characters and other + // user specified operating parameters + U0LCR = (mode & ~ULCR_DLAB_ENABLE); + U0FCR = mode>>8; /*fifo mode*/ + + // set port pins for UART1 + PINSEL0 = (PINSEL0 & ~U1_PINMASK) | U1_PINSEL; + + U1IER = 0x00; // disable all interrupts + }else if(minor==1){ + // set the baudrate + U1LCR = ULCR_DLAB_ENABLE; // select divisor latches + U1DLL = (uint8_t)baud; // set for baud low byte + U1DLM = (uint8_t)(baud >> 8); // set for baud high byte + + // set the number of characters and other + // user specified operating parameters + U1LCR = (mode & ~ULCR_DLAB_ENABLE); + U1FCR = mode>>8;/*fifo mode*/ + } + +#endif +} + +/* I'm not sure this is needed for the shared console driver. */ +static void uart_write_polled(int minor, char c) +{ + uart_write(minor, &c, 1); +} + +/* This is for setting baud rate, bits, etc. */ +static int uart_set_attributes(int minor, const struct termios *t) +{ + return 0; +} + +/* + * Write a character to the console. This is used by printk() and + * maybe other low level functions. It should not use interrupts or any + * RTEMS system calls. It needs to be very simple + */ +static void _BSP_put_char( char c ) +{ + uart_write_polled(0, c); +} + +BSP_output_char_function_type BSP_output_char = _BSP_put_char; + +static int _BSP_get_char(void) +{ + return uart_read(0); +} + +BSP_polling_getchar_function_type BSP_poll_char = _BSP_get_char; + +/* + * init USART 0¡£8 bit, 1 Stop,No checkout, BPS115200 + */ +void UART0_Ini(void) +{ + long Fdiv; + int i; + + PINSEL0 = 0x00000005; // I/O to UART0 + U0LCR = 0x83; // DLAB = 1 + Fdiv = (Fpclk >>4) / UART_BPS; // configure BPS + U0DLM = Fdiv/256; + U0DLL = Fdiv%256; + U0LCR = 0x03; + + for(i=0;i<10;i++){ + U0THR = 67; //send a C to see if is OK + while ( (U0LSR&0x40)==0 ); + } +} diff --git a/bsps/arm/smdk2410/console/uart.c b/bsps/arm/smdk2410/console/uart.c new file mode 100644 index 0000000000..06adecf239 --- /dev/null +++ b/bsps/arm/smdk2410/console/uart.c @@ -0,0 +1,242 @@ +/* + * console driver for S3C2400 UARTs + * + * This driver uses the shared console driver in + * ...../libbsp/shared/console.c + * + * If you want the driver to be interrupt driven, you + * need to write the ISR, and in the ISR insert the + * chars into termios's queue. + * + * Copyright (c) 2004 Cogent Computer Systems + * Written by Jay Monkman <jtm@lopingdog.com> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. +*/ +#include <bsp.h> /* Must be before libio.h */ +#include <rtems/libio.h> +#include <termios.h> +#include <rtems/bspIo.h> + +/* Put the CPU (or UART) specific header file #include here */ +#include <s3c24xx.h> +#include <libchip/serial.h> +#include <libchip/sersupp.h> + +/* How many serial ports? */ +#define NUM_DEVS 1 + +int uart_poll_read(int minor); + +int dbg_dly; + +/* static function prototypes */ +static int uart_first_open(int major, int minor, void *arg); +static int uart_last_close(int major, int minor, void *arg); +static int uart_read(int minor); +static ssize_t uart_write(int minor, const char *buf, size_t len); +static void uart_init(int minor); +static void uart_write_polled(int minor, char c); +static int uart_set_attributes(int minor, const struct termios *t); + +/* These are used by code in console.c */ +unsigned long Console_Configuration_Count = NUM_DEVS; + +/* Pointers to functions for handling the UART. */ +const console_fns uart_fns = +{ + libchip_serial_default_probe, + uart_first_open, + uart_last_close, + uart_read, + uart_write, + uart_init, + uart_write_polled, /* not used in this driver */ + uart_set_attributes, + FALSE /* TRUE if interrupt driven, FALSE if not. */ +}; + +/* + * There's one item in array for each UART. + * + * Some of these fields are marked "NOT USED". They are not used + * by console.c, but may be used by drivers in libchip + * + */ +console_tbl Console_Configuration_Ports[] = { + { + "/dev/com0", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &uart_fns, /* pDeviceFns */ + NULL, /* deviceProbe */ + NULL, /* pDeviceFlow */ + 0, /* ulMargin - NOT USED */ + 0, /* ulHysteresis - NOT USED */ + NULL, /* pDeviceParams */ + 0, /* ulCtrlPort1 - NOT USED */ + 0, /* ulCtrlPort2 - NOT USED */ + 0, /* ulDataPort - NOT USED */ + NULL, /* getRegister - NOT USED */ + NULL, /* setRegister - NOT USED */ + NULL, /* getData - NOT USED */ + NULL, /* setData - NOT USED */ + 0, /* ulClock - NOT USED */ + 0 /* ulIntVector - NOT USED */ + } +}; + +/*********************************************************************/ +/* Functions called via termios callbacks (i.e. the ones in uart_fns */ +/*********************************************************************/ + +/* + * This is called the first time each device is opened. If the driver + * is interrupt driven, you should enable interrupts here. Otherwise, + * it's probably safe to do nothing. + * + * Since micromonitor already set up the UART, we do nothing. + */ +static int uart_first_open(int major, int minor, void *arg) +{ + return 0; +} + + +/* + * This is called the last time each device is closed. If the driver + * is interrupt driven, you should disable interrupts here. Otherwise, + * it's probably safe to do nothing. + */ +static int uart_last_close(int major, int minor, void *arg) +{ + return 0; +} + + +/* + * Read one character from UART. + * + * Return -1 if there's no data, otherwise return + * the character in lowest 8 bits of returned int. + */ +static int uart_read(int minor) +{ + char c; + + if (minor == 0) { + if (rUTRSTAT0 & 0x1) { + c = rURXH0 & 0xff; + return c; + } else { + return -1; + } + } else { + printk("Unknown console minor number: %d\n", minor); + return -1; + } + +} + + +/* + * Write buffer to UART + * + * return 1 on success, -1 on error + */ +static ssize_t uart_write(int minor, const char *buf, size_t len) +{ + int i; + + if (minor == 0) { + for (i = 0; i < len; i++) { + /* Wait for fifo to have room */ + while(!(rUTRSTAT0 & 0x2)) { + continue; + } + + rUTXH0 = (char) buf[i]; + } + } else { + printk("Unknown console minor number: %d\n", minor); + return -1; + } + + return 1; +} + + +/* Set up the UART. */ +static void uart_init(int minor) +{ + int i; + unsigned int reg = 0; + + /* enable UART0 */ + rCLKCON|=0x100; + + /* value is calculated so : (int)(PCLK/16./baudrate) -1 */ + reg = get_PCLK() / (16 * 115200) - 1; + + /* FIFO enable, Tx/Rx FIFO clear */ + rUFCON0 = 0x07; + rUMCON0 = 0x0; + /* Normal,No parity,1 stop,8 bit */ + rULCON0 = 0x3; + /* + * tx=level,rx=edge,disable timeout int.,enable rx error int., + * normal,interrupt or polling + */ + rUCON0 = 0x245; + rUBRDIV0 = reg; + + for (i = 0; i < 100; i++); + +} + +/* I'm not sure this is needed for the shared console driver. */ +static void uart_write_polled(int minor, char c) +{ + uart_write(minor, &c, 1); +} + +/* This is for setting baud rate, bits, etc. */ +static int uart_set_attributes(int minor, const struct termios *t) +{ + return 0; +} + +/***********************************************************************/ +/* + * The following functions are not used by TERMIOS, but other RTEMS + * functions use them instead. + */ +/***********************************************************************/ +/* + * Read from UART. This is used in the exit code, and can't + * rely on interrupts. +*/ +int uart_poll_read(int minor) +{ + return uart_read(minor); +} + + +/* + * Write a character to the console. This is used by printk() and + * maybe other low level functions. It should not use interrupts or any + * RTEMS system calls. It needs to be very simple + */ +static void _BSP_put_char( char c ) { + uart_write_polled(0, c); +} + +BSP_output_char_function_type BSP_output_char = _BSP_put_char; + +static int _BSP_get_char(void) +{ + return uart_poll_read(0); +} + +BSP_polling_getchar_function_type BSP_poll_char = _BSP_get_char; diff --git a/bsps/arm/stm32f4/console/console-config.c b/bsps/arm/stm32f4/console/console-config.c new file mode 100644 index 0000000000..6bf2d7e3b5 --- /dev/null +++ b/bsps/arm/stm32f4/console/console-config.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/bspIo.h> + +#include <libchip/serial.h> + +#include <bspopts.h> +#include <bsp/irq.h> +#include <bsp/usart.h> +#include <bsp/stm32f4.h> + +console_tbl Console_Configuration_Ports [] = { + #ifdef STM32F4_ENABLE_USART_1 + { + .sDeviceName = "/dev/ttyS0", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &stm32f4_usart_fns, + .ulCtrlPort1 = (uint32_t) STM32F4_USART_1, + .ulCtrlPort2 = 0, + .ulClock = STM32F4_USART_BAUD, + .ulIntVector = STM32F4_IRQ_USART1 + }, + #endif + #ifdef STM32F4_ENABLE_USART_2 + { + .sDeviceName = "/dev/ttyS1", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &stm32f4_usart_fns, + .ulCtrlPort1 = (uint32_t) STM32F4_USART_2, + .ulCtrlPort2 = 1, + .ulClock = STM32F4_USART_BAUD, + .ulIntVector = STM32F4_IRQ_USART2 + }, + #endif + #ifdef STM32F4_ENABLE_USART_3 + { + .sDeviceName = "/dev/ttyS2", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &stm32f4_usart_fns, + .ulCtrlPort1 = (uint32_t) STM32F4_USART_3, + .ulCtrlPort2 = 2, + .ulClock = STM32F4_USART_BAUD, + .ulIntVector = STM32F4_IRQ_USART3 + }, + #endif + #ifdef STM32F4_ENABLE_UART_4 + { + .sDeviceName = "/dev/ttyS3", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &stm32f4_usart_fns, + .ulCtrlPort1 = (uint32_t) STM32F4_USART_4, + .ulCtrlPort2 = 3, + .ulClock = STM32F4_USART_BAUD, + .ulIntVector = STM32F4_IRQ_UART4 + }, + #endif + #ifdef STM32F4_ENABLE_UART_5 + { + .sDeviceName = "/dev/ttyS4", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &stm32f4_usart_fns, + .ulCtrlPort1 = (uint32_t) STM32F4_USART_5, + .ulCtrlPort2 = 4, + .ulClock = STM32F4_USART_BAUD, + .ulIntVector = STM32F4_IRQ_UART5 + }, + #endif + #ifdef STM32F4_ENABLE_USART_6 + { + .sDeviceName = "/dev/ttyS5", + .deviceType = SERIAL_CUSTOM, + .pDeviceFns = &stm32f4_usart_fns, + .ulCtrlPort1 = (uint32_t) STM32F4_USART_6, + .ulCtrlPort2 = 5, + .ulClock = STM32F4_USART_BAUD, + .ulIntVector = STM32F4_IRQ_USART6 + }, + #endif +}; + +#define PORT_COUNT \ + (sizeof(Console_Configuration_Ports) \ + / sizeof(Console_Configuration_Ports [0])) + +unsigned long Console_Configuration_Count = PORT_COUNT; + +static void output_char(char c) +{ + const console_fns *con = + Console_Configuration_Ports [Console_Port_Minor].pDeviceFns; + + con->deviceWritePolled((int) Console_Port_Minor, c); +} + +BSP_output_char_function_type BSP_output_char = output_char; + +BSP_polling_getchar_function_type BSP_poll_char = NULL; diff --git a/bsps/arm/stm32f4/console/usart.c b/bsps/arm/stm32f4/console/usart.c new file mode 100644 index 0000000000..24e010d6bf --- /dev/null +++ b/bsps/arm/stm32f4/console/usart.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <libchip/sersupp.h> + +#include <bsp.h> +#include <bsp/io.h> +#include <bsp/rcc.h> +#include <bsp/irq.h> +#include <bsp/usart.h> +#include <bsp/stm32f4.h> + +static volatile stm32f4_usart *usart_get_regs(const console_tbl *ct) +{ + return (stm32f4_usart *) ct->ulCtrlPort1; +} + +#if 0 +static rtems_vector_number usart_get_irq_number(const console_tbl *ct) +{ + return ct->ulIntVector; +} +#endif + +static const stm32f4_rcc_index usart_rcc_index [] = { + STM32F4_RCC_USART1, + STM32F4_RCC_USART2, + STM32F4_RCC_USART3, + STM32F4_RCC_UART4, + STM32F4_RCC_UART5, +#ifdef STM32F4_FAMILY_F4XXXX + STM32F4_RCC_USART6 +#endif /* STM32F4_FAMILY_F4XXXX */ +}; + +static stm32f4_rcc_index usart_get_rcc_index(const console_tbl *ct) +{ + return usart_rcc_index [ct->ulCtrlPort2]; +} + +static const uint8_t usart_pclk_index [] = { 1, 0, 0, 0, 0, 1 }; + +static const uint32_t usart_pclk_by_index [] = { + STM32F4_PCLK1, + STM32F4_PCLK2 +}; + +static uint32_t usart_get_pclk(const console_tbl *ct) +{ + return usart_pclk_by_index [usart_pclk_index [ct->ulCtrlPort2]]; +} + +static uint32_t usart_get_baud(const console_tbl *ct) +{ + return ct->ulClock; +} + +/* + * a = 8 * (2 - CR1[OVER8]) + * + * usartdiv = div_mantissa + div_fraction / a + * + * baud = pclk / (a * usartdiv) + * + * usartdiv = pclk / (a * baud) + * + * Calculation in integer arithmetic: + * + * 1. div_mantissa = pclk / (a * baud) + * + * 2. div_fraction = pclk / (baud - a * div_mantissa) + */ +static uint32_t usart_get_bbr( + volatile stm32f4_usart *usart, + uint32_t pclk, + uint32_t baud +) +{ + uint32_t a = 8 * (2 - ((usart->cr1 & STM32F4_USART_CR1_OVER8) != 0)); + uint32_t div_mantissa_low = pclk / (a * baud); + uint32_t div_fraction_low = pclk / (baud - a * div_mantissa_low); + uint32_t div_mantissa_high; + uint32_t div_fraction_high; + uint32_t high_err; + uint32_t low_err; + uint32_t div_mantissa; + uint32_t div_fraction; + + if (div_fraction_low < a - 1) { + div_mantissa_high = div_fraction_low; + div_fraction_high = div_fraction_low + 1; + } else { + div_mantissa_high = div_fraction_low + 1; + div_fraction_high = 0; + } + + high_err = pclk - baud * (a * div_mantissa_high + div_fraction_high); + low_err = baud * (a * div_mantissa_low + div_fraction_low) - pclk; + + if (low_err < high_err) { + div_mantissa = div_mantissa_low; + div_fraction = div_fraction_low; + } else { + div_mantissa = div_mantissa_high; + div_fraction = div_fraction_high; + } + + return STM32F4_USART_BBR_DIV_MANTISSA(div_mantissa) + | STM32F4_USART_BBR_DIV_FRACTION(div_fraction); +} + +static void usart_initialize(int minor) +{ + const console_tbl *ct = Console_Port_Tbl [minor]; + volatile stm32f4_usart *usart = usart_get_regs(ct); + uint32_t pclk = usart_get_pclk(ct); + uint32_t baud = usart_get_baud(ct); + stm32f4_rcc_index rcc_index = usart_get_rcc_index(ct); + + stm32f4_rcc_set_clock(rcc_index, true); + + usart->cr1 = 0; + usart->cr2 = 0; + usart->cr3 = 0; + usart->bbr = usart_get_bbr(usart, pclk, baud); + usart->cr1 = STM32F4_USART_CR1_UE + | STM32F4_USART_CR1_TE + | STM32F4_USART_CR1_RE; +} + +static int usart_first_open(int major, int minor, void *arg) +{ + rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg; + struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1; + const console_tbl *ct = Console_Port_Tbl [minor]; + console_data *cd = &Console_Port_Data [minor]; + + cd->termios_data = tty; + rtems_termios_set_initial_baud(tty, ct->ulClock); + + return 0; +} + +static int usart_last_close(int major, int minor, void *arg) +{ + return 0; +} + +static int usart_read_polled(int minor) +{ + const console_tbl *ct = Console_Port_Tbl [minor]; + volatile stm32f4_usart *usart = usart_get_regs(ct); + + if ((usart->sr & STM32F4_USART_SR_RXNE) != 0) { + return STM32F4_USART_DR_GET(usart->dr); + } else { + return -1; + } +} + +static void usart_write_polled(int minor, char c) +{ + const console_tbl *ct = Console_Port_Tbl [minor]; + volatile stm32f4_usart *usart = usart_get_regs(ct); + + while ((usart->sr & STM32F4_USART_SR_TXE) == 0) { + /* Wait */ + } + + usart->dr = STM32F4_USART_DR(c); +} + +static ssize_t usart_write_support_polled( + int minor, + const char *s, + size_t n +) +{ + ssize_t i = 0; + + for (i = 0; i < n; ++i) { + usart_write_polled(minor, s [i]); + } + + return n; +} + +static int usart_set_attributes(int minor, const struct termios *term) +{ + return -1; +} + +const console_fns stm32f4_usart_fns = { + .deviceProbe = libchip_serial_default_probe, + .deviceFirstOpen = usart_first_open, + .deviceLastClose = usart_last_close, + .deviceRead = usart_read_polled, + .deviceWrite = usart_write_support_polled, + .deviceInitialize = usart_initialize, + .deviceWritePolled = usart_write_polled, + .deviceSetAttributes = usart_set_attributes, + .deviceOutputUsesInterrupts = false +}; diff --git a/bsps/arm/tms570/console/printk-support.c b/bsps/arm/tms570/console/printk-support.c new file mode 100644 index 0000000000..529c5dba20 --- /dev/null +++ b/bsps/arm/tms570/console/printk-support.c @@ -0,0 +1,126 @@ +/** + * @file printk-support.c + * + * @ingroup tms570 + * + * @brief definitions of serial line for debugging. + */ + +/* + * Copyright (c) 2014 Premysl Houdek <kom541000@gmail.com> + * + * Google Summer of Code 2014 at + * Czech Technical University in Prague + * Zikova 1903/4 + * 166 36 Praha 6 + * Czech Republic + * + * Based on LPC24xx and LPC1768 BSP + * by embedded brains GmbH and others + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/bspIo.h> +#include <rtems/sysinit.h> +#include <stdint.h> +#include <string.h> +#include <bsp/tms570-sci.h> +#include <bsp/tms570-sci-driver.h> + +#define TMS570_CONSOLE (&driver_context_table[0]) + +/** + * @brief Puts chars into peripheral + * + * debug functions always use serial dev 0 peripheral + * + * @retval Void + */ +static void tms570_debug_console_putc(char ch) +{ + tms570_sci_context *ctx = TMS570_CONSOLE; + volatile tms570_sci_t *regs = ctx->regs; + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + while ( ( regs->FLR & TMS570_SCI_FLR_TXRDY ) == 0) { + rtems_interrupt_flash(level); + } + regs->TD = ch; + while ( ( regs->FLR & TMS570_SCI_FLR_TX_EMPTY ) == 0) { + rtems_interrupt_flash(level); + } + rtems_interrupt_enable(level); +} + +/** + * @brief debug console output + * + * debug functions always use serial dev 0 peripheral + * + * @retval Void + */ +static void tms570_debug_console_out(char c) +{ + tms570_debug_console_putc(c); +} + +static void tms570_debug_console_init(void) +{ + tms570_sci_context *ctx = TMS570_CONSOLE; + struct termios term; + + tms570_sci_initialize(ctx); + memset(&term, 0, sizeof(term)); + term.c_cflag = B115200; + tms570_sci_set_attributes(&ctx->base, &term); + BSP_output_char = tms570_debug_console_out; +} + +static void tms570_debug_console_early_init(char c) +{ + tms570_debug_console_init(); + tms570_debug_console_out(c); +} + +/** + * @brief debug console input + * + * debug functions always use serial dev 0 peripheral + * + * @retval x Read char + * @retval -1 No input character available + */ +static int tms570_debug_console_in( void ) +{ + tms570_sci_context *ctx = TMS570_CONSOLE; + volatile tms570_sci_t *regs = ctx->regs; + rtems_interrupt_level level; + int c; + + rtems_interrupt_disable(level); + + if ( regs->FLR & TMS570_SCI_FLR_RXRDY ) { + c = (unsigned char) regs->RD; + } else { + c = -1; + } + + rtems_interrupt_enable(level); + + return c; +} + +BSP_output_char_function_type BSP_output_char = + tms570_debug_console_early_init; + +BSP_polling_getchar_function_type BSP_poll_char = tms570_debug_console_in; + +RTEMS_SYSINIT_ITEM( + tms570_debug_console_init, + RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_LAST +); diff --git a/bsps/arm/tms570/console/tms570-sci.c b/bsps/arm/tms570/console/tms570-sci.c new file mode 100644 index 0000000000..48986e9a2e --- /dev/null +++ b/bsps/arm/tms570/console/tms570-sci.c @@ -0,0 +1,642 @@ +/** + * @file tms570-sci.c + * + * @ingroup tms570 + * + * @brief Serial communication interface (SCI) functions definitions. + */ + +/* + * Copyright (c) 2014 Premysl Houdek <kom541000@gmail.com> + * + * Google Summer of Code 2014 at + * Czech Technical University in Prague + * Zikova 1903/4 + * 166 36 Praha 6 + * Czech Republic + * + * Based on LPC24xx and LPC1768 BSP + * by embedded brains GmbH and others + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bspopts.h> +#include <termios.h> +#include <rtems/termiostypes.h> +#include <bsp/tms570-sci.h> +#include <bsp/tms570-sci-driver.h> +#include <rtems/console.h> +#include <bsp.h> +#include <bsp/fatal.h> +#include <bsp/irq.h> + +#define TMS570_SCI_BUFFER_SIZE 1 + +/** + * @brief Table including all serial drivers + * + * Definitions of all serial drivers + */ +tms570_sci_context driver_context_table[] = { + { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("TMS570 SCI1"), + .device_name = "/dev/console", + /* TMS570 UART peripheral use subset of LIN registers which are equivalent + * to SCI ones + */ + .regs = (volatile tms570_sci_t *) &TMS570_LIN, + .irq = TMS570_IRQ_SCI_LEVEL_0, + }, + { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("TMS570 SCI2"), + .device_name = "/dev/ttyS1", + .regs = &TMS570_SCI, + .irq = TMS570_IRQ_SCI2_LEVEL_0, + } +}; + +void tms570_sci_initialize(tms570_sci_context *ctx) +{ + uint32_t rx_pin = 1 << 1; + uint32_t tx_pin = 1 << 2; + + /* Resec SCI peripheral */ + ctx->regs->GCR0 = TMS570_SCI_GCR0_RESET * 0; + ctx->regs->GCR0 = TMS570_SCI_GCR0_RESET * 1; + + /* Clear all interrupt sources */ + ctx->regs->CLEARINT = 0xffffffff; + + /* Map all interrupts to SCI INT0 line */ + ctx->regs->CLEARINTLVL = 0xffffffff; + + ctx->regs->GCR1 = TMS570_SCI_GCR1_TXENA * 0 | + TMS570_SCI_GCR1_RXENA * 0 | + TMS570_SCI_GCR1_CONT * 0 | /* continue operation when debugged */ + TMS570_SCI_GCR1_LOOP_BACK * 0 | + TMS570_SCI_GCR1_POWERDOWN * 0 | + TMS570_SCI_GCR1_SLEEP * 0 | + TMS570_SCI_GCR1_SWnRST * 0 | /* reset state */ + TMS570_SCI_GCR1_CLOCK * 1 | /* internal clock */ + TMS570_SCI_GCR1_TIMING_MODE * 1 | + TMS570_SCI_GCR1_COMM_MODE * 0; + + /* Setup connection of SCI peripheral Rx and Tx pins */ + ctx->regs->PIO0 = rx_pin * 1 | tx_pin * 1; /* Rx and Tx pins are not GPIO */ + ctx->regs->PIO3 = rx_pin * 0 | tx_pin * 0; /* Default output low */ + ctx->regs->PIO1 = rx_pin * 0 | tx_pin * 0; /* Input when not used by SCI */ + ctx->regs->PIO6 = rx_pin * 0 | tx_pin * 0; /* No open drain */ + ctx->regs->PIO7 = rx_pin * 0 | tx_pin * 0; /* Pull-up/down enabled */ + ctx->regs->PIO8 = rx_pin * 1 | tx_pin * 1; /* Select pull-up */ + + /* Bring device out of software reset */ + ctx->regs->GCR1 |= TMS570_SCI_GCR1_SWnRST; +} + +/** + * @brief Serial drivers init function + * + * Initialize all serial drivers specified in driver_context_table + * + * @param[in] major + * @param[in] minor + * @param[in] arg + * @retval RTEMS_SUCCESSFUL Initialization completed + */ +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code sc; +#if CONSOLE_USE_INTERRUPTS + const rtems_termios_device_handler *handler = &tms570_sci_handler_interrupt; +#else + const rtems_termios_device_handler *handler = &tms570_sci_handler_polled; +#endif + + /* + * Initialize the Termios infrastructure. If Termios has already + * been initialized by another device driver, then this call will + * have no effect. + */ + rtems_termios_initialize(); + + /* Initialize each device */ + for ( + minor = 0; + minor < RTEMS_ARRAY_SIZE(driver_context_table); + ++minor + ) { + tms570_sci_context *ctx = &driver_context_table[minor]; + + tms570_sci_initialize(ctx); + + /* + * Install this device in the file system and Termios. In order + * to use the console (i.e. being able to do printf, scanf etc. + * on stdin, stdout and stderr), one device must be registered as + * "/dev/console" (CONSOLE_DEVICE_NAME). + */ + sc = rtems_termios_device_install( + ctx->device_name, + handler, + NULL, + &ctx->base + ); + if ( sc != RTEMS_SUCCESSFUL ) { + bsp_fatal(BSP_FATAL_CONSOLE_NO_DEV); + } + } + return RTEMS_SUCCESSFUL; +} + +/** + * @brief Reads chars from HW + * + * Reads chars from HW peripheral specified in driver context. + * TMS570 does not have HW buffer for serial line so this function can + * return only 0 or 1 char + * + * @param[in] ctx context of the driver + * @param[out] buf read data buffer + * @param[in] N size of buffer + * @retval x Number of read chars from peripherals + */ +static int tms570_sci_read_received_chars( + tms570_sci_context * ctx, + char * buf, + int N) +{ + if ( N < 1 ) { + return 0; + } + if ( ctx->regs->RD != 0 ) { + buf[0] = ctx->regs->RD; + return 1; + } + return 0; +} + +/** + * @brief Enables RX interrupt + * + * Enables RX interrupt source of SCI peripheral + * specified in the driver context. + * + * @param[in] ctx context of the driver + * @retval Void + */ +static void tms570_sci_enable_interrupts(tms570_sci_context * ctx) +{ + ctx->regs->SETINT = TMS570_SCI_SETINT_SET_RX_INT; +} + +/** + * @brief Disables RX interrupt + * + * Disables RX interrupt source of SCI peripheral specified in the driver + * context. + * + * @param[in] ctx context of the driver + * @retval Void + */ +static void tms570_sci_disable_interrupts(tms570_sci_context * ctx) +{ + ctx->regs->CLEARINT = TMS570_SCI_CLEARINT_CLR_RX_INT; +} + +/** + * @brief Check whether driver has put char in HW + * + * Check whether driver has put char in HW. + * This information is read from the driver context not from a peripheral. + * TMS570 does not have write data buffer asociated with SCI + * so the return can be only 0 or 1. + * + * @param[in] ctx context of the driver + * @retval x + */ +static int tms570_sci_transmitted_chars(tms570_sci_context * ctx) +{ + int ret; + + ret = ctx->tx_chars_in_hw; + if ( ret == 1 ) { + ctx->tx_chars_in_hw = 0; + return 1; + } + return ret; +} + +/** + * @brief Set attributes of the HW peripheral + * + * Sets attributes of the HW peripheral (parity, baud rate, etc.) + * + * @param[in] base context of the driver + * @param[in] t termios driver + * @retval true peripheral setting is changed + */ +bool tms570_sci_set_attributes( + rtems_termios_device_context *base, + const struct termios *t +) +{ + tms570_sci_context *ctx = (tms570_sci_context *) base; + rtems_interrupt_lock_context lock_context; + int32_t bauddiv; + int32_t baudrate; + uint32_t flr_tx_ready = TMS570_SCI_FLR_TX_EMPTY; + /* + * Test for TMS570_SCI_FLR_TXRDY is not necessary + * because both SCITD and SCITXSHF has to be empty + * to TX_EMPTY be asserted. But there is no interrupt + * option for TX_EMPTY. Polling is used isntead. + */ + + /* Baud rate */ + baudrate = rtems_termios_baud_to_number(cfgetospeed(t)); + + rtems_termios_device_lock_acquire(base, &lock_context); + + while ( (ctx->regs->GCR1 & TMS570_SCI_GCR1_TXENA) && + (ctx->regs->FLR & flr_tx_ready) != flr_tx_ready) { + /* + * There are pending characters in the hardware, + * change in the middle of the character Tx leads + * to disturb of the character and SCI engine + */ + rtems_interval tw; + + rtems_termios_device_lock_release(base, &lock_context); + + tw = rtems_clock_get_ticks_per_second(); + tw = tw * 5 / baudrate + 1; + rtems_task_wake_after( tw ); + + rtems_termios_device_lock_acquire(base, &lock_context); + } + + ctx->regs->GCR1 &= ~( TMS570_SCI_GCR1_SWnRST | TMS570_SCI_GCR1_TXENA | + TMS570_SCI_GCR1_RXENA ); + + ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_STOP; /*one stop bit*/ + ctx->regs->FORMAT = TMS570_SCI_FORMAT_CHAR(0x7); + + switch ( t->c_cflag & ( PARENB|PARODD ) ) { + case ( PARENB|PARODD ): + /* Odd parity */ + ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_PARITY; + ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY_ENA; + break; + + case PARENB: + /* Even parity */ + ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY; + ctx->regs->GCR1 |= TMS570_SCI_GCR1_PARITY_ENA; + break; + + default: + case 0: + case PARODD: + /* No Parity */ + ctx->regs->GCR1 &= ~TMS570_SCI_GCR1_PARITY_ENA; + } + + /* Apply baudrate to the hardware */ + baudrate *= 2 * 16; + bauddiv = (BSP_PLL_OUT_CLOCK + baudrate / 2) / baudrate; + ctx->regs->BRS = bauddiv; + + ctx->regs->GCR1 |= TMS570_SCI_GCR1_SWnRST | TMS570_SCI_GCR1_TXENA | + TMS570_SCI_GCR1_RXENA; + + rtems_termios_device_lock_release(base, &lock_context); + + return true; +} + +/** + * @brief sci interrupt handler + * + * Handler checks which interrupt occured and provides nessesary maintenance + * dequeue characters in termios driver whether character is send succesfully + * enqueue characters in termios driver whether character is recieved + * + * @param[in] arg rtems_termios_tty + * @retval Void + */ +static void tms570_sci_interrupt_handler(void * arg) +{ + rtems_termios_tty *tty = arg; + tms570_sci_context *ctx = rtems_termios_get_device_context(tty); + char buf[TMS570_SCI_BUFFER_SIZE]; + size_t n; + + /* + * Check if we have received something. + */ + if ( (ctx->regs->FLR & TMS570_SCI_FLR_RXRDY ) == TMS570_SCI_FLR_RXRDY ) { + n = tms570_sci_read_received_chars(ctx, buf, TMS570_SCI_BUFFER_SIZE); + if ( n > 0 ) { + /* Hand the data over to the Termios infrastructure */ + rtems_termios_enqueue_raw_characters(tty, buf, n); + } + } + /* + * Check if we have something transmitted. + */ + if ( (ctx->regs->FLR & TMS570_SCI_FLR_TXRDY ) == TMS570_SCI_FLR_TXRDY ) { + n = tms570_sci_transmitted_chars(ctx); + if ( n > 0 ) { + /* + * Notify Termios that we have transmitted some characters. It + * will call now the interrupt write function if more characters + * are ready for transmission. + */ + rtems_termios_dequeue_characters(tty, n); + } + } +} + +/** + * @brief sci write function called from interrupt + * + * Nonblocking write function. Writes characters to HW peripheral + * TMS570 does not have write data buffer asociated with SCI + * so only one character can be written. + * + * @param[in] base context of the driver + * @param[in] buf buffer of characters pending to send + * @param[in] len size of the buffer + * @retval Void + */ +static void tms570_sci_interrupt_write( + rtems_termios_device_context *base, + const char *buf, + size_t len +) +{ + tms570_sci_context *ctx = (tms570_sci_context *) base; + + if ( len > 0 ) { + /* start UART TX, this will result in an interrupt when done */ + ctx->regs->TD = *buf; + /* character written - raise count*/ + ctx->tx_chars_in_hw = 1; + /* Enable TX interrupt (interrupt is edge-triggered) */ + ctx->regs->SETINT = (1<<8); + + } else { + /* No more to send, disable TX interrupts */ + ctx->regs->CLEARINT = (1<<8); + /* Tell close that we sent everything */ + } +} + +/** + * @brief sci write function + * + * Blocking write function. Waits until HW peripheral is ready and then writes + * character to HW peripheral. Writes all characters in the buffer. + * + * @param[in] base context of the driver + * @param[in] buf buffer of characters pending to send + * @param[in] len size of the buffer + * @retval Void + */ +static void tms570_sci_poll_write( + rtems_termios_device_context *base, + const char *buf, + size_t n +) +{ + tms570_sci_context *ctx = (tms570_sci_context *) base; + size_t i; + + /* Write */ + + for ( i = 0; i < n; ++i ) { + while ( (ctx->regs->FLR & TMS570_SCI_FLR_TX_EMPTY ) == 0) { + ; + } + ctx->regs->TD = buf[i]; + } +} + +/** + * @brief See if there is recieved charakter to read + * + * read the RX flag from peripheral specified in context + * + * @param[in] ctx context of the driver + * @retval 0 No character to read + * @retval x Character ready to read + */ +static int TMS570_sci_can_read_char( + tms570_sci_context * ctx +) +{ + return ctx->regs->FLR & TMS570_SCI_FLR_RXRDY; +} + +/** + * @brief reads character from peripheral + * + * reads the recieved character from peripheral specified in context + * + * @param[in] ctx context of the driver + * @retval x Character + */ +static char TMS570_sci_read_char( + tms570_sci_context * ctx +) +{ + return ctx->regs->RD; +} + +/** + * @brief sci read function + * + * check if there is recieved character to be read and reads it. + * + * @param[in] base context of the driver + * @retval -1 No character to be read + * @retval x Read character + */ +static int tms570_sci_poll_read(rtems_termios_device_context *base) +{ + tms570_sci_context *ctx = (tms570_sci_context *) base; + + /* Check if a character is available */ + if ( TMS570_sci_can_read_char(ctx) ) { + return TMS570_sci_read_char(ctx); + } else { + return -1; + } +} + +/** + * @brief initialization of the driver + * + * initialization of the HW peripheral specified in contex of the driver. + * This function is called only once when opening the driver. + * + * @param[in] tty Termios control + * @param[in] ctx context of the driver + * @param[in] term Termios attributes + * @param[in] args + * @retval false Error occured during initialization + * @retval true Driver is open and ready + */ +static bool tms570_sci_poll_first_open( + rtems_termios_tty *tty, + rtems_termios_device_context *ctx, + struct termios *term, + rtems_libio_open_close_args_t *args +) +{ + bool ok; + + rtems_termios_set_best_baud(term, TMS570_SCI_BAUD_RATE); + ok = tms570_sci_set_attributes(ctx, term); + if ( !ok ) { + return false; + } + return true; +} + +/** + * @brief initialization of the interrupt driven driver + * + * calls tms570_sci_poll_first_open function. + * install and enables interrupts. + * + * @param[in] tty Termios control + * @param[in] base context of the driver + * @param[in] args + * @retval false Error occured during initialization + * @retval true Driver is open and ready + */ +static bool tms570_sci_interrupt_first_open( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + struct termios *term, + rtems_libio_open_close_args_t *args +) +{ + tms570_sci_context *ctx = (tms570_sci_context *) base; + rtems_status_code sc; + bool ret; + + ret = tms570_sci_poll_first_open(tty, base, term, args); + if ( ret == false ) { + return false; + } + + /* Register Interrupt handler */ + sc = rtems_interrupt_handler_install(ctx->irq, + ctx->device_name, + RTEMS_INTERRUPT_SHARED, + tms570_sci_interrupt_handler, + tty + ); + if ( sc != RTEMS_SUCCESSFUL ) { + return false; + } + tms570_sci_enable_interrupts(ctx); + return true; +} + +/** + * @brief closes sci peripheral + * + * @param[in] tty Termios control + * @param[in] base context of the driver + * @param[in] args + * @retval false Error occured during initialization + * @retval true Driver is open and ready + */ +static void tms570_sci_poll_last_close( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + rtems_libio_open_close_args_t *args +) +{ + ; +} + +/** + * @brief closes sci peripheral of interrupt driven driver + * + * calls tms570_sci_poll_last_close and disables interrupts + * + * @param[in] tty Termios control + * @param[in] base context of the driver + * @param[in] args + * @retval false Error occured during initialization + * @retval true Driver is open and ready + */ +static void tms570_sci_interrupt_last_close( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + rtems_libio_open_close_args_t *args +) +{ + tms570_sci_context *ctx = (tms570_sci_context *) base; + rtems_interrupt_lock_context lock_context; + rtems_interval tw; + int32_t baudrate; + + /* Turn off RX interrupts */ + rtems_termios_device_lock_acquire(base, &lock_context); + tms570_sci_disable_interrupts(ctx); + rtems_termios_device_lock_release(base, &lock_context); + + tw = rtems_clock_get_ticks_per_second(); + baudrate = rtems_termios_baud_to_number(cfgetospeed(&tty->termios)); + tw = tw * 10 / baudrate + 1; + while ( ( ctx->regs->FLR & TMS570_SCI_FLR_TX_EMPTY ) == 0 ) { + rtems_task_wake_after(tw); + } + + /* uninstall ISR */ + rtems_interrupt_handler_remove(ctx->irq, tms570_sci_interrupt_handler, tty); + + tms570_sci_poll_last_close(tty, base, args); +} + +/** + * @brief Struct containing definitions of polled driver functions. + * + * Encapsulates polled driver functions. + * Use of this table is determited by not defining TMS570_USE_INTERRUPTS + */ +const rtems_termios_device_handler tms570_sci_handler_polled = { + .first_open = tms570_sci_poll_first_open, + .last_close = tms570_sci_poll_last_close, + .poll_read = tms570_sci_poll_read, + .write = tms570_sci_poll_write, + .set_attributes = tms570_sci_set_attributes, + .mode = TERMIOS_POLLED +}; + +/** + * @brief Struct containing definitions of interrupt driven driver functions. + * + * Encapsulates interrupt driven driver functions. + * Use of this table is determited by defining TMS570_USE_INTERRUPTS + */ +const rtems_termios_device_handler tms570_sci_handler_interrupt = { + .first_open = tms570_sci_interrupt_first_open, + .last_close = tms570_sci_interrupt_last_close, + .poll_read = NULL, + .write = tms570_sci_interrupt_write, + .set_attributes = tms570_sci_set_attributes, + .mode = TERMIOS_IRQ_DRIVEN +}; diff --git a/bsps/arm/xilinx-zynq/console/console-config.c b/bsps/arm/xilinx-zynq/console/console-config.c new file mode 100644 index 0000000000..ce7da2f114 --- /dev/null +++ b/bsps/arm/xilinx-zynq/console/console-config.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/console.h> +#include <rtems/bspIo.h> + +#include <bsp/irq.h> +#include <bsp/zynq-uart.h> + +#include <bspopts.h> + +zynq_uart_context zynq_uart_instances[2] = { + { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "Zynq UART 0" ), + .regs = (volatile struct zynq_uart *) 0xe0000000, + .irq = ZYNQ_IRQ_UART_0 + }, { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "Zynq UART 1" ), + .regs = (volatile struct zynq_uart *) 0xe0001000, + .irq = ZYNQ_IRQ_UART_1 + } +}; + +rtems_status_code console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + size_t i; + + rtems_termios_initialize(); + + for (i = 0; i < RTEMS_ARRAY_SIZE(zynq_uart_instances); ++i) { + char uart[] = "/dev/ttySX"; + + uart[sizeof(uart) - 2] = (char) ('0' + i); + rtems_termios_device_install( + &uart[0], + &zynq_uart_handler, + NULL, + &zynq_uart_instances[i].base + ); + + if (i == BSP_CONSOLE_MINOR) { + link(&uart[0], CONSOLE_DEVICE_NAME); + } + } + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/xilinx-zynq/console/debug-console.c b/bsps/arm/xilinx-zynq/console/debug-console.c new file mode 100644 index 0000000000..38c0050e90 --- /dev/null +++ b/bsps/arm/xilinx-zynq/console/debug-console.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <rtems@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <rtems/bspIo.h> +#include <rtems/sysinit.h> + +#include <bsp/zynq-uart.h> + +#include <bspopts.h> + +static void zynq_debug_console_out(char c) +{ + rtems_termios_device_context *base = + &zynq_uart_instances[BSP_CONSOLE_MINOR].base; + + zynq_uart_write_polled(base, c); +} + +static void zynq_debug_console_init(void) +{ + rtems_termios_device_context *base = + &zynq_uart_instances[BSP_CONSOLE_MINOR].base; + + zynq_uart_initialize(base); + BSP_output_char = zynq_debug_console_out; +} + +static void zynq_debug_console_early_init(char c) +{ + rtems_termios_device_context *base = + &zynq_uart_instances[BSP_CONSOLE_MINOR].base; + + zynq_uart_initialize(base); + zynq_debug_console_out(c); +} + +static int zynq_debug_console_in(void) +{ + rtems_termios_device_context *base = + &zynq_uart_instances[BSP_CONSOLE_MINOR].base; + + return zynq_uart_read_polled(base); +} + +BSP_output_char_function_type BSP_output_char = zynq_debug_console_early_init; + +BSP_polling_getchar_function_type BSP_poll_char = zynq_debug_console_in; + +RTEMS_SYSINIT_ITEM( + zynq_debug_console_init, + RTEMS_SYSINIT_BSP_START, + RTEMS_SYSINIT_ORDER_LAST +); diff --git a/bsps/arm/xilinx-zynq/console/zynq-uart.c b/bsps/arm/xilinx-zynq/console/zynq-uart.c new file mode 100644 index 0000000000..fa91f3f46e --- /dev/null +++ b/bsps/arm/xilinx-zynq/console/zynq-uart.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2013, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * <info@embedded-brains.de> + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include <bsp/zynq-uart.h> +#include <bsp/zynq-uart-regs.h> +#include <bsp/irq.h> + +#include <bspopts.h> + +/* + * Make weak and let the user override. + */ +uint32_t zynq_uart_input_clock(void) __attribute__ ((weak)); + +uint32_t zynq_uart_input_clock(void) +{ + return ZYNQ_CLOCK_UART; +} + +static int zynq_cal_baud_rate(uint32_t baudrate, + uint32_t* brgr, + uint32_t* bauddiv, + uint32_t modereg) +{ + uint32_t brgr_value; /* Calculated value for baud rate generator */ + uint32_t calcbaudrate; /* Calculated baud rate */ + uint32_t bauderror; /* Diff between calculated and requested baud rate */ + uint32_t best_error = 0xFFFFFFFF; + uint32_t percenterror; + uint32_t bdiv; + uint32_t inputclk = zynq_uart_input_clock(); + + /* + * Make sure the baud rate is not impossilby large. + * Fastest possible baud rate is Input Clock / 2. + */ + if ((baudrate * 2) > inputclk) { + return -1; + } + /* + * Check whether the input clock is divided by 8 + */ + if(modereg & ZYNQ_UART_MODE_CLKS) { + inputclk = inputclk / 8; + } + + /* + * Determine the Baud divider. It can be 4to 254. + * Loop through all possible combinations + */ + for (bdiv = 4; bdiv < 255; bdiv++) { + + /* + * Calculate the value for BRGR register + */ + brgr_value = inputclk / (baudrate * (bdiv + 1)); + + /* + * Calculate the baud rate from the BRGR value + */ + calcbaudrate = inputclk/ (brgr_value * (bdiv + 1)); + + /* + * Avoid unsigned integer underflow + */ + if (baudrate > calcbaudrate) { + bauderror = baudrate - calcbaudrate; + } + else { + bauderror = calcbaudrate - baudrate; + } + + /* + * Find the calculated baud rate closest to requested baud rate. + */ + if (best_error > bauderror) { + *brgr = brgr_value; + *bauddiv = bdiv; + best_error = bauderror; + } + } + + /* + * Make sure the best error is not too large. + */ + percenterror = (best_error * 100) / baudrate; +#define XUARTPS_MAX_BAUD_ERROR_RATE 3 /* max % error allowed */ + if (XUARTPS_MAX_BAUD_ERROR_RATE < percenterror) { + return -1; + } + + return 0; +} + +void zynq_uart_initialize(rtems_termios_device_context *base) +{ + zynq_uart_context *ctx = (zynq_uart_context *) base; + volatile zynq_uart *regs = ctx->regs; + uint32_t brgr = 0x3e; + uint32_t bauddiv = 0x6; + + zynq_cal_baud_rate(ZYNQ_UART_DEFAULT_BAUD, &brgr, &bauddiv, regs->mode); + + regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN); + regs->control = ZYNQ_UART_CONTROL_RXDIS + | ZYNQ_UART_CONTROL_TXDIS + | ZYNQ_UART_CONTROL_RXRES + | ZYNQ_UART_CONTROL_TXRES; + regs->mode = ZYNQ_UART_MODE_CHMODE(ZYNQ_UART_MODE_CHMODE_NORMAL) + | ZYNQ_UART_MODE_PAR(ZYNQ_UART_MODE_PAR_NONE) + | ZYNQ_UART_MODE_CHRL(ZYNQ_UART_MODE_CHRL_8); + regs->baud_rate_gen = ZYNQ_UART_BAUD_RATE_GEN_CD(brgr); + regs->baud_rate_div = ZYNQ_UART_BAUD_RATE_DIV_BDIV(bauddiv); + regs->rx_fifo_trg_lvl = ZYNQ_UART_RX_FIFO_TRG_LVL_RTRIG(0); + regs->rx_timeout = ZYNQ_UART_RX_TIMEOUT_RTO(0); + regs->control = ZYNQ_UART_CONTROL_RXEN + | ZYNQ_UART_CONTROL_TXEN + | ZYNQ_UART_CONTROL_RSTTO; +} + +#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS +static void zynq_uart_interrupt(void *arg) +{ + rtems_termios_tty *tty = arg; + zynq_uart_context *ctx = rtems_termios_get_device_context(tty); + volatile zynq_uart *regs = ctx->regs; + uint32_t channel_sts; + + if ((regs->irq_sts & (ZYNQ_UART_TIMEOUT | ZYNQ_UART_RTRIG)) != 0) { + regs->irq_sts = ZYNQ_UART_TIMEOUT | ZYNQ_UART_RTRIG; + + do { + char c = (char) ZYNQ_UART_TX_RX_FIFO_FIFO_GET(regs->tx_rx_fifo); + + rtems_termios_enqueue_raw_characters(tty, &c, 1); + + channel_sts = regs->channel_sts; + } while ((channel_sts & ZYNQ_UART_CHANNEL_STS_REMPTY) == 0); + } else { + channel_sts = regs->channel_sts; + } + + if (ctx->transmitting && (channel_sts & ZYNQ_UART_CHANNEL_STS_TEMPTY) != 0) { + rtems_termios_dequeue_characters(tty, 1); + } +} +#endif + +static bool zynq_uart_first_open( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + struct termios *term, + rtems_libio_open_close_args_t *args +) +{ +#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS + zynq_uart_context *ctx = (zynq_uart_context *) base; + volatile zynq_uart *regs = ctx->regs; + rtems_status_code sc; +#endif + + rtems_termios_set_initial_baud(tty, ZYNQ_UART_DEFAULT_BAUD); + zynq_uart_initialize(base); + +#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS + regs->rx_timeout = 32; + regs->rx_fifo_trg_lvl = ZYNQ_UART_FIFO_DEPTH / 2; + regs->irq_dis = 0xffffffff; + regs->irq_sts = 0xffffffff; + regs->irq_en = ZYNQ_UART_RTRIG | ZYNQ_UART_TIMEOUT; + sc = rtems_interrupt_handler_install( + ctx->irq, + "UART", + RTEMS_INTERRUPT_SHARED, + zynq_uart_interrupt, + tty + ); + if (sc != RTEMS_SUCCESSFUL) { + return false; + } +#endif + + return true; +} + +#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS +static void zynq_uart_last_close( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + rtems_libio_open_close_args_t *args +) +{ + zynq_uart_context *ctx = (zynq_uart_context *) base; + + rtems_interrupt_handler_remove(ctx->irq, zynq_uart_interrupt, tty); +} +#endif + +int zynq_uart_read_polled(rtems_termios_device_context *base) +{ + zynq_uart_context *ctx = (zynq_uart_context *) base; + volatile zynq_uart *regs = ctx->regs; + + if ((regs->channel_sts & ZYNQ_UART_CHANNEL_STS_REMPTY) != 0) { + return -1; + } else { + return ZYNQ_UART_TX_RX_FIFO_FIFO_GET(regs->tx_rx_fifo); + } +} + +void zynq_uart_write_polled( + rtems_termios_device_context *base, + char c +) +{ + zynq_uart_context *ctx = (zynq_uart_context *) base; + volatile zynq_uart *regs = ctx->regs; + + while ((regs->channel_sts & ZYNQ_UART_CHANNEL_STS_TFUL) != 0) { + /* Wait */ + } + + regs->tx_rx_fifo = ZYNQ_UART_TX_RX_FIFO_FIFO(c); +} + +static void zynq_uart_write_support( + rtems_termios_device_context *base, + const char *buf, + size_t len +) +{ +#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS + zynq_uart_context *ctx = (zynq_uart_context *) base; + volatile zynq_uart *regs = ctx->regs; + + if (len > 0) { + ctx->transmitting = true; + regs->irq_sts = ZYNQ_UART_TEMPTY; + regs->irq_en = ZYNQ_UART_TEMPTY; + regs->tx_rx_fifo = ZYNQ_UART_TX_RX_FIFO_FIFO(buf[0]); + } else { + ctx->transmitting = false; + regs->irq_dis = ZYNQ_UART_TEMPTY; + } +#else + ssize_t i; + + for (i = 0; i < len; ++i) { + zynq_uart_write_polled(base, buf[i]); + } +#endif +} + +static bool zynq_uart_set_attributes( + rtems_termios_device_context *context, + const struct termios *term +) +{ +#if 0 + volatile zynq_uart *regs = zynq_uart_get_regs(minor); + uint32_t brgr = 0; + uint32_t bauddiv = 0; + int rc; + + rc = zynq_cal_baud_rate(115200, &brgr, &bauddiv, regs->mode); + if (rc != 0) + return rc; + + regs->control &= ~(ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN); + regs->baud_rate_gen = ZYNQ_UART_BAUD_RATE_GEN_CD(brgr); + regs->baud_rate_div = ZYNQ_UART_BAUD_RATE_DIV_BDIV(bauddiv); + regs->control |= ZYNQ_UART_CONTROL_RXEN | ZYNQ_UART_CONTROL_TXEN; + + return true; +#else + return false; +#endif +} + +const rtems_termios_device_handler zynq_uart_handler = { + .first_open = zynq_uart_first_open, + .set_attributes = zynq_uart_set_attributes, + .write = zynq_uart_write_support, +#ifdef ZYNQ_CONSOLE_USE_INTERRUPTS + .last_close = zynq_uart_last_close, + .mode = TERMIOS_IRQ_DRIVEN +#else + .poll_read = zynq_uart_read_polled, + .mode = TERMIOS_POLLED +#endif +}; + +void zynq_uart_reset_tx_flush(zynq_uart_context *ctx) +{ + volatile zynq_uart *regs = ctx->regs; + int c = 4; + + while (c-- > 0) + zynq_uart_write_polled(&ctx->base, '\r'); + + while ((regs->channel_sts & ZYNQ_UART_CHANNEL_STS_TEMPTY) == 0) { + /* Wait */ + } +} |