1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

boards/cpu: Add limited GBA boot support to RIOT

This commit is contained in:
Teufelchen1 2023-04-27 15:05:47 +02:00
parent 5a4d55a66a
commit c8d5fe2352
29 changed files with 1204 additions and 10 deletions

View File

@ -0,0 +1,13 @@
# Copyright (c) 2023 HAW Hamburg
#
# This file is subject to the terms and conditions of the GNU Lesser
# General Public License v2.1. See the file LICENSE in the top level
# directory for more details.
config BOARD
default "gba" if BOARD_GBA
config BOARD_GBA
bool
default y
select CPU_MODEL_ARM7TDMI_GBA

View File

@ -0,0 +1,3 @@
MODULE = board
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,2 @@
CPU = arm7tdmi_gba
CPU_MODEL = arm7tdmi_gba

View File

@ -0,0 +1 @@
FLASHFILE = $(BINFILE)

View File

@ -0,0 +1,5 @@
/**
@defgroup boards_gba_cartridge GBA
@ingroup boards
@brief Support for the GBA
*/

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2023 Bennet Blischke <bennet.blischke@haw-hamburg.de>
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup boards_gba_cartridge
* @{
*
* @file
* @brief
*
* @author
*/
#ifndef BOARD_H
#define BOARD_H
#include "cpu.h"
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef __cplusplus
}
#endif
#endif /* BOARD_H */
/** @} */

View File

@ -0,0 +1,34 @@
/*
* Copyright (C) 2023 Bennet Blischke <bennet.blischke@haw-hamburg.de>
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/
/**
* @ingroup boards_gba_cartridge
* @{
*
* @file
* @brief
*
* @author
*/
#ifndef PERIPH_CONF_H
#define PERIPH_CONF_H
#include "periph_cpu.h"
#ifdef __cplusplus
extern "C"
{
#endif
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CONF_H */
/** @} */

View File

@ -25,6 +25,17 @@ void cpu_clock_scale(uint32_t source, uint32_t target, uint32_t *prescale);
void arm_reset(void); void arm_reset(void);
/**
* @brief Returns the current content of the link register (lr)
*/
static inline uintptr_t cpu_get_caller_pc(void)
{
register uintptr_t lr_ptr;
__asm__ __volatile__ ("mov %0, lr" : "=r" (lr_ptr));
return lr_ptr;
}
/** /**
* @brief Interrupt stack canary value * @brief Interrupt stack canary value
* *

11
cpu/arm7tdmi_gba/Makefile Normal file
View File

@ -0,0 +1,11 @@
MODULE = cpu
include $(RIOTCPU)/$(CPU)/Makefile.include
DIRS = $(RIOTCPU)/arm7_common
ifneq (,$(filter stdio_%,$(USEMODULE)))
DIRS += stdio_fb
endif
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1 @@
DISABLE_MODULE += periph_init_leds

View File

@ -0,0 +1,7 @@
USEMODULE += arm7_common
ifeq (,$(filter stdio_%,$(USEMODULE)))
USEMODULE += stdio_fb
endif
include $(RIOTCPU)/arm7_common/Makefile.dep

View File

@ -0,0 +1,10 @@
CPU_ARCH = armv4t
CPU_CORE = arm7tdmi_s
FEATURES_PROVIDED += arch_32bit
FEATURES_PROVIDED += arch_arm
FEATURES_PROVIDED += arch_arm7
FEATURES_PROVIDED += cpp
FEATURES_PROVIDED += libstdcpp
FEATURES_PROVIDED += newlib
FEATURES_PROVIDED += picolibc

View File

@ -0,0 +1,3 @@
MCPU := arm7tdmi
include $(RIOTCPU)/arm7_common/Makefile.include

View File

@ -0,0 +1,54 @@
.section .gbaheader
b _startup
// Nintendo Logo data
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
.byte 0x00, 0x00, 0x00, 0x00
// ASCII Game title
.ascii "\0\0\0\0\0\0\0\0\0\0\0\0"
// ASCII Game code
.ascii "\0\0\0\0"
// ASCII Manufacturer id
.ascii "\0\0"
// Fixed value
.byte 0x96
// Target device (0 = GBA)
.byte 0x00
// Reserved
.word 0x00000000
.word 0x00000000
// Version
.byte 0x00
// Checksum
.byte 0x51
// Reserved
.hword 0x0000
// Multiboot header
.zero 36

30
cpu/arm7tdmi_gba/cpu.c Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 HAW Hamburg. All rights reserved.
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_arm7tdmi_gba
* @{
*/
#include <stdint.h>
#include "cpu.h"
#include "kernel_init.h"
/**
* @brief Initialize the CPU, set IRQ priorities, clocks
*/
void cpu_init(void)
{
extern void board_init(void);
/* board specific setup of i/o pins */
board_init();
/* initialize stdio prior to periph_init() to allow use of DEBUG() there */
early_init();
}

5
cpu/arm7tdmi_gba/doc.txt Normal file
View File

@ -0,0 +1,5 @@
/**
* @defgroup cpu_arm7tdmi_gba GBAs ARM7TDMI
* @ingroup cpu
* @brief Nintendos ARM7TDMI on the GBA
*/

View File

@ -0,0 +1,30 @@
/*
* Copyright (C) 2023 HAW Hamburg. All rights reserved.
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#ifndef CPU_H
#define CPU_H
/**
* @ingroup cpu_arm7tdmi_gba
* @{
*/
#include "arm_cpu.h"
#ifdef __cplusplus
extern "C"
{
#endif
extern uintptr_t __stack_start; /**< end of user stack memory space */
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CPU_H */

View File

@ -0,0 +1,94 @@
/*
* Copyright (C) 2023 HAW Hamburg. All rights reserved.
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#ifndef CPU_CONF_H
#define CPU_CONF_H
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @ingroup cpu_arm7tdmi_gba
*
* @{
*/
/**
* @file
* @brief ARM7TDMI_GBA CPU configuration
*
* @author
*/
/**
* @brief This arch uses the inlined irq API.
*/
#define IRQ_API_INLINED (1)
/**
* @name Kernel configuration
* @{
*/
#define THREAD_EXTRA_STACKSIZE_PRINTF (512)
#ifndef THREAD_STACKSIZE_DEFAULT
#define THREAD_STACKSIZE_DEFAULT (1024)
#endif
#ifndef THREAD_STACKSIZE_IDLE
#define THREAD_STACKSIZE_IDLE (160)
#endif
/** @} */
/**
* @brief Stack size used for the undefined instruction interrupt stack
*/
#define UND_STACKSIZE (64)
/**
* @brief Stack size used for the abort interrupt stack
*/
#define ABT_STACKSIZE (64)
/**
* @brief Stack size used for the interrupt (ISR) stack
*/
#ifndef ISR_STACKSIZE
#define ISR_STACKSIZE (400)
#endif
/**
* @brief Stack size used for the fast interrupt (FIQ) stack
*/
#define FIQ_STACKSIZE (64)
/**
* @brief Stack size used for the supervisor mode (SVC) stack
*/
#define SVC_STACKSIZE (400)
/**
* @brief Stack size used for the user mode/kernel init stack
*/
#define USR_STACKSIZE (4096)
/**
* @brief The CPU has 2 blocks of SRAM at different addresses.
* (primary on-chip RAM and external working EWRAM)
*/
#define NUM_HEAPS (2)
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* CPU_CONF_H */

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2023 HAW Hamburg. All rights reserved.
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_arm7tdmi_gba
* @{
*
* @file
* @brief CPU specific definitions for internal peripheral handling
*
* @author
*/
#ifndef PERIPH_CPU_H
#define PERIPH_CPU_H
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Clock configuration
*/
#define CLOCK_CORECLOCK (16780000U) /* 16.78MHz */
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_CPU_H */
/** @} */

View File

@ -0,0 +1,106 @@
/*
* Copyright (C) 2023 HAW Hamburg. All rights reserved.
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup cpu_arm7tdmi_gba
* @{
*
* @file
* @brief GBA specific definitions for internal peripheral handling
*
* @author Bennet Blischke
*/
#ifndef PERIPH_GBA_H
#define PERIPH_GBA_H
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Type for 32-bit registers
*/
#define REG32(ADDR) (*(uint32_t volatile (*))(ADDR))
/**
* @brief Type for 16-bit registers
*/
#define REG16(ADDR) (*(uint16_t volatile (*))(ADDR))
/**
* @brief Type for 16-bit memory addresses
*/
#define MEM16(ADDR) ((uint16_t(*))(ADDR))
/**
* @brief Screen dimension in pixel
* @{
*/
#define GBA_SCREEN_WIDTH (240) /**< width */
#define GBA_SCREEN_HEIGHT (160) /**< height */
/** @} */
/**
* @brief Display Control register
*/
#define GBA_DISPCNT REG16(0x4000000)
/**
* @name Settings for GBA_DISPCNT
* @{
*/
#define GBA_DISPCNT_BGMODE_0 0x0000 /**< Tiled, four layers, up to 1024 tiles */
#define GBA_DISPCNT_BGMODE_1 0x0001 /**< Tiled, three layers, up to 1024 tiles */
#define GBA_DISPCNT_BGMODE_2 0x0002 /**< Tiled, two layers, up to 1024 tiles */
#define GBA_DISPCNT_BGMODE_3 0x0003 /**< Bitmap, 240x160, 15-bit RGB */
#define GBA_DISPCNT_BGMODE_4 0x0004 /**< Bitmap, 240x160, 8-bit RGB */
#define GBA_DISPCNT_BGMODE_5 0x0005 /**< Bitmap, 160x128, 15-bit RGB */
#define GBA_DISPCNT_SDBG_0 0x0100 /**< Enable display of background 0 */
#define GBA_DISPCNT_SDBG_1 0x0200 /**< Enable display of background 1 */
#define GBA_DISPCNT_SDBG_2 0x0400 /**< Enable display of background 2 */
#define GBA_DISPCNT_SDBG_3 0x0800 /**< Enable display of background 3 */
#define GBA_DISPCNT_SDOBJ 0x1000 /**< Enable display of objects */
/** @} */
/**
* @brief General LCD Status register
*/
#define GBA_DISPSTAT REG16(0x4000004)
/**
* @name LCD background control registers
* @{
*/
#define GBA_BG0CNT REG16(0x4000008) /**< BG0 */
#define GBA_BG1CNT REG16(0x400000a) /**< BG1 */
#define GBA_BG2CNT REG16(0x400000c) /**< BG2 */
#define GBA_BG3CNT REG16(0x400000e) /**< BG3 */
/** @} */
/**
* @brief VRAM color palette memory
*/
#define GBA_VRAM_PALETTE MEM16(0x5000000)
/**
* @brief VRAM, 96Kb, 0x6017FFF - size depends on display mode!
*/
#define GBA_VRAM MEM16(0x6000000)
#ifdef __cplusplus
}
#endif
#endif /* PERIPH_GBA_H */
/** @} */

View File

@ -0,0 +1,213 @@
/*
* Copyright 2013, Freie Universitaet Berlin (FUB). All rights reserved.
* 2024, HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
MEMORY {
ewram : ORIGIN = 0x2000000, LENGTH = 256K /* on board ram, slower */
ram (w!rx) : ORIGIN = 0x3000000, LENGTH = 32K /* on chip ram, faster */
rom (rx) : ORIGIN = 0x8000000, LENGTH = 32M /* on cartridge */
}
SECTIONS
{
.text :
{
KEEP(*(.gbaheader))
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
KEEP(*(.init0)) /* Start here after reset. */
. = ALIGN(4);
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
. = ALIGN(4);
*(.rodata .rodata* .gnu.linkonce.r.*)
*(.ARM.extab* .gnu.linkonce.armextab.*)
/* Support C constructors, and C destructors in both user code
and the C library. This also provides support for C++ code. */
. = ALIGN(4);
KEEP(*(.init))
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
. = ALIGN(0x4);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*crtend.o(.ctors))
. = ALIGN(4);
KEEP(*(.fini))
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*crtend.o(.dtors))
KEEP (*(SORT(.roxfa.*)))
. = ALIGN(4);
_efixed = .; /* End of text section */
} > rom
/*
* TLS relocations are offsets relative to the address
* of the first TLS symbol. That means we just need to
* allocate them all together so that the TLS region
* is compact when allocated for each thread.
*/
/*
* TLS initialization data is loaded into ROM so that
* each thread can get its values initialized from there
* at startup
*/
.tdata :
{
__tdata_start = .;
*(.tdata .tdata.* .gnu.linkonce.td.*)
__tdata_end = .;
} > rom
__tdata_source = LOADADDR(.tdata);
__tdata_size = SIZEOF(.tdata);
/*
* TLS zeroed data is relocated as if it immediately followed
* the tdata values. However, the linker 'magically' erases the
* memory allocation so that no ROM is consumed by this
* section
*/
.tbss :
{
*(.tbss .tbss.* .gnu.linkonce.tb.*)
*(.tcommon)
__tbss_end = .;
} > rom
__tls_size = __tbss_end - __tdata_start;
__tbss_size = __tls_size - __tdata_size;
/* .ARM.exidx is sorted, so has to go in its own output section. */
PROVIDE_HIDDEN (__exidx_start = .);
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
PROVIDE_HIDDEN (__exidx_end = .);
/* exception handling */
. = ALIGN(4);
.eh_frame :
{
KEEP (*(.eh_frame))
} > rom
. = ALIGN(4);
_etext = .;
/**************************************************************************
* RAM
**************************************************************************/
/*
* Stacks
*/
.stack (NOLOAD) :
{
PROVIDE(__stack_start = .);
KEEP (*(.usr_stack))
__stack_usr_start = .;
KEEP (*(.und_stack))
__stack_und_start = .;
KEEP (*(.fiq_stack))
__stack_fiq_start = .;
KEEP (*(.irq_stack))
__stack_irq_start = .;
KEEP (*(.abt_stack))
__stack_abt_start = .;
KEEP (*(.svc_stack))
__stack_svc_start = .;
PROVIDE(__stack_end = .);
} > ram
.relocate :
{
. = ALIGN(4);
_srelocate = .;
*(.ramfunc .ramfunc.*);
*(.data .data.*);
KEEP (*(.openocd .openocd.*))
KEEP (*(SORT(.xfa.*)))
. = ALIGN(4);
_erelocate = .;
} > ram AT> rom
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = . ;
_szero = .;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
_ezero = .;
} > ram
/*
* collect all uninitialized sections that go into RAM
*/
.noinit (NOLOAD) :
{
__noinit_start = .;
PROVIDE(__fiq_handler = .);
*(.fiq)
*(.noinit)
. = ALIGN(4);
__noinit_end = .;
} > ram
/* heap section */
. = ALIGN(4);
_sheap = . ;
_eheap = ORIGIN(ram) + LENGTH(ram);
.heap1 ALIGN(4) (NOLOAD) :
{
_sheap1 = ORIGIN(ewram);
_eheap1 = ORIGIN(ewram) + LENGTH(ewram);
} > ewram
/* Populate information about ram size */
_sram = ORIGIN(ram);
_eram = ORIGIN(ram) + LENGTH(ram);
/* Populate information about rom size */
_srom = ORIGIN(rom);
_erom = ORIGIN(rom) + LENGTH(rom);
.end_fw (NOLOAD) : ALIGN(4) {
_end_fw = . ;
} > rom
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2023 HAW Hamburg
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/* ***************************************************************************************************************
startup.s STARTUP ASSEMBLY CODE
-----------------------
Module includes the interrupt vectors and start-up code.
*************************************************************************************************************** */
.extern __start_start
.extern __stack_end
.extern __fiq_handler
/* Stack Positions */
.extern __stack_usr_start
.extern __stack_abt_start
.extern __stack_und_start
.extern __stack_fiq_start
.extern __start_irq_start
.extern __start_svc_start
/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs (program status registers) */
.set MODE_USR, 0x10 /* Normal User Mode */
.set MODE_FIQ, 0x11 /* FIQ Processing Fast Interrupts Mode */
.set MODE_IRQ, 0x12 /* IRQ Processing Standard Interrupts Mode */
.set MODE_SVC, 0x13 /* Supervisor Processing Software Interrupts Mode */
.set MODE_ABT, 0x17 /* Abort Processing memory Faults Mode */
.set MODE_UND, 0x1B /* Undefined Processing Undefined Instructions Mode */
.set MODE_SYS, 0x1F /* System Running Priviledged Operating System Tasks Mode */
.set I_BIT, 0x80 /* when I bit is set, IRQ is disabled (program status registers) */
.set F_BIT, 0x40 /* when F bit is set, FIQ is disabled (program status registers) */
.set REG_IME, 0x4000208
.text
.arm
/* Begin of boot code */
.text
.arm
.section .init
.global _startup
.func _startup
_startup:
ldr pc, =reset_handler
/*.func reset_handler */
reset_handler:
.section .init0
/* Disable interrupts using the GBA control reg */
ldr r0, =REG_IME
mov r1, #0
strh r1, [r0]
/* Setup a stack for each mode - note that this only sets up a usable stack
for User mode. Also each mode is setup with interrupts initially disabled. */
ldr r0, = __stack_end
msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */
ldr sp, =__stack_und_start
msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */
ldr sp, =__stack_abt_start
msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */
ldr sp, =__stack_fiq_start
msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */
ldr sp, =__stack_irq_start
msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */
ldr sp, =__stack_svc_start
msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* User Mode */
ldr sp, =__stack_usr_start
bl bootloader
b kernel_init
/* Infinite Loop */
.section .fini0
__main_exit: B __main_exit
.endfunc
.end

View File

@ -0,0 +1 @@
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,286 @@
#ifndef FONT_TERMINAL_H
#define FONT_TERMINAL_H
#ifdef __cplusplus
extern "C"
{
#endif
#define FONT_WIDTH 8
#define FONT_HEIGHT 8
#define FONT_VMIRROR 1
/*
https://github.com/dhepper/font8x8
; Summary: font8_8.asm
; 8x8 monochrome bitmap fonts for rendering
;
; Author:
; Marcel Sondaar
; International Business Machines (public domain VGA fonts)
;
; License:
; Public Domain
;
*/
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0000 (nul)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0001
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0002
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0003
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0004
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0005
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0006
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0007
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0008
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0009
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+000A
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+000B
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+000C
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+000D
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+000E
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+000F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0010
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0011
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0012
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0013
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0014
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0015
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0016
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0017
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0018
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0019
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+001A
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+001B
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+001C
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+001D
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+001E
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+001F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0020 (space)
0x18, 0x3C, 0x3C, 0x18, 0x18, 0x00, 0x18, 0x00, // U+0021 (!)
0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0022 (")
0x36, 0x36, 0x7F, 0x36, 0x7F, 0x36, 0x36, 0x00, // U+0023 (#)
0x0C, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x0C, 0x00, // U+0024 ($)
0x00, 0x63, 0x33, 0x18, 0x0C, 0x66, 0x63, 0x00, // U+0025 (%)
0x1C, 0x36, 0x1C, 0x6E, 0x3B, 0x33, 0x6E, 0x00, // U+0026 (&)
0x06, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0027 (')
0x18, 0x0C, 0x06, 0x06, 0x06, 0x0C, 0x18, 0x00, // U+0028 (()
0x06, 0x0C, 0x18, 0x18, 0x18, 0x0C, 0x06, 0x00, // U+0029 ())
0x00, 0x66, 0x3C, 0xFF, 0x3C, 0x66, 0x00, 0x00, // U+002A (*)
0x00, 0x0C, 0x0C, 0x3F, 0x0C, 0x0C, 0x00, 0x00, // U+002B (+)
0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x06, // U+002C (,)
0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0x00, // U+002D (-)
0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x0C, 0x00, // U+002E (.)
0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, // U+002F (/)
0x3E, 0x63, 0x73, 0x7B, 0x6F, 0x67, 0x3E, 0x00, // U+0030 (0)
0x0C, 0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x3F, 0x00, // U+0031 (1)
0x1E, 0x33, 0x30, 0x1C, 0x06, 0x33, 0x3F, 0x00, // U+0032 (2)
0x1E, 0x33, 0x30, 0x1C, 0x30, 0x33, 0x1E, 0x00, // U+0033 (3)
0x38, 0x3C, 0x36, 0x33, 0x7F, 0x30, 0x78, 0x00, // U+0034 (4)
0x3F, 0x03, 0x1F, 0x30, 0x30, 0x33, 0x1E, 0x00, // U+0035 (5)
0x1C, 0x06, 0x03, 0x1F, 0x33, 0x33, 0x1E, 0x00, // U+0036 (6)
0x3F, 0x33, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x00, // U+0037 (7)
0x1E, 0x33, 0x33, 0x1E, 0x33, 0x33, 0x1E, 0x00, // U+0038 (8)
0x1E, 0x33, 0x33, 0x3E, 0x30, 0x18, 0x0E, 0x00, // U+0039 (9)
0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x00, // U+003A (:)
0x00, 0x0C, 0x0C, 0x00, 0x00, 0x0C, 0x0C, 0x06, // U+003B (//)
0x18, 0x0C, 0x06, 0x03, 0x06, 0x0C, 0x18, 0x00, // U+003C (<)
0x00, 0x00, 0x3F, 0x00, 0x00, 0x3F, 0x00, 0x00, // U+003D (=)
0x06, 0x0C, 0x18, 0x30, 0x18, 0x0C, 0x06, 0x00, // U+003E (>)
0x1E, 0x33, 0x30, 0x18, 0x0C, 0x00, 0x0C, 0x00, // U+003F (?)
0x3E, 0x63, 0x7B, 0x7B, 0x7B, 0x03, 0x1E, 0x00, // U+0040 (@)
0x0C, 0x1E, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x00, // U+0041 (A)
0x3F, 0x66, 0x66, 0x3E, 0x66, 0x66, 0x3F, 0x00, // U+0042 (B)
0x3C, 0x66, 0x03, 0x03, 0x03, 0x66, 0x3C, 0x00, // U+0043 (C)
0x1F, 0x36, 0x66, 0x66, 0x66, 0x36, 0x1F, 0x00, // U+0044 (D)
0x7F, 0x46, 0x16, 0x1E, 0x16, 0x46, 0x7F, 0x00, // U+0045 (E)
0x7F, 0x46, 0x16, 0x1E, 0x16, 0x06, 0x0F, 0x00, // U+0046 (F)
0x3C, 0x66, 0x03, 0x03, 0x73, 0x66, 0x7C, 0x00, // U+0047 (G)
0x33, 0x33, 0x33, 0x3F, 0x33, 0x33, 0x33, 0x00, // U+0048 (H)
0x1E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, // U+0049 (I)
0x78, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, 0x00, // U+004A (J)
0x67, 0x66, 0x36, 0x1E, 0x36, 0x66, 0x67, 0x00, // U+004B (K)
0x0F, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7F, 0x00, // U+004C (L)
0x63, 0x77, 0x7F, 0x7F, 0x6B, 0x63, 0x63, 0x00, // U+004D (M)
0x63, 0x67, 0x6F, 0x7B, 0x73, 0x63, 0x63, 0x00, // U+004E (N)
0x1C, 0x36, 0x63, 0x63, 0x63, 0x36, 0x1C, 0x00, // U+004F (O)
0x3F, 0x66, 0x66, 0x3E, 0x06, 0x06, 0x0F, 0x00, // U+0050 (P)
0x1E, 0x33, 0x33, 0x33, 0x3B, 0x1E, 0x38, 0x00, // U+0051 (Q)
0x3F, 0x66, 0x66, 0x3E, 0x36, 0x66, 0x67, 0x00, // U+0052 (R)
0x1E, 0x33, 0x07, 0x0E, 0x38, 0x33, 0x1E, 0x00, // U+0053 (S)
0x3F, 0x2D, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, // U+0054 (T)
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x00, // U+0055 (U)
0x33, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00, // U+0056 (V)
0x63, 0x63, 0x63, 0x6B, 0x7F, 0x77, 0x63, 0x00, // U+0057 (W)
0x63, 0x63, 0x36, 0x1C, 0x1C, 0x36, 0x63, 0x00, // U+0058 (X)
0x33, 0x33, 0x33, 0x1E, 0x0C, 0x0C, 0x1E, 0x00, // U+0059 (Y)
0x7F, 0x63, 0x31, 0x18, 0x4C, 0x66, 0x7F, 0x00, // U+005A (Z)
0x1E, 0x06, 0x06, 0x06, 0x06, 0x06, 0x1E, 0x00, // U+005B ([)
0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0x40, 0x00, // U+005C (\)
0x1E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1E, 0x00, // U+005D (])
0x08, 0x1C, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00, // U+005E (^)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, // U+005F (_)
0x0C, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0060 (`)
0x00, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x6E, 0x00, // U+0061 (a)
0x07, 0x06, 0x06, 0x3E, 0x66, 0x66, 0x3B, 0x00, // U+0062 (b)
0x00, 0x00, 0x1E, 0x33, 0x03, 0x33, 0x1E, 0x00, // U+0063 (c)
0x38, 0x30, 0x30, 0x3e, 0x33, 0x33, 0x6E, 0x00, // U+0064 (d)
0x00, 0x00, 0x1E, 0x33, 0x3f, 0x03, 0x1E, 0x00, // U+0065 (e)
0x1C, 0x36, 0x06, 0x0f, 0x06, 0x06, 0x0F, 0x00, // U+0066 (f)
0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x1F, // U+0067 (g)
0x07, 0x06, 0x36, 0x6E, 0x66, 0x66, 0x67, 0x00, // U+0068 (h)
0x0C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, // U+0069 (i)
0x30, 0x00, 0x30, 0x30, 0x30, 0x33, 0x33, 0x1E, // U+006A (j)
0x07, 0x06, 0x66, 0x36, 0x1E, 0x36, 0x67, 0x00, // U+006B (k)
0x0E, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, // U+006C (l)
0x00, 0x00, 0x33, 0x7F, 0x7F, 0x6B, 0x63, 0x00, // U+006D (m)
0x00, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x33, 0x00, // U+006E (n)
0x00, 0x00, 0x1E, 0x33, 0x33, 0x33, 0x1E, 0x00, // U+006F (o)
0x00, 0x00, 0x3B, 0x66, 0x66, 0x3E, 0x06, 0x0F, // U+0070 (p)
0x00, 0x00, 0x6E, 0x33, 0x33, 0x3E, 0x30, 0x78, // U+0071 (q)
0x00, 0x00, 0x3B, 0x6E, 0x66, 0x06, 0x0F, 0x00, // U+0072 (r)
0x00, 0x00, 0x3E, 0x03, 0x1E, 0x30, 0x1F, 0x00, // U+0073 (s)
0x08, 0x0C, 0x3E, 0x0C, 0x0C, 0x2C, 0x18, 0x00, // U+0074 (t)
0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x6E, 0x00, // U+0075 (u)
0x00, 0x00, 0x33, 0x33, 0x33, 0x1E, 0x0C, 0x00, // U+0076 (v)
0x00, 0x00, 0x63, 0x6B, 0x7F, 0x7F, 0x36, 0x00, // U+0077 (w)
0x00, 0x00, 0x63, 0x36, 0x1C, 0x36, 0x63, 0x00, // U+0078 (x)
0x00, 0x00, 0x33, 0x33, 0x33, 0x3E, 0x30, 0x1F, // U+0079 (y)
0x00, 0x00, 0x3F, 0x19, 0x0C, 0x26, 0x3F, 0x00, // U+007A (z)
0x38, 0x0C, 0x0C, 0x07, 0x0C, 0x0C, 0x38, 0x00, // U+007B ({)
0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, // U+007C (|)
0x07, 0x0C, 0x0C, 0x38, 0x0C, 0x0C, 0x07, 0x00, // U+007D (})
0x6E, 0x3B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+007E (~)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+007F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0080
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0081
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0082
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0083
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0084
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0085
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0086
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0087
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0088
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0089
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+008A
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+008B
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+008C
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+008D
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+008E
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+008F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0090
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0091
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0092
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0093
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0094
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0095
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0096
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0097
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0098
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+0099
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+009A
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+009B
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+009C
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+009D
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+009E
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+009F
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+00A0 (no break space)
0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, // U+00A1 (inverted !)
0x18, 0x18, 0x7E, 0x03, 0x03, 0x7E, 0x18, 0x18, // U+00A2 (dollarcents)
0x1C, 0x36, 0x26, 0x0F, 0x06, 0x67, 0x3F, 0x00, // U+00A3 (pound sterling)
0x00, 0x00, 0x63, 0x3E, 0x36, 0x3E, 0x63, 0x00, // U+00A4 (currency mark)
0x33, 0x33, 0x1E, 0x3F, 0x0C, 0x3F, 0x0C, 0x0C, // U+00A5 (yen)
0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, // U+00A6 (broken pipe)
0x7C, 0xC6, 0x1C, 0x36, 0x36, 0x1C, 0x33, 0x1E, // U+00A7 (paragraph)
0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+00A8 (diaeresis)
0x3C, 0x42, 0x99, 0x85, 0x85, 0x99, 0x42, 0x3C, // U+00A9 (copyright symbol)
0x3C, 0x36, 0x36, 0x7C, 0x00, 0x00, 0x00, 0x00, // U+00AA (superscript a)
0x00, 0xCC, 0x66, 0x33, 0x66, 0xCC, 0x00, 0x00, // U+00AB (<<)
0x00, 0x00, 0x00, 0x3F, 0x30, 0x30, 0x00, 0x00, // U+00AC (gun pointing left)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+00AD (soft hyphen)
0x3C, 0x42, 0x9D, 0xA5, 0x9D, 0xA5, 0x42, 0x3C, // U+00AE (registered symbol)
0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+00AF (macron)
0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00, // U+00B0 (degree)
0x18, 0x18, 0x7E, 0x18, 0x18, 0x00, 0x7E, 0x00, // U+00B1 (plusminus)
0x1C, 0x30, 0x18, 0x0C, 0x3C, 0x00, 0x00, 0x00, // U+00B2 (superscript 2)
0x1C, 0x30, 0x18, 0x30, 0x1C, 0x00, 0x00, 0x00, // U+00B2 (superscript 3)
0x18, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // U+00B2 (aigu)
0x00, 0x00, 0x66, 0x66, 0x66, 0x3E, 0x06, 0x03, // U+00B5 (mu)
0xFE, 0xDB, 0xDB, 0xDE, 0xD8, 0xD8, 0xD8, 0x00, // U+00B6 (pilcrow)
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, // U+00B7 (central dot)
0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x1E, // U+00B8 (cedille)
0x08, 0x0C, 0x08, 0x1C, 0x00, 0x00, 0x00, 0x00, // U+00B9 (superscript 1)
0x1C, 0x36, 0x36, 0x1C, 0x00, 0x00, 0x00, 0x00, // U+00BA (superscript 0)
0x00, 0x33, 0x66, 0xCC, 0x66, 0x33, 0x00, 0x00, // U+00BB (>>)
0xC3, 0x63, 0x33, 0xBD, 0xEC, 0xF6, 0xF3, 0x03, // U+00BC (1/4)
0xC3, 0x63, 0x33, 0x7B, 0xCC, 0x66, 0x33, 0xF0, // U+00BD (1/2)
0x03, 0xC4, 0x63, 0xB4, 0xDB, 0xAC, 0xE6, 0x80, // U+00BE (3/4)
0x0C, 0x00, 0x0C, 0x06, 0x03, 0x33, 0x1E, 0x00, // U+00BF (inverted ?)
0x07, 0x00, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x00, // U+00C0 (A grave)
0x70, 0x00, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x00, // U+00C1 (A aigu)
0x1C, 0x36, 0x00, 0x3E, 0x63, 0x7F, 0x63, 0x00, // U+00C2 (A circumflex)
0x6E, 0x3B, 0x00, 0x3E, 0x63, 0x7F, 0x63, 0x00, // U+00C3 (A ~)
0x63, 0x1C, 0x36, 0x63, 0x7F, 0x63, 0x63, 0x00, // U+00C4 (A umlaut)
0x0C, 0x0C, 0x00, 0x1E, 0x33, 0x3F, 0x33, 0x00, // U+00C5 (A ring)
0x7C, 0x36, 0x33, 0x7F, 0x33, 0x33, 0x73, 0x00, // U+00C6 (AE)
0x1E, 0x33, 0x03, 0x33, 0x1E, 0x18, 0x30, 0x1E, // U+00C7 (C cedille)
0x07, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00, // U+00C8 (E grave)
0x38, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00, // U+00C9 (E aigu)
0x0C, 0x12, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00, // U+00CA (E circumflex)
0x36, 0x00, 0x3F, 0x06, 0x1E, 0x06, 0x3F, 0x00, // U+00CB (E umlaut)
0x07, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, // U+00CC (I grave)
0x38, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, // U+00CD (I aigu)
0x0C, 0x12, 0x00, 0x1E, 0x0C, 0x0C, 0x1E, 0x00, // U+00CE (I circumflex)
0x33, 0x00, 0x1E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, // U+00CF (I umlaut)
0x3F, 0x66, 0x6F, 0x6F, 0x66, 0x66, 0x3F, 0x00, // U+00D0 (Eth)
0x3F, 0x00, 0x33, 0x37, 0x3F, 0x3B, 0x33, 0x00, // U+00D1 (N ~)
0x0E, 0x00, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00, // U+00D2 (O grave)
0x70, 0x00, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00, // U+00D3 (O aigu)
0x3C, 0x66, 0x18, 0x3C, 0x66, 0x3C, 0x18, 0x00, // U+00D4 (O circumflex)
0x6E, 0x3B, 0x00, 0x3E, 0x63, 0x63, 0x3E, 0x00, // U+00D5 (O ~)
0xC3, 0x18, 0x3C, 0x66, 0x66, 0x3C, 0x18, 0x00, // U+00D6 (O umlaut)
0x00, 0x36, 0x1C, 0x08, 0x1C, 0x36, 0x00, 0x00, // U+00D7 (multiplicative x)
0x5C, 0x36, 0x73, 0x7B, 0x6F, 0x36, 0x1D, 0x00, // U+00D8 (O stroke)
0x0E, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // U+00D9 (U grave)
0x70, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3C, 0x00, // U+00DA (U aigu)
0x3C, 0x66, 0x00, 0x66, 0x66, 0x66, 0x3C, 0x00, // U+00DB (U circumflex)
0x33, 0x00, 0x33, 0x33, 0x33, 0x33, 0x1E, 0x00, // U+00DC (U umlaut)
0x70, 0x00, 0x66, 0x66, 0x3C, 0x18, 0x18, 0x00, // U+00DD (Y aigu)
0x0F, 0x06, 0x3E, 0x66, 0x66, 0x3E, 0x06, 0x0F, // U+00DE (Thorn)
0x00, 0x1E, 0x33, 0x1F, 0x33, 0x1F, 0x03, 0x03, // U+00DF (beta)
0x07, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00, // U+00E0 (a grave)
0x38, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00, // U+00E1 (a aigu)
0x7E, 0xC3, 0x3C, 0x60, 0x7C, 0x66, 0xFC, 0x00, // U+00E2 (a circumflex)
0x6E, 0x3B, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00, // U+00E3 (a ~)
0x33, 0x00, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00, // U+00E4 (a umlaut)
0x0C, 0x0C, 0x1E, 0x30, 0x3E, 0x33, 0x7E, 0x00, // U+00E5 (a ring)
0x00, 0x00, 0xFE, 0x30, 0xFE, 0x33, 0xFE, 0x00, // U+00E6 (ae)
0x00, 0x00, 0x1E, 0x03, 0x03, 0x1E, 0x30, 0x1C, // U+00E7 (c cedille)
0x07, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00, // U+00E8 (e grave)
0x38, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00, // U+00E9 (e aigu)
0x7E, 0xC3, 0x3C, 0x66, 0x7E, 0x06, 0x3C, 0x00, // U+00EA (e circumflex)
0x33, 0x00, 0x1E, 0x33, 0x3F, 0x03, 0x1E, 0x00, // U+00EB (e umlaut)
0x07, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, // U+00EC (i grave)
0x1C, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, // U+00ED (i augu)
0x3E, 0x63, 0x1C, 0x18, 0x18, 0x18, 0x3C, 0x00, // U+00EE (i circumflex)
0x33, 0x00, 0x0E, 0x0C, 0x0C, 0x0C, 0x1E, 0x00, // U+00EF (i umlaut)
0x1B, 0x0E, 0x1B, 0x30, 0x3E, 0x33, 0x1E, 0x00, // U+00F0 (eth)
0x00, 0x1F, 0x00, 0x1F, 0x33, 0x33, 0x33, 0x00, // U+00F1 (n ~)
0x00, 0x07, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00, // U+00F2 (o grave)
0x00, 0x38, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00, // U+00F3 (o aigu)
0x1E, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00, // U+00F4 (o circumflex)
0x6E, 0x3B, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00, // U+00F5 (o ~)
0x00, 0x33, 0x00, 0x1E, 0x33, 0x33, 0x1E, 0x00, // U+00F6 (o umlaut)
0x18, 0x18, 0x00, 0x7E, 0x00, 0x18, 0x18, 0x00, // U+00F7 (division)
0x00, 0x60, 0x3C, 0x76, 0x7E, 0x6E, 0x3C, 0x06, // U+00F8 (o stroke)
0x00, 0x07, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00, // U+00F9 (u grave)
0x00, 0x38, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00, // U+00FA (u aigu)
0x1E, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00, // U+00FB (u circumflex)
0x00, 0x33, 0x00, 0x33, 0x33, 0x33, 0x7E, 0x00, // U+00FC (u umlaut)
0x00, 0x38, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F, // U+00FD (y aigu)
0x00, 0x00, 0x06, 0x3E, 0x66, 0x3E, 0x06, 0x00, // U+00FE (thorn)
0x00, 0x33, 0x00, 0x33, 0x33, 0x3E, 0x30, 0x1F, // U+00FF (y umlaut)
#ifdef __cplusplus
}
#endif
#endif /* FONT_TERMINAL_H */

View File

@ -0,0 +1,113 @@
/*
* Copyright (C) 2023 Bennet Blischke <bennet.blischke@haw-hamburg.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup boards_gba_stdio_fb
* @{
*
* @file
* @brief STDIO framebuffer driver
*
* This file provides a framebuffer driver for STDIO, implementing stdout only.
*
* @author Bennet Blischke <bennet.blischke@haw-hamburg.de>
*
* @}
*/
#include "stdio_base.h"
#include "periph_gba.h"
#include <string.h>
static const unsigned char systemFont[] =
{
#include "font_terminal.h"
};
#define BLACK 0x0000
#define WHITE 0x7FFF
static void clearScreen(void)
{
/* width * height * two byte per pixel */
memset(GBA_VRAM, 0x00, GBA_SCREEN_WIDTH * GBA_SCREEN_HEIGHT * 2);
}
static void drawPixel(unsigned short x, unsigned short y, unsigned short color)
{
GBA_VRAM[x + y * GBA_SCREEN_WIDTH] = color;
}
static void drawChar(unsigned char c, int x, int y, unsigned short fgColour,
unsigned short bgColour)
{
unsigned char mask;
const unsigned char *font = systemFont + (c * FONT_HEIGHT);
unsigned short colourToDraw;
for (int h = 0; h < FONT_HEIGHT; h++) {
mask = 0x01;
/* This loop draws 8 pixels at most / 1 byte per line */
for (int w = 0; w < FONT_WIDTH; w++) {
if ((*font) & mask) {
colourToDraw = fgColour;
}
else {
colourToDraw = bgColour;
}
drawPixel(x + w, y + h, colourToDraw);
mask <<= 1;
}
font++;
}
}
void stdio_init(void)
{
/* setup bitmap mode */
GBA_DISPCNT = GBA_DISPCNT_BGMODE_3 | GBA_DISPCNT_SDBG_2;
clearScreen();
}
ssize_t stdio_read(void *buffer, size_t count)
{
(void)buffer;
(void)count;
return 0;
}
ssize_t stdio_write(const void *buffer, size_t len)
{
static unsigned short row = 0;
static unsigned short cursor = 0;
for (size_t i = 0; i < len; i++) {
if (cursor >= (GBA_SCREEN_WIDTH / FONT_WIDTH)) {
cursor = 0;
row++;
}
if (row >= (GBA_SCREEN_HEIGHT / FONT_HEIGHT)) {
clearScreen();
row = 0;
}
char c = ((char *)buffer)[i];
if (c == '\n') {
row++;
cursor = 0;
continue;
}
drawChar(c, cursor * FONT_WIDTH, row * FONT_HEIGHT, WHITE, BLACK);
cursor++;
}
return len;
}

View File

@ -57,16 +57,6 @@ bool install_irq(int IntNumber, void (*HandlerAddr)(void), int Priority);
void gpio_init_ports(void); void gpio_init_ports(void);
#endif #endif
/**
* @brief Returns the current content of the link register (lr)
*/
static inline uintptr_t cpu_get_caller_pc(void)
{
register uintptr_t lr_ptr;
__asm__ __volatile__("mov %0, lr" : "=r"(lr_ptr));
return lr_ptr;
}
/** /**
* @brief Returns true if the CPU woke from Deep Sleep * @brief Returns true if the CPU woke from Deep Sleep
*/ */

View File

@ -276,6 +276,11 @@ groups:
- name: cpu_qn908x - name: cpu_qn908x
help: The MCU is part of the NXP QN908x family help: The MCU is part of the NXP QN908x family
- title: Nintendo Grouping
features:
- name: cpu_arm7tdmi_gba
help: The MCU of the Game Boy Advance.
- title: Raspberry Pi Grouping - title: Raspberry Pi Grouping
features: features:
- name: cpu_rpx0xx - name: cpu_rpx0xx

View File

@ -48,6 +48,7 @@ FEATURES_EXISTING := \
cortexm_mpu \ cortexm_mpu \
cortexm_svc \ cortexm_svc \
cpp \ cpp \
cpu_arm7tdmi_gba \
cpu_atmega1281 \ cpu_atmega1281 \
cpu_atmega1284p \ cpu_atmega1284p \
cpu_atmega128rfa1 \ cpu_atmega128rfa1 \

View File

@ -12,6 +12,7 @@ STDIO_MODULES = \
stdio_telnet \ stdio_telnet \
stdio_tinyusb_cdc_acm \ stdio_tinyusb_cdc_acm \
stdio_usb_serial_jtag \ stdio_usb_serial_jtag \
stdio_fb \
# #
STDIO_LEGACY_MODULES = \ STDIO_LEGACY_MODULES = \