Initial commit
This commit is contained in:
commit
b0255f2c62
22 changed files with 3038 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
build/*
|
||||
20
CMakeLists.txt
Normal file
20
CMakeLists.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
cmake_minimum_required(VERSION 3.12)
|
||||
|
||||
set(PICO_PLATFORM rp2350)
|
||||
|
||||
include(pico_sdk_import.cmake)
|
||||
include(pimoroni_pico_import.cmake)
|
||||
|
||||
# Gooey boilerplate
|
||||
project(pico_dvhstx_examples C CXX ASM)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# Initialize the SDK
|
||||
pico_sdk_init()
|
||||
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror")
|
||||
|
||||
include(pico_dvhstx.cmake)
|
||||
|
||||
add_subdirectory(examples/dvhstx)
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 Michael Bell and Pimoroni Ltd
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
34
README.md
Normal file
34
README.md
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# DVI for HSTX <!-- omit in toc -->
|
||||
|
||||
This repository is home to the Pimoroni PicoGraphics compatible DVI driver for RP2 chips with HSTX (e.g. RP2350).
|
||||
|
||||
[](https://github.com/MichaelBell/dvhstx/actions/workflows/micropython.yml)
|
||||
[](https://github.com/MichaelBell/dvhstx/releases/latest/)
|
||||
|
||||
- [Introduction](#introduction)
|
||||
- [Download MicroPython](#download-micropython)
|
||||
- [Documentation](#documentation)
|
||||
- [C/C++ Resources](#cc-resources)
|
||||
- [C/C++ Community Projects](#cc-community-projects)
|
||||
|
||||
## Introduction
|
||||
|
||||
DV HSTX will enable you to create big, bold audio visual projects using MicroPython and an HDMI display of your choice.
|
||||
|
||||
## Download MicroPython
|
||||
|
||||
TODO
|
||||
|
||||
* [DV HSTX MicroPython Releases](https://github.com/MichaelBell/dvhstx/releases)
|
||||
|
||||
## Documentation
|
||||
|
||||
TODO
|
||||
|
||||
## C/C++ Resources
|
||||
|
||||
* :link: [C++ Boilerplate](https://github.com/MichaelBell/dvhstx-boilerplate/)
|
||||
|
||||
## C/C++ Community Projects
|
||||
|
||||
TODO
|
||||
1
drivers/dvhstx/CMakeLists.txt
Normal file
1
drivers/dvhstx/CMakeLists.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
include(dvhstx.cmake)
|
||||
16
drivers/dvhstx/dvhstx.cmake
Normal file
16
drivers/dvhstx/dvhstx.cmake
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
set(DRIVER_NAME dvhstx)
|
||||
|
||||
# main DV display driver
|
||||
add_library(${DRIVER_NAME} INTERFACE)
|
||||
|
||||
target_sources(${DRIVER_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/dvi.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/${DRIVER_NAME}.cpp
|
||||
|
||||
${CMAKE_CURRENT_LIST_DIR}/intel_one_mono_2bpp.c
|
||||
)
|
||||
|
||||
target_include_directories(${DRIVER_NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(${DRIVER_NAME} INTERFACE pico_stdlib)
|
||||
874
drivers/dvhstx/dvhstx.cpp
Normal file
874
drivers/dvhstx/dvhstx.cpp
Normal file
|
|
@ -0,0 +1,874 @@
|
|||
#include <string.h>
|
||||
#include <pico/stdlib.h>
|
||||
|
||||
extern "C" {
|
||||
#include <pico/lock_core.h>
|
||||
}
|
||||
|
||||
#include <algorithm>
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "hardware/irq.h"
|
||||
#include "hardware/structs/bus_ctrl.h"
|
||||
#include "hardware/structs/hstx_ctrl.h"
|
||||
#include "hardware/structs/hstx_fifo.h"
|
||||
#include "hardware/structs/sio.h"
|
||||
|
||||
#include "hardware/structs/ioqspi.h"
|
||||
#include "hardware/vreg.h"
|
||||
#include "hardware/structs/qmi.h"
|
||||
#include "hardware/pll.h"
|
||||
#include "hardware/clocks.h"
|
||||
|
||||
#include "dvi.hpp"
|
||||
#include "dvhstx.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
#include "font.h"
|
||||
|
||||
// If changing the font, note this code will not handle glyphs wider than 13 pixels
|
||||
#define FONT (&intel_one_mono)
|
||||
|
||||
static inline __attribute__((always_inline)) uint32_t render_char_line(int c, int y) {
|
||||
if (c < 0x20 || c > 0x7e) return 0;
|
||||
const lv_font_fmt_txt_glyph_dsc_t* g = &FONT->dsc->glyph_dsc[c - 0x20 + 1];
|
||||
const uint8_t *b = FONT->dsc->glyph_bitmap + g->bitmap_index;
|
||||
const int ey = y - FONT_HEIGHT + FONT->base_line + g->ofs_y + g->box_h;
|
||||
if (ey < 0 || ey >= g->box_h || g->box_w == 0) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
int bi = (g->box_w * ey);
|
||||
|
||||
uint32_t bits = (b[bi >> 2] << 24) | (b[(bi >> 2) + 1] << 16) | (b[(bi >> 2) + 2] << 8) | b[(bi >> 2) + 3];
|
||||
bits >>= 6 - ((bi & 3) << 1);
|
||||
bits &= 0x3ffffff & (0x3ffffff << ((13 - g->box_w) << 1));
|
||||
bits >>= g->ofs_x << 1;
|
||||
|
||||
return bits;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// HSTX command lists
|
||||
|
||||
// Lists are padded with NOPs to be >= HSTX FIFO size, to avoid DMA rapidly
|
||||
// pingponging and tripping up the IRQs.
|
||||
|
||||
static uint32_t vblank_line_vsync_off[] = {
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V1_H1,
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V1_H0,
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V1_H1
|
||||
};
|
||||
|
||||
static uint32_t vblank_line_vsync_on[] = {
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V0_H1,
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V0_H0,
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V0_H1
|
||||
};
|
||||
|
||||
static uint32_t vactive_line_header[] = {
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V1_H1,
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V1_H0,
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V1_H1,
|
||||
HSTX_CMD_TMDS
|
||||
};
|
||||
|
||||
static uint32_t vactive_text_line_header[] = {
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V1_H1,
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V1_H0,
|
||||
HSTX_CMD_RAW_REPEAT,
|
||||
SYNC_V1_H1,
|
||||
HSTX_CMD_RAW | 6,
|
||||
BLACK_PIXEL_A,
|
||||
BLACK_PIXEL_B,
|
||||
BLACK_PIXEL_A,
|
||||
BLACK_PIXEL_B,
|
||||
BLACK_PIXEL_A,
|
||||
BLACK_PIXEL_B,
|
||||
HSTX_CMD_TMDS
|
||||
};
|
||||
|
||||
#define NUM_FRAME_LINES 2
|
||||
#define NUM_CHANS 3
|
||||
|
||||
static DVHSTX* display = nullptr;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// DMA logic
|
||||
|
||||
void __scratch_x("display") dma_irq_handler() {
|
||||
display->gfx_dma_handler();
|
||||
}
|
||||
|
||||
void __scratch_x("display") DVHSTX::gfx_dma_handler() {
|
||||
// ch_num indicates the channel that just finished, which is the one
|
||||
// we're about to reload.
|
||||
dma_channel_hw_t *ch = &dma_hw->ch[ch_num];
|
||||
dma_hw->intr = 1u << ch_num;
|
||||
if (++ch_num == NUM_CHANS) ch_num = 0;
|
||||
|
||||
if (v_scanline >= timing_mode->v_front_porch && v_scanline < (timing_mode->v_front_porch + timing_mode->v_sync_width)) {
|
||||
ch->read_addr = (uintptr_t)vblank_line_vsync_on;
|
||||
ch->transfer_count = count_of(vblank_line_vsync_on);
|
||||
} else if (v_scanline < v_inactive_total) {
|
||||
ch->read_addr = (uintptr_t)vblank_line_vsync_off;
|
||||
ch->transfer_count = count_of(vblank_line_vsync_off);
|
||||
} else {
|
||||
const int y = (v_scanline - v_inactive_total) >> v_repeat_shift;
|
||||
const int new_line_num = (v_repeat_shift == 0) ? ch_num : (y & (NUM_FRAME_LINES - 1));
|
||||
const uint line_buf_total_len = ((timing_mode->h_active_pixels * line_bytes_per_pixel) >> 2) + count_of(vactive_line_header);
|
||||
|
||||
ch->read_addr = (uintptr_t)&line_buffers[new_line_num * line_buf_total_len];
|
||||
ch->transfer_count = line_buf_total_len;
|
||||
|
||||
// Fill line buffer
|
||||
if (line_num != new_line_num)
|
||||
{
|
||||
line_num = new_line_num;
|
||||
uint32_t* dst_ptr = &line_buffers[line_num * line_buf_total_len + count_of(vactive_line_header)];
|
||||
|
||||
if (line_bytes_per_pixel == 2) {
|
||||
uint16_t* src_ptr = (uint16_t*)&frame_buffer_display[y * 2 * (timing_mode->h_active_pixels >> h_repeat_shift)];
|
||||
for (int i = 0; i < timing_mode->h_active_pixels >> 1; i += 2) {
|
||||
uint32_t val = (uint32_t)(*src_ptr++) * 0x10001;
|
||||
*dst_ptr++ = val;
|
||||
*dst_ptr++ = val;
|
||||
}
|
||||
}
|
||||
else if (line_bytes_per_pixel == 1) {
|
||||
uint8_t* src_ptr = &frame_buffer_display[y * (timing_mode->h_active_pixels >> h_repeat_shift)];
|
||||
for (int i = 0; i < timing_mode->h_active_pixels >> 2; ++i) {
|
||||
uint32_t val = (uint32_t)(*src_ptr++) * 0x01010101;
|
||||
*dst_ptr++ = val;
|
||||
}
|
||||
}
|
||||
else if (line_bytes_per_pixel == 4) {
|
||||
uint8_t* src_ptr = &frame_buffer_display[y * (timing_mode->h_active_pixels >> h_repeat_shift)];
|
||||
if (h_repeat_shift == 2) {
|
||||
for (int i = 0; i < timing_mode->h_active_pixels; i += 4) {
|
||||
uint32_t val = display_palette[*src_ptr++];
|
||||
*dst_ptr++ = val;
|
||||
*dst_ptr++ = val;
|
||||
*dst_ptr++ = val;
|
||||
*dst_ptr++ = val;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < timing_mode->h_active_pixels; i += 2) {
|
||||
uint32_t val = display_palette[*src_ptr++];
|
||||
*dst_ptr++ = val;
|
||||
*dst_ptr++ = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (++v_scanline == v_total_active_lines) {
|
||||
v_scanline = 0;
|
||||
line_num = -1;
|
||||
if (flip_next) {
|
||||
flip_next = false;
|
||||
display->flip_now();
|
||||
}
|
||||
__sev();
|
||||
}
|
||||
}
|
||||
|
||||
void __scratch_x("display") dma_irq_handler_text() {
|
||||
display->text_dma_handler();
|
||||
}
|
||||
|
||||
void __scratch_x("display") DVHSTX::text_dma_handler() {
|
||||
// ch_num indicates the channel that just finished, which is the one
|
||||
// we're about to reload.
|
||||
dma_channel_hw_t *ch = &dma_hw->ch[ch_num];
|
||||
dma_hw->intr = 1u << ch_num;
|
||||
if (++ch_num == NUM_CHANS) ch_num = 0;
|
||||
|
||||
if (v_scanline >= timing_mode->v_front_porch && v_scanline < (timing_mode->v_front_porch + timing_mode->v_sync_width)) {
|
||||
ch->read_addr = (uintptr_t)vblank_line_vsync_on;
|
||||
ch->transfer_count = count_of(vblank_line_vsync_on);
|
||||
} else if (v_scanline < v_inactive_total) {
|
||||
ch->read_addr = (uintptr_t)vblank_line_vsync_off;
|
||||
ch->transfer_count = count_of(vblank_line_vsync_off);
|
||||
} else {
|
||||
const int y = (v_scanline - v_inactive_total);
|
||||
const uint line_buf_total_len = (frame_width * line_bytes_per_pixel + 3) / 4 + count_of(vactive_text_line_header);
|
||||
|
||||
ch->read_addr = (uintptr_t)&line_buffers[ch_num * line_buf_total_len];
|
||||
ch->transfer_count = line_buf_total_len;
|
||||
|
||||
// Fill line buffer
|
||||
int char_y = y % 24;
|
||||
if (line_bytes_per_pixel == 4) {
|
||||
uint32_t* dst_ptr = &line_buffers[ch_num * line_buf_total_len + count_of(vactive_text_line_header)];
|
||||
uint8_t* src_ptr = &frame_buffer_display[(y / 24) * frame_width];
|
||||
for (int i = 0; i < frame_width; ++i) {
|
||||
*dst_ptr++ = render_char_line(*src_ptr++, char_y);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint8_t* dst_ptr = (uint8_t*)&line_buffers[ch_num * line_buf_total_len + count_of(vactive_text_line_header)];
|
||||
uint8_t* src_ptr = &frame_buffer_display[(y / 24) * frame_width];
|
||||
uint8_t* colour_ptr = src_ptr + frame_width * frame_height;
|
||||
int i = 0;
|
||||
for (; i < frame_width-1; i += 2) {
|
||||
uint8_t c = (*src_ptr++ - 0x20);
|
||||
uint32_t bits = (c < 95) ? font_cache[c * 24 + char_y] : 0;
|
||||
uint8_t colour = *colour_ptr++;
|
||||
c = (*src_ptr++ - 0x20);
|
||||
uint32_t bits2 = (c < 95) ? font_cache[c * 24 + char_y] : 0;
|
||||
uint8_t colour2 = *colour_ptr++;
|
||||
|
||||
// This ASM works around a compiler bug where the optimizer decides
|
||||
// to unroll so hard it spills to the stack.
|
||||
uint32_t tmp, tmp2;
|
||||
asm volatile (
|
||||
"ubfx %[tmp], %[cbits], #24, #2\n\t"
|
||||
"ubfx %[tmp2], %[cbits], #22, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #8, #8\n\t"
|
||||
"ubfx %[tmp2], %[cbits], #20, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #16, #8\n\t"
|
||||
"ubfx %[tmp2], %[cbits], #18, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #24, #8\n\t"
|
||||
"muls %[tmp], %[colour], %[tmp]\n\t"
|
||||
"str %[tmp], [%[dst_ptr]]\n\t"
|
||||
|
||||
"ubfx %[tmp], %[cbits], #16, #2\n\t"
|
||||
"ubfx %[tmp2], %[cbits], #14, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #8, #8\n\t"
|
||||
"ubfx %[tmp2], %[cbits], #12, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #16, #8\n\t"
|
||||
"ubfx %[tmp2], %[cbits], #10, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #24, #8\n\t"
|
||||
"muls %[tmp], %[colour], %[tmp]\n\t"
|
||||
"str %[tmp], [%[dst_ptr], #4]\n\t"
|
||||
|
||||
"ubfx %[tmp], %[cbits], #8, #2\n\t"
|
||||
"ubfx %[tmp2], %[cbits], #6, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #8, #8\n\t"
|
||||
"ubfx %[tmp2], %[cbits], #4, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #16, #8\n\t"
|
||||
"ubfx %[tmp2], %[cbits], #2, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #24, #8\n\t"
|
||||
"muls %[tmp], %[colour], %[tmp]\n\t"
|
||||
"str %[tmp], [%[dst_ptr], #8]\n\t"
|
||||
|
||||
"ubfx %[tmp], %[cbits2], #24, #2\n\t"
|
||||
"ubfx %[tmp2], %[cbits2], #22, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #8, #8\n\t"
|
||||
"muls %[tmp], %[colour2], %[tmp]\n\t"
|
||||
"and %[tmp2], %[cbits], #3\n\t"
|
||||
"muls %[tmp2], %[colour], %[tmp2]\n\t"
|
||||
"bfi %[tmp2], %[tmp], #16, #16\n\t"
|
||||
"str %[tmp2], [%[dst_ptr], #12]\n\t"
|
||||
|
||||
"ubfx %[tmp], %[cbits2], #20, #2\n\t"
|
||||
"ubfx %[tmp2], %[cbits2], #18, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #8, #8\n\t"
|
||||
"ubfx %[tmp2], %[cbits2], #16, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #16, #8\n\t"
|
||||
"ubfx %[tmp2], %[cbits2], #14, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #24, #8\n\t"
|
||||
"muls %[tmp], %[colour2], %[tmp]\n\t"
|
||||
"str %[tmp], [%[dst_ptr], #16]\n\t"
|
||||
|
||||
"ubfx %[tmp], %[cbits2], #12, #2\n\t"
|
||||
"ubfx %[tmp2], %[cbits2], #10, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #8, #8\n\t"
|
||||
"ubfx %[tmp2], %[cbits2], #8, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #16, #8\n\t"
|
||||
"ubfx %[tmp2], %[cbits2], #6, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #24, #8\n\t"
|
||||
"muls %[tmp], %[colour2], %[tmp]\n\t"
|
||||
"str %[tmp], [%[dst_ptr], #20]\n\t"
|
||||
|
||||
"ubfx %[tmp], %[cbits2], #4, #2\n\t"
|
||||
"ubfx %[tmp2], %[cbits2], #2, #2\n\t"
|
||||
"bfi %[tmp], %[tmp2], #8, #8\n\t"
|
||||
"bfi %[tmp], %[cbits2], #16, #2\n\t"
|
||||
"muls %[tmp], %[colour2], %[tmp]\n\t"
|
||||
"str %[tmp], [%[dst_ptr], #24]\n\t"
|
||||
: [tmp] "=&l" (tmp),
|
||||
[tmp2] "=&l" (tmp2)
|
||||
: [cbits] "r" (bits),
|
||||
[colour] "l" (colour),
|
||||
[cbits2] "r" (bits2),
|
||||
[colour2] "l" (colour2),
|
||||
[dst_ptr] "r" (dst_ptr)
|
||||
: "cc", "memory" );
|
||||
dst_ptr += 14 * 2;
|
||||
}
|
||||
if (i != frame_width) {
|
||||
const uint8_t c = (*src_ptr++ - 0x20);
|
||||
uint32_t bits = (c < 95) ? font_cache[c * 24 + char_y] : 0;
|
||||
const uint8_t colour = *colour_ptr++;
|
||||
|
||||
*dst_ptr++ = colour * ((bits >> 24) & 3);
|
||||
*dst_ptr++ = colour * ((bits >> 22) & 3);
|
||||
*dst_ptr++ = colour * ((bits >> 20) & 3);
|
||||
*dst_ptr++ = colour * ((bits >> 18) & 3);
|
||||
*dst_ptr++ = colour * ((bits >> 16) & 3);
|
||||
*dst_ptr++ = colour * ((bits >> 14) & 3);
|
||||
*dst_ptr++ = colour * ((bits >> 12) & 3);
|
||||
*dst_ptr++ = colour * ((bits >> 10) & 3);
|
||||
*dst_ptr++ = colour * ((bits >> 8) & 3);
|
||||
*dst_ptr++ = colour * ((bits >> 6) & 3);
|
||||
*dst_ptr++ = colour * ((bits >> 4) & 3);
|
||||
*dst_ptr++ = colour * ((bits >> 2) & 3);
|
||||
*dst_ptr++ = colour * (bits & 3);
|
||||
*dst_ptr++ = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (++v_scanline == v_total_active_lines) {
|
||||
v_scanline = 0;
|
||||
line_num = -1;
|
||||
if (flip_next) {
|
||||
flip_next = false;
|
||||
display->flip_now();
|
||||
}
|
||||
__sev();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Experimental clock config
|
||||
|
||||
static void __no_inline_not_in_flash_func(set_qmi_timing)() {
|
||||
// Make sure flash is deselected - QMI doesn't appear to have a busy flag(!)
|
||||
while ((ioqspi_hw->io[1].status & IO_QSPI_GPIO_QSPI_SS_STATUS_OUTTOPAD_BITS) != IO_QSPI_GPIO_QSPI_SS_STATUS_OUTTOPAD_BITS)
|
||||
;
|
||||
|
||||
qmi_hw->m[0].timing = 0x40000202;
|
||||
//qmi_hw->m[0].timing = 0x40000101;
|
||||
// Force a read through XIP to ensure the timing is applied
|
||||
volatile uint32_t* ptr = (volatile uint32_t*)0x14000000;
|
||||
(void) *ptr;
|
||||
}
|
||||
|
||||
void DVHSTX::display_setup_clock() {
|
||||
// Before messing with clock speeds ensure QSPI clock is nice and slow
|
||||
hw_write_masked(&qmi_hw->m[0].timing, 6, QMI_M0_TIMING_CLKDIV_BITS);
|
||||
|
||||
// We're going to go fast, boost the voltage a little
|
||||
vreg_set_voltage(VREG_VOLTAGE_1_15);
|
||||
|
||||
// Force a read through XIP to ensure the timing is applied before raising the clock rate
|
||||
volatile uint32_t* ptr = (volatile uint32_t*)0x14000000;
|
||||
(void) *ptr;
|
||||
|
||||
const uint32_t dvi_clock_khz = timing_mode->bit_clk_khz >> 1;
|
||||
uint vco_freq, post_div1, post_div2;
|
||||
if (!check_sys_clock_khz(dvi_clock_khz, &vco_freq, &post_div1, &post_div2))
|
||||
panic("System clock of %u kHz cannot be exactly achieved", dvi_clock_khz);
|
||||
const uint32_t freq = vco_freq / (post_div1 * post_div2);
|
||||
|
||||
// Before we touch PLLs, switch sys and ref cleanly away from their aux sources.
|
||||
hw_clear_bits(&clocks_hw->clk[clk_sys].ctrl, CLOCKS_CLK_SYS_CTRL_SRC_BITS);
|
||||
while (clocks_hw->clk[clk_sys].selected != 0x1)
|
||||
tight_loop_contents();
|
||||
hw_write_masked(&clocks_hw->clk[clk_ref].ctrl, CLOCKS_CLK_REF_CTRL_SRC_VALUE_XOSC_CLKSRC, CLOCKS_CLK_REF_CTRL_SRC_BITS);
|
||||
while (clocks_hw->clk[clk_ref].selected != 0x4)
|
||||
tight_loop_contents();
|
||||
|
||||
// Stop the other clocks so we don't worry about overspeed
|
||||
clock_stop(clk_usb);
|
||||
clock_stop(clk_adc);
|
||||
clock_stop(clk_peri);
|
||||
clock_stop(clk_hstx);
|
||||
|
||||
// Set the sys PLL to the requested freq, set USB PLL to 528MHz
|
||||
pll_init(pll_sys, PLL_COMMON_REFDIV, vco_freq, post_div1, post_div2);
|
||||
pll_init(pll_usb, PLL_COMMON_REFDIV, 1584 * MHZ, 3, 1);
|
||||
|
||||
const uint32_t usb_pll_freq = 528 * MHZ;
|
||||
|
||||
// CLK SYS = PLL USB 528MHz / 2 = 264MHz
|
||||
clock_configure(clk_sys,
|
||||
CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
|
||||
CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
|
||||
usb_pll_freq, usb_pll_freq / 2);
|
||||
|
||||
// CLK PERI = PLL USB 528MHz / 4 = 132MHz
|
||||
clock_configure(clk_peri,
|
||||
0, // Only AUX mux on ADC
|
||||
CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
|
||||
usb_pll_freq, usb_pll_freq / 4);
|
||||
|
||||
// CLK USB = PLL USB 528MHz / 11 = 48MHz
|
||||
clock_configure(clk_usb,
|
||||
0, // No GLMUX
|
||||
CLOCKS_CLK_USB_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
|
||||
usb_pll_freq,
|
||||
USB_CLK_KHZ * KHZ);
|
||||
|
||||
// CLK ADC = PLL USB 528MHz / 11 = 48MHz
|
||||
clock_configure(clk_adc,
|
||||
0, // No GLMUX
|
||||
CLOCKS_CLK_ADC_CTRL_AUXSRC_VALUE_CLKSRC_PLL_USB,
|
||||
usb_pll_freq,
|
||||
USB_CLK_KHZ * KHZ);
|
||||
|
||||
// CLK HSTX = Requested freq
|
||||
clock_configure(clk_hstx,
|
||||
0,
|
||||
CLOCKS_CLK_HSTX_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
|
||||
freq, freq);
|
||||
|
||||
// Now we are running fast set fast QSPI clock and read delay
|
||||
set_qmi_timing();
|
||||
}
|
||||
|
||||
void DVHSTX::write_pixel(const Point &p, uint16_t colour)
|
||||
{
|
||||
*point_to_ptr16(p) = colour;
|
||||
}
|
||||
|
||||
void DVHSTX::write_pixel_span(const Point &p, uint l, uint16_t colour)
|
||||
{
|
||||
uint16_t* ptr = point_to_ptr16(p);
|
||||
for (uint i = 0; i < l; ++i) ptr[i] = colour;
|
||||
}
|
||||
|
||||
void DVHSTX::write_pixel_span(const Point &p, uint l, uint16_t *data)
|
||||
{
|
||||
uint16_t* ptr = point_to_ptr16(p);
|
||||
for (uint i = 0; i < l; ++i) ptr[i] = data[i];
|
||||
}
|
||||
|
||||
void DVHSTX::read_pixel_span(const Point &p, uint l, uint16_t *data)
|
||||
{
|
||||
const uint16_t* ptr = point_to_ptr16(p);
|
||||
for (uint i = 0; i < l; ++i) data[i] = ptr[i];
|
||||
}
|
||||
|
||||
void DVHSTX::set_palette(RGB888 new_palette[PALETTE_SIZE])
|
||||
{
|
||||
memcpy(palette, new_palette, PALETTE_SIZE * sizeof(RGB888));
|
||||
}
|
||||
|
||||
void DVHSTX::set_palette_colour(uint8_t entry, RGB888 colour)
|
||||
{
|
||||
palette[entry] = colour;
|
||||
}
|
||||
|
||||
RGB888* DVHSTX::get_palette()
|
||||
{
|
||||
return palette;
|
||||
}
|
||||
|
||||
void DVHSTX::write_palette_pixel(const Point &p, uint8_t colour)
|
||||
{
|
||||
*point_to_ptr_palette(p) = colour;
|
||||
}
|
||||
|
||||
void DVHSTX::write_palette_pixel_span(const Point &p, uint l, uint8_t colour)
|
||||
{
|
||||
uint8_t* ptr = point_to_ptr_palette(p);
|
||||
memset(ptr, colour, l);
|
||||
}
|
||||
|
||||
void DVHSTX::write_palette_pixel_span(const Point &p, uint l, uint8_t* data)
|
||||
{
|
||||
uint8_t* ptr = point_to_ptr_palette(p);
|
||||
memcpy(ptr, data, l);
|
||||
}
|
||||
|
||||
void DVHSTX::read_palette_pixel_span(const Point &p, uint l, uint8_t *data)
|
||||
{
|
||||
const uint8_t* ptr = point_to_ptr_palette(p);
|
||||
memcpy(data, ptr, l);
|
||||
}
|
||||
|
||||
void DVHSTX::write_text(const Point &p, const char* text, TextColour colour, bool immediate)
|
||||
{
|
||||
char* ptr = (char*)point_to_ptr_text(p, immediate);
|
||||
int len = std::min((int)(frame_width - p.x), (int)strlen(text));
|
||||
memcpy(ptr, text, len);
|
||||
if (mode == MODE_TEXT_RGB111) memset(ptr + frame_width * frame_height, (uint8_t)colour, len);
|
||||
}
|
||||
|
||||
void DVHSTX::clear()
|
||||
{
|
||||
memset(frame_buffer_back, 0, frame_width * frame_height * frame_bytes_per_pixel);
|
||||
}
|
||||
|
||||
bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_)
|
||||
{
|
||||
display_width = width;
|
||||
display_height = height;
|
||||
frame_width = width;
|
||||
frame_height = height;
|
||||
mode = mode_;
|
||||
|
||||
timing_mode = nullptr;
|
||||
if (mode == MODE_TEXT_MONO || mode == MODE_TEXT_RGB111) {
|
||||
width = 1280;
|
||||
height = 720;
|
||||
display_width = 91;
|
||||
frame_width = 91;
|
||||
display_height = 30;
|
||||
frame_height = 30;
|
||||
h_repeat_shift = 0;
|
||||
v_repeat_shift = 0;
|
||||
timing_mode = &dvi_timing_1280x720p_rb_50hz;
|
||||
}
|
||||
else if (width == 320 && height == 180) {
|
||||
h_repeat_shift = 2;
|
||||
v_repeat_shift = 2;
|
||||
timing_mode = &dvi_timing_1280x720p_rb_50hz;
|
||||
}
|
||||
else if (width == 640 && height == 360) {
|
||||
h_repeat_shift = 1;
|
||||
v_repeat_shift = 1;
|
||||
timing_mode = &dvi_timing_1280x720p_rb_50hz;
|
||||
}
|
||||
else if (width == 480 && height == 270) {
|
||||
h_repeat_shift = 2;
|
||||
v_repeat_shift = 2;
|
||||
timing_mode = &dvi_timing_1920x1080p_rb2_30hz;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t full_width = display_width;
|
||||
uint16_t full_height = display_height;
|
||||
h_repeat_shift = 0;
|
||||
v_repeat_shift = 0;
|
||||
|
||||
if (display_width < 640) {
|
||||
h_repeat_shift = 1;
|
||||
full_width *= 2;
|
||||
}
|
||||
|
||||
if (display_height < 400) {
|
||||
v_repeat_shift = 1;
|
||||
full_height *= 2;
|
||||
}
|
||||
|
||||
if (full_width == 640) {
|
||||
if (full_height == 480) timing_mode = &dvi_timing_640x480p_60hz;
|
||||
}
|
||||
else if (full_width == 720) {
|
||||
if (full_height == 480) timing_mode = &dvi_timing_720x480p_60hz;
|
||||
else if (full_height == 400) timing_mode = &dvi_timing_720x400p_70hz;
|
||||
else if (full_height == 576) timing_mode = &dvi_timing_720x576p_50hz;
|
||||
}
|
||||
else if (full_width == 800) {
|
||||
if (full_height == 600) timing_mode = &dvi_timing_800x600p_60hz;
|
||||
else if (full_height == 480) timing_mode = &dvi_timing_800x480p_60hz;
|
||||
else if (full_height == 450) timing_mode = &dvi_timing_800x450p_60hz;
|
||||
}
|
||||
else if (full_width == 960) {
|
||||
if (full_height == 540) timing_mode = &dvi_timing_960x540p_60hz;
|
||||
}
|
||||
else if (full_width == 1024) {
|
||||
if (full_height == 768) timing_mode = &dvi_timing_1024x768_rb_60hz;
|
||||
}
|
||||
}
|
||||
|
||||
if (!timing_mode) {
|
||||
printf("Unsupported resolution %dx%d", width, height);
|
||||
return false;
|
||||
}
|
||||
|
||||
display = this;
|
||||
display_palette = get_palette();
|
||||
|
||||
display_setup_clock();
|
||||
|
||||
stdio_init_all();
|
||||
|
||||
v_inactive_total = timing_mode->v_front_porch + timing_mode->v_sync_width + timing_mode->v_back_porch;
|
||||
v_total_active_lines = v_inactive_total + timing_mode->v_active_lines;
|
||||
v_repeat = 1 << v_repeat_shift;
|
||||
h_repeat = 1 << h_repeat_shift;
|
||||
|
||||
vblank_line_vsync_off[0] |= timing_mode->h_front_porch;
|
||||
vblank_line_vsync_off[2] |= timing_mode->h_sync_width;
|
||||
vblank_line_vsync_off[4] |= timing_mode->h_back_porch + timing_mode->h_active_pixels;
|
||||
|
||||
vblank_line_vsync_on[0] |= timing_mode->h_front_porch;
|
||||
vblank_line_vsync_on[2] |= timing_mode->h_sync_width;
|
||||
vblank_line_vsync_on[4] |= timing_mode->h_back_porch + timing_mode->h_active_pixels;
|
||||
|
||||
vactive_line_header[0] |= timing_mode->h_front_porch;
|
||||
vactive_line_header[2] |= timing_mode->h_sync_width;
|
||||
vactive_line_header[4] |= timing_mode->h_back_porch;
|
||||
vactive_line_header[6] |= timing_mode->h_active_pixels;
|
||||
|
||||
vactive_text_line_header[0] |= timing_mode->h_front_porch;
|
||||
vactive_text_line_header[2] |= timing_mode->h_sync_width;
|
||||
vactive_text_line_header[4] |= timing_mode->h_back_porch;
|
||||
vactive_text_line_header[7+6] |= timing_mode->h_active_pixels - 6;
|
||||
|
||||
switch (mode) {
|
||||
case MODE_RGB565:
|
||||
frame_bytes_per_pixel = 2;
|
||||
line_bytes_per_pixel = 2;
|
||||
break;
|
||||
case MODE_PALETTE:
|
||||
frame_bytes_per_pixel = 1;
|
||||
line_bytes_per_pixel = 4;
|
||||
break;
|
||||
case MODE_RGB888:
|
||||
frame_bytes_per_pixel = 4;
|
||||
line_bytes_per_pixel = 4;
|
||||
break;
|
||||
case MODE_TEXT_MONO:
|
||||
frame_bytes_per_pixel = 1;
|
||||
line_bytes_per_pixel = 4;
|
||||
break;
|
||||
case MODE_TEXT_RGB111:
|
||||
frame_bytes_per_pixel = 2;
|
||||
line_bytes_per_pixel = 14;
|
||||
break;
|
||||
default:
|
||||
printf("Unsupported mode %d", (int)mode);
|
||||
return false;
|
||||
}
|
||||
|
||||
frame_buffer_display = (uint8_t*)malloc(frame_width * frame_height * frame_bytes_per_pixel);
|
||||
frame_buffer_back = (uint8_t*)malloc(frame_width * frame_height * frame_bytes_per_pixel);
|
||||
memset(frame_buffer_display, 0, frame_width * frame_height * frame_bytes_per_pixel);
|
||||
memset(frame_buffer_back, 0, frame_width * frame_height * frame_bytes_per_pixel);
|
||||
|
||||
memset(palette, 0, PALETTE_SIZE);
|
||||
|
||||
frame_buffer_display = frame_buffer_display;
|
||||
|
||||
const bool is_text_mode = (mode == MODE_TEXT_MONO || mode == MODE_TEXT_RGB111);
|
||||
const int frame_pixel_words = (frame_width * h_repeat * line_bytes_per_pixel + 3) >> 2;
|
||||
const int frame_line_words = frame_pixel_words + (is_text_mode ? count_of(vactive_text_line_header) : count_of(vactive_line_header));
|
||||
const int frame_lines = (v_repeat == 1) ? NUM_CHANS : NUM_FRAME_LINES;
|
||||
line_buffers = (uint32_t*)malloc(frame_line_words * 4 * frame_lines);
|
||||
|
||||
for (int i = 0; i < frame_lines; ++i)
|
||||
{
|
||||
if (is_text_mode) memcpy(&line_buffers[i * frame_line_words], vactive_text_line_header, count_of(vactive_text_line_header) * sizeof(uint32_t));
|
||||
else memcpy(&line_buffers[i * frame_line_words], vactive_line_header, count_of(vactive_line_header) * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
if (mode == MODE_TEXT_RGB111) {
|
||||
// Need to pre-render the font to RAM to be fast enough.
|
||||
font_cache = (uint32_t*)malloc(4 * FONT->line_height * 95);
|
||||
uint32_t* font_cache_ptr = font_cache;
|
||||
for (int c = 0x20; c < 128; ++c) {
|
||||
for (int y = 0; y < FONT->line_height; ++y) {
|
||||
*font_cache_ptr++ = render_char_line(c, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case MODE_RGB565:
|
||||
// Configure HSTX's TMDS encoder for RGB565
|
||||
hstx_ctrl_hw->expand_tmds =
|
||||
4 << HSTX_CTRL_EXPAND_TMDS_L2_NBITS_LSB |
|
||||
8 << HSTX_CTRL_EXPAND_TMDS_L2_ROT_LSB |
|
||||
5 << HSTX_CTRL_EXPAND_TMDS_L1_NBITS_LSB |
|
||||
3 << HSTX_CTRL_EXPAND_TMDS_L1_ROT_LSB |
|
||||
4 << HSTX_CTRL_EXPAND_TMDS_L0_NBITS_LSB |
|
||||
29 << HSTX_CTRL_EXPAND_TMDS_L0_ROT_LSB;
|
||||
|
||||
// Pixels (TMDS) come in 2 16-bit chunks. Control symbols (RAW) are an
|
||||
// entire 32-bit word.
|
||||
hstx_ctrl_hw->expand_shift =
|
||||
2 << HSTX_CTRL_EXPAND_SHIFT_ENC_N_SHIFTS_LSB |
|
||||
16 << HSTX_CTRL_EXPAND_SHIFT_ENC_SHIFT_LSB |
|
||||
1 << HSTX_CTRL_EXPAND_SHIFT_RAW_N_SHIFTS_LSB |
|
||||
0 << HSTX_CTRL_EXPAND_SHIFT_RAW_SHIFT_LSB;
|
||||
break;
|
||||
|
||||
case MODE_PALETTE:
|
||||
// Configure HSTX's TMDS encoder for RGB888
|
||||
hstx_ctrl_hw->expand_tmds =
|
||||
7 << HSTX_CTRL_EXPAND_TMDS_L2_NBITS_LSB |
|
||||
16 << HSTX_CTRL_EXPAND_TMDS_L2_ROT_LSB |
|
||||
7 << HSTX_CTRL_EXPAND_TMDS_L1_NBITS_LSB |
|
||||
8 << HSTX_CTRL_EXPAND_TMDS_L1_ROT_LSB |
|
||||
7 << HSTX_CTRL_EXPAND_TMDS_L0_NBITS_LSB |
|
||||
0 << HSTX_CTRL_EXPAND_TMDS_L0_ROT_LSB;
|
||||
|
||||
// Pixels and control symbols (RAW) are an
|
||||
// entire 32-bit word.
|
||||
hstx_ctrl_hw->expand_shift =
|
||||
1 << HSTX_CTRL_EXPAND_SHIFT_ENC_N_SHIFTS_LSB |
|
||||
0 << HSTX_CTRL_EXPAND_SHIFT_ENC_SHIFT_LSB |
|
||||
1 << HSTX_CTRL_EXPAND_SHIFT_RAW_N_SHIFTS_LSB |
|
||||
0 << HSTX_CTRL_EXPAND_SHIFT_RAW_SHIFT_LSB;
|
||||
break;
|
||||
|
||||
case MODE_TEXT_MONO:
|
||||
// Configure HSTX's TMDS encoder for 2bpp
|
||||
hstx_ctrl_hw->expand_tmds =
|
||||
1 << HSTX_CTRL_EXPAND_TMDS_L2_NBITS_LSB |
|
||||
18 << HSTX_CTRL_EXPAND_TMDS_L2_ROT_LSB |
|
||||
1 << HSTX_CTRL_EXPAND_TMDS_L1_NBITS_LSB |
|
||||
18 << HSTX_CTRL_EXPAND_TMDS_L1_ROT_LSB |
|
||||
1 << HSTX_CTRL_EXPAND_TMDS_L0_NBITS_LSB |
|
||||
18 << HSTX_CTRL_EXPAND_TMDS_L0_ROT_LSB;
|
||||
|
||||
// Pixels and control symbols (RAW) are an
|
||||
// entire 32-bit word.
|
||||
hstx_ctrl_hw->expand_shift =
|
||||
14 << HSTX_CTRL_EXPAND_SHIFT_ENC_N_SHIFTS_LSB |
|
||||
30 << HSTX_CTRL_EXPAND_SHIFT_ENC_SHIFT_LSB |
|
||||
1 << HSTX_CTRL_EXPAND_SHIFT_RAW_N_SHIFTS_LSB |
|
||||
0 << HSTX_CTRL_EXPAND_SHIFT_RAW_SHIFT_LSB;
|
||||
break;
|
||||
|
||||
case MODE_TEXT_RGB111:
|
||||
// Configure HSTX's TMDS encoder for RGB222
|
||||
hstx_ctrl_hw->expand_tmds =
|
||||
1 << HSTX_CTRL_EXPAND_TMDS_L2_NBITS_LSB |
|
||||
0 << HSTX_CTRL_EXPAND_TMDS_L2_ROT_LSB |
|
||||
1 << HSTX_CTRL_EXPAND_TMDS_L1_NBITS_LSB |
|
||||
29 << HSTX_CTRL_EXPAND_TMDS_L1_ROT_LSB |
|
||||
1 << HSTX_CTRL_EXPAND_TMDS_L0_NBITS_LSB |
|
||||
26 << HSTX_CTRL_EXPAND_TMDS_L0_ROT_LSB;
|
||||
|
||||
// Pixels (TMDS) come in 4 8-bit chunks. Control symbols (RAW) are an
|
||||
// entire 32-bit word.
|
||||
hstx_ctrl_hw->expand_shift =
|
||||
4 << HSTX_CTRL_EXPAND_SHIFT_ENC_N_SHIFTS_LSB |
|
||||
8 << HSTX_CTRL_EXPAND_SHIFT_ENC_SHIFT_LSB |
|
||||
1 << HSTX_CTRL_EXPAND_SHIFT_RAW_N_SHIFTS_LSB |
|
||||
0 << HSTX_CTRL_EXPAND_SHIFT_RAW_SHIFT_LSB;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("Unsupported mode %d", (int)mode);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Serial output config: clock period of 5 cycles, pop from command
|
||||
// expander every 5 cycles, shift the output shiftreg by 2 every cycle.
|
||||
hstx_ctrl_hw->csr = 0;
|
||||
hstx_ctrl_hw->csr =
|
||||
HSTX_CTRL_CSR_EXPAND_EN_BITS |
|
||||
5u << HSTX_CTRL_CSR_CLKDIV_LSB |
|
||||
5u << HSTX_CTRL_CSR_N_SHIFTS_LSB |
|
||||
2u << HSTX_CTRL_CSR_SHIFT_LSB |
|
||||
HSTX_CTRL_CSR_EN_BITS;
|
||||
|
||||
// HSTX outputs 0 through 7 appear on GPIO 12 through 19.
|
||||
|
||||
// Assign clock pair to two neighbouring pins:
|
||||
hstx_ctrl_hw->bit[1] = HSTX_CTRL_BIT0_CLK_BITS;
|
||||
hstx_ctrl_hw->bit[0] = HSTX_CTRL_BIT0_CLK_BITS | HSTX_CTRL_BIT0_INV_BITS;
|
||||
for (uint lane = 0; lane < 3; ++lane) {
|
||||
// For each TMDS lane, assign it to the correct GPIO pair based on the
|
||||
// desired pinout:
|
||||
static const int lane_to_output_bit[3] = {2, 4, 6};
|
||||
int bit = lane_to_output_bit[lane];
|
||||
// Output even bits during first half of each HSTX cycle, and odd bits
|
||||
// during second half. The shifter advances by two bits each cycle.
|
||||
uint32_t lane_data_sel_bits =
|
||||
(lane * 10 ) << HSTX_CTRL_BIT0_SEL_P_LSB |
|
||||
(lane * 10 + 1) << HSTX_CTRL_BIT0_SEL_N_LSB;
|
||||
// The two halves of each pair get identical data, but one pin is inverted.
|
||||
hstx_ctrl_hw->bit[bit ] = lane_data_sel_bits | HSTX_CTRL_BIT0_INV_BITS;
|
||||
hstx_ctrl_hw->bit[bit + 1] = lane_data_sel_bits;
|
||||
}
|
||||
|
||||
for (int i = 12; i <= 19; ++i) {
|
||||
gpio_set_function(i, GPIO_FUNC_HSTX);
|
||||
gpio_set_drive_strength(i, GPIO_DRIVE_STRENGTH_4MA);
|
||||
}
|
||||
|
||||
// Always use the bottom channels
|
||||
dma_claim_mask((1 << NUM_CHANS) - 1);
|
||||
|
||||
// The channels are set up identically, to transfer a whole scanline and
|
||||
// then chain to the next channel. Each time a channel finishes, we
|
||||
// reconfigure the one that just finished, meanwhile the other channel(s)
|
||||
// are already making progress.
|
||||
// Using just 2 channels was insufficient to avoid issues with the IRQ.
|
||||
dma_channel_config c;
|
||||
c = dma_channel_get_default_config(0);
|
||||
channel_config_set_chain_to(&c, 1);
|
||||
channel_config_set_dreq(&c, DREQ_HSTX);
|
||||
dma_channel_configure(
|
||||
0,
|
||||
&c,
|
||||
&hstx_fifo_hw->fifo,
|
||||
vblank_line_vsync_off,
|
||||
count_of(vblank_line_vsync_off),
|
||||
false
|
||||
);
|
||||
c = dma_channel_get_default_config(1);
|
||||
channel_config_set_chain_to(&c, 2);
|
||||
channel_config_set_dreq(&c, DREQ_HSTX);
|
||||
dma_channel_configure(
|
||||
1,
|
||||
&c,
|
||||
&hstx_fifo_hw->fifo,
|
||||
vblank_line_vsync_off,
|
||||
count_of(vblank_line_vsync_off),
|
||||
false
|
||||
);
|
||||
for (int i = 2; i < NUM_CHANS; ++i) {
|
||||
c = dma_channel_get_default_config(i);
|
||||
channel_config_set_chain_to(&c, (i+1) % NUM_CHANS);
|
||||
channel_config_set_dreq(&c, DREQ_HSTX);
|
||||
dma_channel_configure(
|
||||
i,
|
||||
&c,
|
||||
&hstx_fifo_hw->fifo,
|
||||
vblank_line_vsync_off,
|
||||
count_of(vblank_line_vsync_off),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
dma_hw->ints0 = (1 << NUM_CHANS) - 1;
|
||||
dma_hw->inte0 = (1 << NUM_CHANS) - 1;
|
||||
if (is_text_mode) irq_set_exclusive_handler(DMA_IRQ_0, dma_irq_handler_text);
|
||||
else irq_set_exclusive_handler(DMA_IRQ_0, dma_irq_handler);
|
||||
irq_set_enabled(DMA_IRQ_0, true);
|
||||
|
||||
dma_channel_start(0);
|
||||
|
||||
for (int i = 0; i < frame_height; ++i) {
|
||||
memset(&frame_buffer_display[i * frame_width * frame_bytes_per_pixel], i, frame_width * frame_bytes_per_pixel);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DVHSTX::flip_blocking() {
|
||||
wait_for_vsync();
|
||||
flip_now();
|
||||
}
|
||||
|
||||
void DVHSTX::flip_now() {
|
||||
std::swap(frame_buffer_display, frame_buffer_back);
|
||||
}
|
||||
|
||||
void DVHSTX::wait_for_vsync() {
|
||||
while (v_scanline >= timing_mode->v_front_porch) __wfe();
|
||||
}
|
||||
|
||||
void DVHSTX::flip_async() {
|
||||
flip_next = true;
|
||||
}
|
||||
|
||||
void DVHSTX::wait_for_flip() {
|
||||
while (flip_next) __wfe();
|
||||
}
|
||||
157
drivers/dvhstx/dvhstx.hpp
Normal file
157
drivers/dvhstx/dvhstx.hpp
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "pico/stdlib.h"
|
||||
#include "hardware/gpio.h"
|
||||
#include "common/pimoroni_common.hpp"
|
||||
#include "common/pimoroni_i2c.hpp"
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
|
||||
// DVI HSTX driver for use with Pimoroni PicoGraphics
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
// Digital Video using HSTX
|
||||
// Valid screen modes are:
|
||||
// Pixel doubled: 640x480 (60Hz), 720x480 (60Hz), 720x400 (70Hz), 720x576 (50Hz),
|
||||
// 800x600 (60Hz), 800x480 (60Hz), 800x450 (60Hz), 960x540 (60Hz), 1024x768 (60Hz)
|
||||
// Pixel doubled or quadrupled: 1280x720 (50Hz)
|
||||
//
|
||||
// Giving valid resolutions:
|
||||
// 320x180, 640x360 (well supported, square pixels on a 16:9 display)
|
||||
// 480x270, 400x225 (sometimes supported, square pixels on a 16:9 display)
|
||||
// 320x240, 360x240, 360x200, 360x288, 400x300, 512x384 (well supported, but pixels aren't square)
|
||||
// 400x240 (sometimes supported, pixels aren't square)
|
||||
//
|
||||
// Note that the double buffer is in RAM, so 640x360 uses almost all of the available RAM.
|
||||
class DVHSTX {
|
||||
public:
|
||||
static constexpr int PALETTE_SIZE = 256;
|
||||
|
||||
enum Mode {
|
||||
MODE_PALETTE = 2,
|
||||
MODE_RGB565 = 1,
|
||||
MODE_RGB888 = 3,
|
||||
MODE_TEXT_MONO = 4,
|
||||
MODE_TEXT_RGB111 = 5,
|
||||
};
|
||||
|
||||
enum TextColour {
|
||||
TEXT_BLACK = 0,
|
||||
TEXT_RED = 0b1000000,
|
||||
TEXT_GREEN = 0b0001000,
|
||||
TEXT_BLUE = 0b0000001,
|
||||
TEXT_YELLOW = 0b1001000,
|
||||
TEXT_MAGENTA = 0b1000001,
|
||||
TEXT_CYAN = 0b0001001,
|
||||
TEXT_WHITE = 0b1001001,
|
||||
};
|
||||
|
||||
//--------------------------------------------------
|
||||
// Variables
|
||||
//--------------------------------------------------
|
||||
protected:
|
||||
friend void vsync_callback();
|
||||
|
||||
uint16_t display_width = 320;
|
||||
uint16_t display_height = 180;
|
||||
uint16_t frame_width = 320;
|
||||
uint16_t frame_height = 180;
|
||||
uint8_t frame_bytes_per_pixel = 2;
|
||||
uint8_t bank = 0;
|
||||
uint8_t h_repeat = 4;
|
||||
uint8_t v_repeat = 4;
|
||||
Mode mode = MODE_RGB565;
|
||||
|
||||
public:
|
||||
DVHSTX()
|
||||
{}
|
||||
|
||||
//--------------------------------------------------
|
||||
// Methods
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
// 16bpp interface
|
||||
void write_pixel(const Point &p, uint16_t colour);
|
||||
void write_pixel_span(const Point &p, uint l, uint16_t colour);
|
||||
void write_pixel_span(const Point &p, uint l, uint16_t *data);
|
||||
void read_pixel_span(const Point &p, uint l, uint16_t *data);
|
||||
|
||||
// 256 colour palette mode.
|
||||
void set_palette(RGB888 new_palette[PALETTE_SIZE]);
|
||||
void set_palette_colour(uint8_t entry, RGB888 colour);
|
||||
RGB888* get_palette();
|
||||
|
||||
void write_palette_pixel(const Point &p, uint8_t colour);
|
||||
void write_palette_pixel_span(const Point &p, uint l, uint8_t colour);
|
||||
void write_palette_pixel_span(const Point &p, uint l, uint8_t* data);
|
||||
void read_palette_pixel_span(const Point &p, uint l, uint8_t *data);
|
||||
|
||||
// Text mode (91 x 30)
|
||||
// Immediate writes to the active buffer instead of the back buffer
|
||||
void write_text(const Point &p, const char* text, TextColour colour = TEXT_WHITE, bool immediate = false);
|
||||
|
||||
void clear();
|
||||
|
||||
bool init(uint16_t width, uint16_t height, Mode mode = MODE_RGB565);
|
||||
|
||||
// Wait for vsync and then flip the buffers
|
||||
void flip_blocking();
|
||||
|
||||
// Flip immediately without waiting for vsync
|
||||
void flip_now();
|
||||
|
||||
void wait_for_vsync();
|
||||
|
||||
// flip_async queues a flip to happen next vsync but returns without blocking.
|
||||
// You should call wait_for_flip before doing any more reads or writes, defining sprites, etc.
|
||||
void flip_async();
|
||||
void wait_for_flip();
|
||||
|
||||
// DMA handlers, should not be called externally
|
||||
void gfx_dma_handler();
|
||||
void text_dma_handler();
|
||||
|
||||
private:
|
||||
RGB888 palette[PALETTE_SIZE];
|
||||
|
||||
uint8_t* frame_buffer_display;
|
||||
uint8_t* frame_buffer_back;
|
||||
uint32_t* font_cache;
|
||||
|
||||
uint16_t* point_to_ptr16(const Point &p) const {
|
||||
return ((uint16_t*)frame_buffer_back) + (p.y * (uint32_t)frame_width) + p.x;
|
||||
}
|
||||
|
||||
uint8_t* point_to_ptr_palette(const Point &p) const {
|
||||
return frame_buffer_back + (p.y * (uint32_t)frame_width) + p.x;
|
||||
}
|
||||
|
||||
uint8_t* point_to_ptr_text(const Point &p, bool immediate) const {
|
||||
const uint32_t offset = (p.y * (uint32_t)frame_width) + p.x;
|
||||
if (immediate) return frame_buffer_display + offset;
|
||||
return frame_buffer_back + offset;
|
||||
}
|
||||
|
||||
void display_setup_clock();
|
||||
|
||||
// DMA scanline filling
|
||||
uint ch_num = 0;
|
||||
int line_num = -1;
|
||||
|
||||
volatile int v_scanline = 2;
|
||||
volatile bool flip_next;
|
||||
|
||||
uint32_t* line_buffers;
|
||||
const struct dvi_timing* timing_mode;
|
||||
uint v_inactive_total;
|
||||
uint v_total_active_lines;
|
||||
|
||||
uint h_repeat_shift;
|
||||
uint v_repeat_shift;
|
||||
int line_bytes_per_pixel;
|
||||
|
||||
uint32_t* display_palette = nullptr;
|
||||
};
|
||||
}
|
||||
265
drivers/dvhstx/dvi.cpp
Normal file
265
drivers/dvhstx/dvi.cpp
Normal file
|
|
@ -0,0 +1,265 @@
|
|||
#include <pico/stdlib.h>
|
||||
|
||||
#include "dvi.hpp"
|
||||
|
||||
// VGA -- we do this mode properly, with a pretty comfortable clk_sys (252 MHz)
|
||||
const struct dvi_timing dvi_timing_640x480p_60hz = {
|
||||
.h_sync_polarity = false,
|
||||
.h_front_porch = 16,
|
||||
.h_sync_width = 96,
|
||||
.h_back_porch = 48,
|
||||
.h_active_pixels = 640,
|
||||
|
||||
.v_sync_polarity = false,
|
||||
.v_front_porch = 10,
|
||||
.v_sync_width = 2,
|
||||
.v_back_porch = 33,
|
||||
.v_active_lines = 480,
|
||||
|
||||
.bit_clk_khz = 252000
|
||||
};
|
||||
|
||||
// SVGA -- completely by-the-book but requires 400 MHz clk_sys
|
||||
const struct dvi_timing dvi_timing_800x600p_60hz = {
|
||||
.h_sync_polarity = false,
|
||||
.h_front_porch = 44,
|
||||
.h_sync_width = 128,
|
||||
.h_back_porch = 88,
|
||||
.h_active_pixels = 800,
|
||||
|
||||
.v_sync_polarity = false,
|
||||
.v_front_porch = 1,
|
||||
.v_sync_width = 4,
|
||||
.v_back_porch = 23,
|
||||
.v_active_lines = 600,
|
||||
|
||||
.bit_clk_khz = 400000
|
||||
};
|
||||
|
||||
// 720x480 - timings from dumping the EDID of my monitor
|
||||
const struct dvi_timing dvi_timing_720x480p_60hz = {
|
||||
.h_sync_polarity = false,
|
||||
.h_front_porch = 16,
|
||||
.h_sync_width = 62,
|
||||
.h_back_porch = 60,
|
||||
.h_active_pixels = 720,
|
||||
|
||||
.v_sync_polarity = false,
|
||||
.v_front_porch = 9,
|
||||
.v_sync_width = 6,
|
||||
.v_back_porch = 30,
|
||||
.v_active_lines = 480,
|
||||
|
||||
.bit_clk_khz = 270000
|
||||
};
|
||||
|
||||
// 720x576@50Hz - CEA timing
|
||||
const struct dvi_timing dvi_timing_720x576p_50hz = {
|
||||
.h_sync_polarity = false,
|
||||
.h_front_porch = 12,
|
||||
.h_sync_width = 64,
|
||||
.h_back_porch = 68,
|
||||
.h_active_pixels = 720,
|
||||
|
||||
.v_sync_polarity = false,
|
||||
.v_front_porch = 5,
|
||||
.v_sync_width = 5,
|
||||
.v_back_porch = 39,
|
||||
.v_active_lines = 576,
|
||||
|
||||
.bit_clk_khz = 270000
|
||||
};
|
||||
|
||||
// 720x400@70Hz - "IBM" timing
|
||||
const struct dvi_timing dvi_timing_720x400p_70hz = {
|
||||
.h_sync_polarity = false,
|
||||
.h_front_porch = 18,
|
||||
.h_sync_width = 108,
|
||||
.h_back_porch = 54,
|
||||
.h_active_pixels = 720,
|
||||
|
||||
.v_sync_polarity = true,
|
||||
.v_front_porch = 13,
|
||||
.v_sync_width = 2,
|
||||
.v_back_porch = 34,
|
||||
.v_active_lines = 400,
|
||||
|
||||
.bit_clk_khz = 283200
|
||||
};
|
||||
|
||||
// 800x480p 60 Hz (note this doesn't seem to be a CEA mode, I just used the
|
||||
// output of `cvt 800 480 60`), 295 MHz bit clock
|
||||
const struct dvi_timing dvi_timing_800x480p_60hz = {
|
||||
.h_sync_polarity = false,
|
||||
.h_front_porch = 24,
|
||||
.h_sync_width = 72,
|
||||
.h_back_porch = 96,
|
||||
.h_active_pixels = 800,
|
||||
|
||||
.v_sync_polarity = true,
|
||||
.v_front_porch = 3,
|
||||
.v_sync_width = 10,
|
||||
.v_back_porch = 7,
|
||||
.v_active_lines = 480,
|
||||
|
||||
.bit_clk_khz = 295200
|
||||
};
|
||||
|
||||
// 800x450p 60 Hz Similarly not a CEA mode, but is 16:9
|
||||
const struct dvi_timing dvi_timing_800x450p_60hz = {
|
||||
.h_sync_polarity = false,
|
||||
.h_front_porch = 24,
|
||||
.h_sync_width = 72,
|
||||
.h_back_porch = 96,
|
||||
.h_active_pixels = 800,
|
||||
|
||||
.v_sync_polarity = true,
|
||||
.v_front_porch = 3,
|
||||
.v_sync_width = 5,
|
||||
.v_back_porch = 10,
|
||||
.v_active_lines = 450,
|
||||
|
||||
.bit_clk_khz = 278400
|
||||
};
|
||||
|
||||
// SVGA reduced blanking (355 MHz bit clock) -- valid CVT mode, less common
|
||||
// than fully-blanked SVGA, but doesn't require such a high system clock
|
||||
const struct dvi_timing dvi_timing_800x600p_reduced_60hz = {
|
||||
.h_sync_polarity = true,
|
||||
.h_front_porch = 48,
|
||||
.h_sync_width = 32,
|
||||
.h_back_porch = 80,
|
||||
.h_active_pixels = 800,
|
||||
|
||||
.v_sync_polarity = false,
|
||||
.v_front_porch = 3,
|
||||
.v_sync_width = 4,
|
||||
.v_back_porch = 11,
|
||||
.v_active_lines = 600,
|
||||
|
||||
.bit_clk_khz = 354000
|
||||
};
|
||||
|
||||
// Also known as qHD, bit uncommon, but it's a nice modest-resolution 16:9
|
||||
// aspect mode. Pixel clock 40.75 MHz for full CVT mode (no reduced blanking)
|
||||
const struct dvi_timing dvi_timing_960x540p_60hz = {
|
||||
.h_sync_polarity = false,
|
||||
.h_front_porch = 32,
|
||||
.h_sync_width = 96,
|
||||
.h_back_porch = 128,
|
||||
.h_active_pixels = 960,
|
||||
|
||||
.v_sync_polarity = true,
|
||||
.v_front_porch = 3,
|
||||
.v_sync_width = 5,
|
||||
.v_back_porch = 14,
|
||||
.v_active_lines = 540,
|
||||
|
||||
.bit_clk_khz = 408000
|
||||
};
|
||||
|
||||
// Also known as qHD, bit uncommon, but it's a nice modest-resolution 16:9
|
||||
// aspect mode. Pixel clock 33.5 MHz for 50Hz CVT mode (no reduced blanking)
|
||||
const struct dvi_timing dvi_timing_960x540p_50hz = {
|
||||
.h_sync_polarity = false,
|
||||
.h_front_porch = 24,
|
||||
.h_sync_width = 96,
|
||||
.h_back_porch = 120,
|
||||
.h_active_pixels = 960,
|
||||
|
||||
.v_sync_polarity = true,
|
||||
.v_front_porch = 3,
|
||||
.v_sync_width = 5,
|
||||
.v_back_porch = 11,
|
||||
.v_active_lines = 540,
|
||||
|
||||
.bit_clk_khz = 336000
|
||||
};
|
||||
|
||||
// 1024x768, CVT-RB
|
||||
const struct dvi_timing dvi_timing_1024x768_rb_60hz = {
|
||||
.h_sync_polarity = true,
|
||||
.h_front_porch = 48,
|
||||
.h_sync_width = 32,
|
||||
.h_back_porch = 80,
|
||||
.h_active_pixels = 1024,
|
||||
|
||||
.v_sync_polarity = false,
|
||||
.v_front_porch = 3,
|
||||
.v_sync_width = 4,
|
||||
.v_back_porch = 15,
|
||||
.v_active_lines = 768,
|
||||
|
||||
.bit_clk_khz = 560000
|
||||
};
|
||||
|
||||
// 720p50, this is a standard HD mode, the CVT-RB variant
|
||||
// should be widely supported
|
||||
const struct dvi_timing dvi_timing_1280x720p_rb_50hz = {
|
||||
.h_sync_polarity = true,
|
||||
.h_front_porch = 48,
|
||||
.h_sync_width = 32,
|
||||
.h_back_porch = 80,
|
||||
.h_active_pixels = 1280,
|
||||
|
||||
.v_sync_polarity = false,
|
||||
.v_front_porch = 3,
|
||||
.v_sync_width = 5,
|
||||
.v_back_porch = 9,
|
||||
.v_active_lines = 720,
|
||||
|
||||
.bit_clk_khz = 528000
|
||||
};
|
||||
|
||||
// 720p60, this is the CVT-RB variant, again should be widely supported
|
||||
const struct dvi_timing dvi_timing_1280x720p_rb_60hz = {
|
||||
.h_sync_polarity = true,
|
||||
.h_front_porch = 48,
|
||||
.h_sync_width = 32,
|
||||
.h_back_porch = 80,
|
||||
.h_active_pixels = 1280,
|
||||
|
||||
.v_sync_polarity = false,
|
||||
.v_front_porch = 3,
|
||||
.v_sync_width = 5,
|
||||
.v_back_porch = 13,
|
||||
.v_active_lines = 720,
|
||||
|
||||
.bit_clk_khz = 640000
|
||||
};
|
||||
|
||||
// 1080p30 - not a normal mode but seems to work on a wide variety of hardware
|
||||
// Strictly speaking RB2 should have a clock speed matching the target frequency more closely
|
||||
// but it seems to work!
|
||||
const struct dvi_timing dvi_timing_1920x1080p_rb2_30hz = {
|
||||
.h_sync_polarity = true,
|
||||
.h_front_porch = 8,
|
||||
.h_sync_width = 32,
|
||||
.h_back_porch = 40,
|
||||
.h_active_pixels = 1920,
|
||||
|
||||
.v_sync_polarity = false,
|
||||
.v_front_porch = 7,
|
||||
.v_sync_width = 8,
|
||||
.v_back_porch = 6,
|
||||
.v_active_lines = 1080,
|
||||
|
||||
.bit_clk_khz = 660000
|
||||
};
|
||||
|
||||
// 1440p24 YOLO - works on my Dell Ultrasharp, that most forgiving of monitors. May require a little more than 1.3V
|
||||
const struct dvi_timing dvi_timing_2560x1440p_yolo_24hz = {
|
||||
.h_sync_polarity = true,
|
||||
.h_front_porch = 8,
|
||||
.h_sync_width = 32,
|
||||
.h_back_porch = 20,
|
||||
.h_active_pixels = 2560,
|
||||
|
||||
.v_sync_polarity = false,
|
||||
.v_front_porch = 2,
|
||||
.v_sync_width = 6,
|
||||
.v_back_porch = 2,
|
||||
.v_active_lines = 1440,
|
||||
|
||||
.bit_clk_khz = 912000
|
||||
};
|
||||
62
drivers/dvhstx/dvi.hpp
Normal file
62
drivers/dvhstx/dvi.hpp
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#pragma once
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// DVI constants
|
||||
|
||||
#define TMDS_CTRL_00 0x354u
|
||||
#define TMDS_CTRL_01 0x0abu
|
||||
#define TMDS_CTRL_10 0x154u
|
||||
#define TMDS_CTRL_11 0x2abu
|
||||
|
||||
#define TMDS_BALANCED_LOW 0x307u
|
||||
#define TMDS_BALANCED_HIGH 0x2f0u
|
||||
|
||||
#define TMDS_BLACK_A 0x100u
|
||||
#define TMDS_BLACK_B 0x1ffu
|
||||
|
||||
#define SYNC_V0_H0 (TMDS_CTRL_00 | (TMDS_CTRL_00 << 10) | (TMDS_CTRL_00 << 20))
|
||||
#define SYNC_V0_H1 (TMDS_CTRL_01 | (TMDS_CTRL_00 << 10) | (TMDS_CTRL_00 << 20))
|
||||
#define SYNC_V1_H0 (TMDS_CTRL_10 | (TMDS_CTRL_00 << 10) | (TMDS_CTRL_00 << 20))
|
||||
#define SYNC_V1_H1 (TMDS_CTRL_11 | (TMDS_CTRL_00 << 10) | (TMDS_CTRL_00 << 20))
|
||||
#define MISSING_PIXEL (TMDS_BALANCED_LOW | (TMDS_BALANCED_LOW << 10) | (TMDS_BALANCED_HIGH << 20))
|
||||
#define BLACK_PIXEL (TMDS_BALANCED_LOW | (TMDS_BALANCED_LOW << 10) | (TMDS_BALANCED_LOW << 20))
|
||||
#define BLACK_PIXEL_A (TMDS_BLACK_A | (TMDS_BLACK_A << 10) | (TMDS_BLACK_A << 20))
|
||||
#define BLACK_PIXEL_B (TMDS_BLACK_B | (TMDS_BLACK_B << 10) | (TMDS_BLACK_B << 20))
|
||||
|
||||
#define HSTX_CMD_RAW (0x0u << 12)
|
||||
#define HSTX_CMD_RAW_REPEAT (0x1u << 12)
|
||||
#define HSTX_CMD_TMDS (0x2u << 12)
|
||||
#define HSTX_CMD_TMDS_REPEAT (0x3u << 12)
|
||||
#define HSTX_CMD_NOP (0xfu << 12)
|
||||
|
||||
struct dvi_timing {
|
||||
bool h_sync_polarity;
|
||||
uint h_front_porch;
|
||||
uint h_sync_width;
|
||||
uint h_back_porch;
|
||||
uint h_active_pixels;
|
||||
|
||||
bool v_sync_polarity;
|
||||
uint v_front_porch;
|
||||
uint v_sync_width;
|
||||
uint v_back_porch;
|
||||
uint v_active_lines;
|
||||
|
||||
uint bit_clk_khz;
|
||||
};
|
||||
|
||||
extern const struct dvi_timing dvi_timing_640x480p_60hz;
|
||||
extern const struct dvi_timing dvi_timing_720x480p_60hz;
|
||||
extern const struct dvi_timing dvi_timing_720x576p_50hz;
|
||||
extern const struct dvi_timing dvi_timing_720x400p_70hz;
|
||||
extern const struct dvi_timing dvi_timing_800x450p_60hz;
|
||||
extern const struct dvi_timing dvi_timing_800x480p_60hz;
|
||||
extern const struct dvi_timing dvi_timing_800x600p_60hz;
|
||||
extern const struct dvi_timing dvi_timing_960x540p_60hz;
|
||||
extern const struct dvi_timing dvi_timing_960x540p_50hz;
|
||||
extern const struct dvi_timing dvi_timing_1024x768_rb_60hz;
|
||||
extern const struct dvi_timing dvi_timing_1280x720p_rb_50hz;
|
||||
extern const struct dvi_timing dvi_timing_1280x720p_rb_60hz;
|
||||
extern const struct dvi_timing dvi_timing_1920x1080p_rb2_30hz;
|
||||
extern const struct dvi_timing dvi_timing_1920x1080p_yolo_50hz;
|
||||
extern const struct dvi_timing dvi_timing_1920x1080p_yolo_60hz;
|
||||
42
drivers/dvhstx/font.h
Normal file
42
drivers/dvhstx/font.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef _FONT_H
|
||||
#define _FONT_H
|
||||
|
||||
#include "pico/types.h"
|
||||
|
||||
typedef struct {
|
||||
uint16_t bitmap_index;
|
||||
uint16_t adv_w;
|
||||
int8_t box_w, box_h, ofs_x, ofs_y;
|
||||
} __attribute__((packed)) lv_font_fmt_txt_glyph_dsc_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t range_start, range_length, glyph_id_start, list_length;
|
||||
void *unicode_list, *glyph_id_ofs_list;
|
||||
enum {
|
||||
LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
|
||||
} type;
|
||||
} lv_font_fmt_txt_cmap_t;
|
||||
|
||||
typedef struct {
|
||||
const uint8_t *glyph_bitmap;
|
||||
const lv_font_fmt_txt_glyph_dsc_t *glyph_dsc;
|
||||
const lv_font_fmt_txt_cmap_t *cmaps;
|
||||
uint8_t cmap_num, bpp, kern_scale, kern_classes;
|
||||
void *kern_dsc;
|
||||
} lv_font_fmt_txt_dsc_t;
|
||||
|
||||
typedef struct {
|
||||
lv_font_fmt_txt_dsc_t *dsc;
|
||||
uint8_t line_height, base_line;
|
||||
} lv_font_t;
|
||||
|
||||
#define FONT_HEIGHT 23
|
||||
extern const lv_font_t intel_one_mono;
|
||||
|
||||
#endif //SOFTWARE_FONT_H
|
||||
895
drivers/dvhstx/intel_one_mono_2bpp.c
Normal file
895
drivers/dvhstx/intel_one_mono_2bpp.c
Normal file
|
|
@ -0,0 +1,895 @@
|
|||
/*******************************************************************************
|
||||
* Size: 22 px
|
||||
* Bpp: 2
|
||||
* Opts: --bpp 2 --size 22 --no-compress --font IntelOneMono-Medium.ttf --range 32-127 --format lvgl -o intel_one_mono.c
|
||||
******************************************************************************/
|
||||
|
||||
// The Intel One Mono font is licensed under the SIL Open Font License, Version 1.1:
|
||||
// https://github.com/intel/intel-one-mono/blob/main/OFL.txt
|
||||
|
||||
// This file is created using https://lvgl.io/tools/fontconverter
|
||||
|
||||
#include "font.h"
|
||||
|
||||
#ifndef INTEL_ONE_MONO
|
||||
#define INTEL_ONE_MONO 1
|
||||
#endif
|
||||
|
||||
#if INTEL_ONE_MONO
|
||||
|
||||
/*-----------------
|
||||
* BITMAPS
|
||||
*----------------*/
|
||||
|
||||
/*Store the image of the glyphs*/
|
||||
static const uint8_t glyph_bitmap[] = {
|
||||
/* U+0020 " " */
|
||||
|
||||
/* U+0021 "!" */
|
||||
0x7f, 0xc7, 0xfc, 0x3f, 0x83, 0xf8, 0x3f, 0x42,
|
||||
0xf4, 0x2f, 0x1, 0xf0, 0x1f, 0x0, 0xe0, 0x0,
|
||||
0x0, 0x0, 0x5, 0x3, 0xf8, 0x7f, 0xc3, 0xf4,
|
||||
|
||||
/* U+0022 "\"" */
|
||||
0xbd, 0xb, 0xd7, 0xd0, 0xbd, 0x7d, 0xb, 0xc7,
|
||||
0xd0, 0x7c, 0x7d, 0x7, 0xc3, 0xc0, 0x7c, 0x3c,
|
||||
0x7, 0xc1, 0x40, 0x14,
|
||||
|
||||
/* U+0023 "#" */
|
||||
0x0, 0x3c, 0x3c, 0x0, 0xe, 0xe, 0x0, 0x3,
|
||||
0x43, 0x80, 0x16, 0xe6, 0xe5, 0x1f, 0xff, 0xff,
|
||||
0x87, 0xf8, 0x2f, 0xe0, 0xd, 0xb, 0x0, 0x3,
|
||||
0x43, 0x80, 0x16, 0xc0, 0xe5, 0xf, 0xfa, 0xbf,
|
||||
0xc3, 0xff, 0xff, 0xf0, 0xf, 0xf, 0x0, 0x3,
|
||||
0x83, 0x80, 0x0, 0xd0, 0xe0, 0x0, 0x74, 0x74,
|
||||
0x0,
|
||||
|
||||
/* U+0024 "$" */
|
||||
0x0, 0x3c, 0x0, 0x0, 0xf0, 0x0, 0x3, 0xc0,
|
||||
0x0, 0xbf, 0xf8, 0xf, 0xff, 0xf4, 0xfe, 0x56,
|
||||
0xc3, 0xd0, 0x0, 0xf, 0x40, 0x0, 0x3f, 0x40,
|
||||
0x0, 0x7f, 0xe4, 0x0, 0x7f, 0xfd, 0x0, 0xb,
|
||||
0xfd, 0x0, 0x1, 0xf8, 0x0, 0x2, 0xf0, 0x0,
|
||||
0xb, 0xde, 0x40, 0x7e, 0xbf, 0xff, 0xf0, 0x6f,
|
||||
0xfd, 0x0, 0x3, 0xc0, 0x0, 0xf, 0x0, 0x0,
|
||||
0x3c, 0x0, 0x0, 0x50, 0x0,
|
||||
|
||||
/* U+0025 "%" */
|
||||
0xb, 0xe0, 0xb, 0xc2, 0xeb, 0xc0, 0xf0, 0x38,
|
||||
0x1c, 0x2d, 0x3, 0x81, 0xd3, 0x80, 0x38, 0x1d,
|
||||
0x70, 0x3, 0xc2, 0xcd, 0x0, 0xf, 0xf4, 0x0,
|
||||
0x0, 0x14, 0x1f, 0xc0, 0x0, 0x57, 0xef, 0x0,
|
||||
0xc, 0xb0, 0x74, 0x2, 0xcf, 0x3, 0x80, 0x74,
|
||||
0xf0, 0x38, 0xf, 0xb, 0x7, 0x42, 0xe0, 0x7e,
|
||||
0xf0, 0x7c, 0x1, 0xfc, 0x0,
|
||||
|
||||
/* U+0026 "&" */
|
||||
0x0, 0xbf, 0xd0, 0x3, 0xff, 0xd0, 0xb, 0xc0,
|
||||
0x0, 0xb, 0x80, 0x0, 0xb, 0xc0, 0x0, 0x3,
|
||||
0xd0, 0x10, 0x2, 0xf0, 0x3c, 0xb, 0xfc, 0x78,
|
||||
0x3f, 0x7d, 0xf0, 0xbc, 0x2f, 0xe0, 0xf4, 0xf,
|
||||
0xd0, 0xf4, 0x7, 0xe0, 0xbc, 0xf, 0xf0, 0x3f,
|
||||
0xfd, 0xbc, 0x1f, 0xf4, 0x3e,
|
||||
|
||||
/* U+0027 "'" */
|
||||
0xfd, 0xfd, 0xfd, 0xbc, 0xbc, 0xbc, 0xbc, 0x14,
|
||||
|
||||
/* U+0028 "(" */
|
||||
0x0, 0x0, 0x0, 0x0, 0x2c, 0x0, 0x1f, 0xd0,
|
||||
0x7, 0xf0, 0x2, 0xf8, 0x0, 0x7e, 0x0, 0xf,
|
||||
0x80, 0x2, 0xf0, 0x0, 0x3e, 0x0, 0x7, 0xc0,
|
||||
0x0, 0xbc, 0x0, 0xb, 0xc0, 0x0, 0xbc, 0x0,
|
||||
0x7, 0xc0, 0x0, 0x3d, 0x0, 0x2, 0xf0, 0x0,
|
||||
0xf, 0x80, 0x0, 0x7d, 0x0, 0x2, 0xf8, 0x0,
|
||||
0xb, 0xe0, 0x0, 0x1f, 0xd0, 0x0, 0x2c, 0x0,
|
||||
0x0, 0x0,
|
||||
|
||||
/* U+0029 ")" */
|
||||
0x0, 0x0, 0x0, 0xb4, 0x0, 0x3, 0xf8, 0x0,
|
||||
0x1, 0xfc, 0x0, 0x0, 0xfc, 0x0, 0x0, 0xfc,
|
||||
0x0, 0x0, 0xf8, 0x0, 0x1, 0xf0, 0x0, 0x3,
|
||||
0xe0, 0x0, 0xb, 0xc0, 0x0, 0x1f, 0x0, 0x0,
|
||||
0x7c, 0x0, 0x1, 0xf0, 0x0, 0xb, 0xc0, 0x0,
|
||||
0x3e, 0x0, 0x1, 0xf0, 0x0, 0xf, 0x80, 0x0,
|
||||
0xfc, 0x0, 0xf, 0xc0, 0x1, 0xfc, 0x0, 0x3f,
|
||||
0x80, 0x0, 0xb4, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
/* U+002A "*" */
|
||||
0x0, 0x7c, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x38,
|
||||
0x0, 0x38, 0x34, 0x78, 0xbf, 0x66, 0xfc, 0x16,
|
||||
0xbe, 0x50, 0x0, 0xbc, 0x0, 0x3, 0xcb, 0x40,
|
||||
0xf, 0x83, 0xe0, 0xf, 0x1, 0xe0, 0x1, 0x0,
|
||||
0x40,
|
||||
|
||||
/* U+002B "+" */
|
||||
0x0, 0x0, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x7c,
|
||||
0x0, 0x0, 0x7c, 0x0, 0x0, 0x7c, 0x0, 0xbf,
|
||||
0xff, 0xfc, 0xbf, 0xff, 0xfc, 0x0, 0x7c, 0x0,
|
||||
0x0, 0x7c, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x7c,
|
||||
0x0, 0x0, 0x7c, 0x0,
|
||||
|
||||
/* U+002C "," */
|
||||
0x3, 0xfc, 0x3, 0xf8, 0x3, 0xf4, 0x7, 0xf0,
|
||||
0xf, 0xd0, 0x2f, 0x40, 0x3d, 0x0,
|
||||
|
||||
/* U+002D "-" */
|
||||
0x15, 0x55, 0x5f, 0xff, 0xf7, 0xff, 0xfc,
|
||||
|
||||
/* U+002E "." */
|
||||
0x0, 0x3, 0xf8, 0x7f, 0xc7, 0xfc, 0x2f, 0x40,
|
||||
|
||||
/* U+002F "/" */
|
||||
0x0, 0x0, 0x6, 0x0, 0x0, 0x3, 0xc0, 0x0,
|
||||
0x2, 0xe0, 0x0, 0x0, 0xf0, 0x0, 0x0, 0xb8,
|
||||
0x0, 0x0, 0x3c, 0x0, 0x0, 0x2e, 0x0, 0x0,
|
||||
0xf, 0x40, 0x0, 0xb, 0xc0, 0x0, 0x3, 0xd0,
|
||||
0x0, 0x2, 0xf0, 0x0, 0x0, 0xf4, 0x0, 0x0,
|
||||
0xbc, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x1f, 0x0,
|
||||
0x0, 0xf, 0x40, 0x0, 0x7, 0xc0, 0x0, 0x3,
|
||||
0xd0, 0x0, 0x1, 0xf0, 0x0, 0x0, 0xf8, 0x0,
|
||||
0x0,
|
||||
|
||||
/* U+0030 "0" */
|
||||
0x1, 0xfe, 0x0, 0xb, 0xff, 0xd0, 0x1f, 0x87,
|
||||
0xf0, 0x3e, 0x0, 0xf4, 0x3c, 0x0, 0xfc, 0x7c,
|
||||
0x3, 0xfc, 0x7c, 0x1f, 0xbc, 0xbc, 0x7c, 0x7c,
|
||||
0xbe, 0xe0, 0x7c, 0x7f, 0x80, 0x7c, 0x3d, 0x0,
|
||||
0xb8, 0x3e, 0x0, 0xf4, 0x2f, 0x87, 0xf0, 0xf,
|
||||
0xff, 0xd0, 0x2, 0xfe, 0x0,
|
||||
|
||||
/* U+0031 "1" */
|
||||
0x0, 0x74, 0x0, 0x7f, 0x40, 0x7f, 0xf4, 0xb,
|
||||
0xef, 0x40, 0xa0, 0xf4, 0x0, 0xf, 0x40, 0x0,
|
||||
0xf4, 0x0, 0xf, 0x40, 0x0, 0xf4, 0x0, 0xf,
|
||||
0x40, 0x0, 0xf4, 0x0, 0xf, 0x40, 0x0, 0xf4,
|
||||
0xb, 0xff, 0xfe, 0xbf, 0xff, 0xe0,
|
||||
|
||||
/* U+0032 "2" */
|
||||
0x1, 0xbf, 0x40, 0xb, 0xff, 0xf0, 0x3f, 0x96,
|
||||
0xf4, 0x7d, 0x0, 0xf8, 0x10, 0x0, 0xf8, 0x0,
|
||||
0x0, 0xf4, 0x0, 0x3, 0xf0, 0x0, 0xb, 0xc0,
|
||||
0x0, 0x2f, 0x40, 0x0, 0xbd, 0x0, 0x2, 0xf4,
|
||||
0x0, 0xb, 0xd0, 0x0, 0x2f, 0x40, 0x0, 0x7f,
|
||||
0xff, 0xfc, 0x7f, 0xff, 0xfc,
|
||||
|
||||
/* U+0033 "3" */
|
||||
0x7f, 0xff, 0xf5, 0xff, 0xff, 0xc0, 0x0, 0x7e,
|
||||
0x0, 0x3, 0xe0, 0x0, 0x3e, 0x0, 0x3, 0xf0,
|
||||
0x0, 0x3f, 0xf8, 0x0, 0xff, 0xfc, 0x0, 0x2,
|
||||
0xf8, 0x0, 0x2, 0xf0, 0x0, 0xb, 0xc0, 0x0,
|
||||
0x7e, 0x5, 0x6f, 0xf4, 0xff, 0xff, 0x43, 0xff,
|
||||
0x90, 0x0,
|
||||
|
||||
/* U+0034 "4" */
|
||||
0x0, 0x1f, 0xc0, 0x0, 0x3f, 0xc0, 0x0, 0xb7,
|
||||
0xc0, 0x1, 0xf3, 0xc0, 0x3, 0xc3, 0xc0, 0xb,
|
||||
0x83, 0xc0, 0xf, 0x3, 0xc0, 0x3c, 0x3, 0xc0,
|
||||
0x78, 0x3, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x0, 0x3, 0xc0, 0x0, 0x3, 0xc0, 0x0,
|
||||
0x3, 0xc0, 0x0, 0x3, 0xc0,
|
||||
|
||||
/* U+0035 "5" */
|
||||
0x1f, 0xff, 0xf0, 0x7f, 0xff, 0xc2, 0xe0, 0x0,
|
||||
0xb, 0x80, 0x0, 0x2e, 0x0, 0x0, 0xba, 0xfe,
|
||||
0x3, 0xff, 0xff, 0xb, 0x90, 0xbe, 0x0, 0x0,
|
||||
0xfc, 0x0, 0x2, 0xf0, 0x0, 0xf, 0x80, 0x1,
|
||||
0xfd, 0x1a, 0xff, 0xe0, 0xff, 0xf9, 0x3, 0xa5,
|
||||
0x0, 0x0,
|
||||
|
||||
/* U+0036 "6" */
|
||||
0x0, 0x1f, 0xc0, 0x0, 0x7f, 0x0, 0x1, 0xfc,
|
||||
0x0, 0x3, 0xf0, 0x0, 0xf, 0xc0, 0x0, 0x1f,
|
||||
0xff, 0x80, 0x3f, 0xff, 0xf0, 0x3d, 0x1, 0xf8,
|
||||
0x7c, 0x0, 0xfc, 0x7c, 0x0, 0xbc, 0x7c, 0x0,
|
||||
0xbc, 0x3e, 0x0, 0xfc, 0x3f, 0x43, 0xf4, 0xf,
|
||||
0xff, 0xe0, 0x2, 0xfe, 0x40,
|
||||
|
||||
/* U+0037 "7" */
|
||||
0xbf, 0xff, 0xfe, 0xff, 0xff, 0xf0, 0x0, 0xf,
|
||||
0x80, 0x0, 0x7c, 0x0, 0x3, 0xe0, 0x0, 0x1f,
|
||||
0x0, 0x0, 0xfc, 0x0, 0x7, 0xd0, 0x0, 0x3f,
|
||||
0x0, 0x1, 0xf4, 0x0, 0xf, 0xc0, 0x0, 0x7d,
|
||||
0x0, 0x3, 0xf0, 0x0, 0x1f, 0x80, 0x0, 0xfc,
|
||||
0x0, 0x0,
|
||||
|
||||
/* U+0038 "8" */
|
||||
0x2, 0xff, 0x40, 0x3f, 0xff, 0x83, 0xf4, 0x2f,
|
||||
0x4f, 0x40, 0x3e, 0x3d, 0x0, 0xf4, 0x7c, 0x7,
|
||||
0xc0, 0x7f, 0xf8, 0x1, 0xff, 0xe0, 0x2f, 0x42,
|
||||
0xf0, 0xf0, 0x2, 0xe7, 0xc0, 0x7, 0xdf, 0x0,
|
||||
0x2f, 0x3f, 0x2, 0xf8, 0x7f, 0xff, 0xc0, 0x2f,
|
||||
0xf4, 0x0,
|
||||
|
||||
/* U+0039 "9" */
|
||||
0x2, 0xff, 0x40, 0xf, 0xff, 0xe0, 0x3f, 0x43,
|
||||
0xf4, 0x3d, 0x0, 0xf8, 0x7c, 0x0, 0xbc, 0x7c,
|
||||
0x0, 0xbc, 0x7d, 0x0, 0xbc, 0x3f, 0x0, 0xf8,
|
||||
0x1f, 0xff, 0xf4, 0x6, 0xff, 0xf0, 0x0, 0x7,
|
||||
0xd0, 0x0, 0x1f, 0x80, 0x0, 0x7e, 0x0, 0x1,
|
||||
0xf8, 0x0, 0xb, 0xe0, 0x0,
|
||||
|
||||
/* U+003A ":" */
|
||||
0x2f, 0x47, 0xfc, 0x7f, 0xc2, 0xf4, 0x0, 0x0,
|
||||
0x0, 0x0, 0x2, 0xf4, 0x7f, 0xc7, 0xfc, 0x2f,
|
||||
0x40,
|
||||
|
||||
/* U+003B ";" */
|
||||
0x1, 0xf8, 0x3, 0xfc, 0x3, 0xfc, 0x1, 0xf8,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x54,
|
||||
0x3, 0xf8, 0x3, 0xf4, 0x7, 0xf0, 0xf, 0xe0,
|
||||
0x1f, 0x80, 0x3e, 0x0, 0x14, 0x0,
|
||||
|
||||
/* U+003C "<" */
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x60, 0x0, 0x2f,
|
||||
0xc0, 0xb, 0xfd, 0x7, 0xff, 0x41, 0xff, 0x80,
|
||||
0xb, 0xd0, 0x0, 0x2f, 0xe0, 0x0, 0x1f, 0xf9,
|
||||
0x0, 0x2, 0xff, 0x40, 0x0, 0xbf, 0xc0, 0x0,
|
||||
0x1f, 0x0, 0x0, 0x4,
|
||||
|
||||
/* U+003D "=" */
|
||||
0x3f, 0xff, 0xf8, 0xff, 0xff, 0xe0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
|
||||
0xe3, 0xff, 0xff, 0x80,
|
||||
|
||||
/* U+003E ">" */
|
||||
0x0, 0x0, 0x0, 0x60, 0x0, 0x0, 0x7f, 0x40,
|
||||
0x0, 0x2f, 0xf4, 0x0, 0x2, 0xff, 0x80, 0x0,
|
||||
0x1f, 0xf8, 0x0, 0x0, 0xbc, 0x0, 0x6, 0xfc,
|
||||
0x0, 0x7f, 0xe0, 0xb, 0xfd, 0x0, 0x7f, 0xd0,
|
||||
0x0, 0x78, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
/* U+003F "?" */
|
||||
0xa, 0xff, 0x81, 0xff, 0xff, 0xd7, 0x94, 0x1f,
|
||||
0xc0, 0x0, 0x2f, 0x0, 0x0, 0xfc, 0x0, 0xf,
|
||||
0xd0, 0x7, 0xfd, 0x0, 0x7f, 0x80, 0x1, 0xf0,
|
||||
0x0, 0x7, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0,
|
||||
0x0, 0x0, 0x50, 0x0, 0x1f, 0xd0, 0x0, 0xbf,
|
||||
0x80, 0x0, 0xfc, 0x0,
|
||||
|
||||
/* U+0040 "@" */
|
||||
0x1, 0xbf, 0x80, 0xb, 0x41, 0xb0, 0x1c, 0x0,
|
||||
0x34, 0x34, 0x0, 0x1c, 0x30, 0x0, 0xc, 0x70,
|
||||
0x2f, 0xfc, 0xa0, 0xbe, 0xad, 0xa0, 0xf0, 0xd,
|
||||
0xa1, 0xd0, 0xd, 0xa1, 0xd0, 0xd, 0xa1, 0xe0,
|
||||
0xc, 0xa0, 0xf0, 0x3c, 0x70, 0x7f, 0xf4, 0x70,
|
||||
0xa, 0x40, 0x34, 0x0, 0x0, 0x2c, 0x0, 0x0,
|
||||
0xf, 0x40, 0x0, 0x2, 0xff, 0xe0, 0x0, 0x0,
|
||||
0x0,
|
||||
|
||||
/* U+0041 "A" */
|
||||
0x0, 0x3f, 0x40, 0x0, 0xf, 0xe0, 0x0, 0xb,
|
||||
0xfc, 0x0, 0x3, 0xdf, 0x40, 0x0, 0xf2, 0xe0,
|
||||
0x0, 0x7c, 0x7c, 0x0, 0x2e, 0xf, 0x0, 0xf,
|
||||
0x3, 0xe0, 0x7, 0xc0, 0xbc, 0x2, 0xff, 0xff,
|
||||
0x0, 0xff, 0xff, 0xd0, 0x3c, 0x0, 0xf8, 0x1f,
|
||||
0x0, 0x2f, 0xf, 0x80, 0x7, 0xd3, 0xd0, 0x0,
|
||||
0xf8,
|
||||
|
||||
/* U+0042 "B" */
|
||||
0x3f, 0xff, 0x80, 0x3f, 0xff, 0xf0, 0x3d, 0x1,
|
||||
0xf8, 0x3d, 0x0, 0xbc, 0x3d, 0x0, 0xbc, 0x3d,
|
||||
0x0, 0xf4, 0x3d, 0x2, 0xe0, 0x3f, 0xff, 0x40,
|
||||
0x3f, 0xff, 0xe0, 0x3d, 0x1, 0xfc, 0x3d, 0x0,
|
||||
0x3d, 0x3d, 0x0, 0x3d, 0x3d, 0x0, 0xbd, 0x3f,
|
||||
0xff, 0xfc, 0x3f, 0xff, 0xe0,
|
||||
|
||||
/* U+0043 "C" */
|
||||
0x0, 0xbf, 0x90, 0x7, 0xff, 0xf8, 0x1f, 0xd0,
|
||||
0xbc, 0x3f, 0x0, 0x4, 0x7d, 0x0, 0x0, 0xbc,
|
||||
0x0, 0x0, 0xfc, 0x0, 0x0, 0xf8, 0x0, 0x0,
|
||||
0xfc, 0x0, 0x0, 0xbc, 0x0, 0x0, 0x7c, 0x0,
|
||||
0x0, 0x3f, 0x0, 0x4, 0x2f, 0xd1, 0xbd, 0xb,
|
||||
0xff, 0xf8, 0x1, 0xff, 0x80,
|
||||
|
||||
/* U+0044 "D" */
|
||||
0x3f, 0xf8, 0x0, 0x3f, 0xff, 0x80, 0x3d, 0x1b,
|
||||
0xf0, 0x3d, 0x1, 0xf8, 0x3d, 0x0, 0xbc, 0x3d,
|
||||
0x0, 0x7c, 0x3d, 0x0, 0x3d, 0x3d, 0x0, 0x3d,
|
||||
0x3d, 0x0, 0x3d, 0x3d, 0x0, 0x7c, 0x3d, 0x0,
|
||||
0xfc, 0x3d, 0x2, 0xf4, 0x3d, 0x5f, 0xe0, 0x3f,
|
||||
0xff, 0x80, 0x3f, 0xe4, 0x0,
|
||||
|
||||
/* U+0045 "E" */
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0xf,
|
||||
0x80, 0x0, 0xf8, 0x0, 0xf, 0x80, 0x0, 0xf8,
|
||||
0x0, 0xf, 0xff, 0xfc, 0xff, 0xff, 0xcf, 0x80,
|
||||
0x0, 0xf8, 0x0, 0xf, 0x80, 0x0, 0xf8, 0x0,
|
||||
0xf, 0xff, 0xff, 0xff, 0xff, 0xf0,
|
||||
|
||||
/* U+0046 "F" */
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0xf,
|
||||
0x80, 0x0, 0xf8, 0x0, 0xf, 0x80, 0x0, 0xf8,
|
||||
0x0, 0xf, 0xff, 0xfc, 0xff, 0xff, 0xcf, 0x80,
|
||||
0x0, 0xf8, 0x0, 0xf, 0x80, 0x0, 0xf8, 0x0,
|
||||
0xf, 0x80, 0x0, 0xf8, 0x0, 0x0,
|
||||
|
||||
/* U+0047 "G" */
|
||||
0x0, 0x6f, 0xf0, 0x7, 0xff, 0xf0, 0x1f, 0xe4,
|
||||
0x0, 0x3f, 0x0, 0x0, 0x7d, 0x0, 0x0, 0xbc,
|
||||
0x0, 0x0, 0xfc, 0xf, 0xfc, 0xf8, 0xf, 0xfc,
|
||||
0xfc, 0x0, 0x3c, 0xbc, 0x0, 0x3c, 0x7c, 0x0,
|
||||
0x3c, 0x3f, 0x0, 0x3c, 0x2f, 0xd0, 0x7c, 0xb,
|
||||
0xff, 0xfc, 0x1, 0xbf, 0xf8,
|
||||
|
||||
/* U+0048 "H" */
|
||||
0x3d, 0x0, 0xf8, 0xf4, 0x3, 0xe3, 0xd0, 0xf,
|
||||
0x8f, 0x40, 0x3e, 0x3d, 0x0, 0xf8, 0xf4, 0x3,
|
||||
0xe3, 0xd0, 0xf, 0x8f, 0xff, 0xfe, 0x3f, 0xff,
|
||||
0xf8, 0xf4, 0x3, 0xe3, 0xd0, 0xf, 0x8f, 0x40,
|
||||
0x3e, 0x3d, 0x0, 0xf8, 0xf4, 0x3, 0xe3, 0xd0,
|
||||
0xf, 0x80,
|
||||
|
||||
/* U+0049 "I" */
|
||||
0x7f, 0xff, 0xca, 0xff, 0x90, 0x1f, 0x0, 0x7,
|
||||
0xc0, 0x1, 0xf0, 0x0, 0x7c, 0x0, 0x1f, 0x0,
|
||||
0x7, 0xc0, 0x1, 0xf0, 0x0, 0x7c, 0x0, 0x1f,
|
||||
0x0, 0x7, 0xc0, 0x1, 0xf0, 0xa, 0xff, 0x97,
|
||||
0xff, 0xfc,
|
||||
|
||||
/* U+004A "J" */
|
||||
0x0, 0x0, 0x3e, 0x0, 0x0, 0x3e, 0x0, 0x0,
|
||||
0x3e, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x3e, 0x0,
|
||||
0x0, 0x3e, 0x0, 0x0, 0x3e, 0x0, 0x0, 0x3e,
|
||||
0x0, 0x0, 0x3e, 0x0, 0x0, 0x3e, 0xc, 0x0,
|
||||
0x3e, 0x3f, 0x40, 0x3e, 0x1f, 0xe5, 0xfc, 0x3,
|
||||
0xff, 0xf8, 0x0, 0x7f, 0xd0,
|
||||
|
||||
/* U+004B "K" */
|
||||
0x3d, 0x0, 0x7e, 0xf, 0x40, 0x3f, 0x3, 0xd0,
|
||||
0x3f, 0x0, 0xf4, 0x2f, 0x0, 0x3d, 0x1f, 0x40,
|
||||
0xf, 0x5f, 0x80, 0x3, 0xef, 0xc0, 0x0, 0xff,
|
||||
0xd0, 0x0, 0x3e, 0xfc, 0x0, 0xf, 0x4f, 0xc0,
|
||||
0x3, 0xd1, 0xf8, 0x0, 0xf4, 0x2f, 0x40, 0x3d,
|
||||
0x3, 0xf0, 0xf, 0x40, 0x3f, 0x3, 0xd0, 0x7,
|
||||
0xe0,
|
||||
|
||||
/* U+004C "L" */
|
||||
0xf8, 0x0, 0x3, 0xe0, 0x0, 0xf, 0x80, 0x0,
|
||||
0x3e, 0x0, 0x0, 0xf8, 0x0, 0x3, 0xe0, 0x0,
|
||||
0xf, 0x80, 0x0, 0x3e, 0x0, 0x0, 0xf8, 0x0,
|
||||
0x3, 0xe0, 0x0, 0xf, 0x80, 0x0, 0x3e, 0x0,
|
||||
0x0, 0xf8, 0x0, 0x3, 0xff, 0xff, 0xcf, 0xff,
|
||||
0xff, 0x0,
|
||||
|
||||
/* U+004D "M" */
|
||||
0x3e, 0x0, 0xf8, 0x3f, 0x1, 0xf8, 0x3f, 0x42,
|
||||
0xf8, 0x7f, 0x83, 0xfc, 0x7e, 0xc7, 0xbc, 0x7d,
|
||||
0xdf, 0x7c, 0x7c, 0xfd, 0x7c, 0x7c, 0xbc, 0x7c,
|
||||
0x78, 0x7c, 0x7c, 0x78, 0x34, 0x3c, 0xb8, 0x20,
|
||||
0x3c, 0xb8, 0x0, 0x3c, 0xb8, 0x0, 0x3c, 0xb8,
|
||||
0x0, 0x3c, 0xb8, 0x0, 0x3c,
|
||||
|
||||
/* U+004E "N" */
|
||||
0x3f, 0x0, 0xb8, 0xfc, 0x2, 0xe3, 0xf8, 0xb,
|
||||
0x8f, 0xf0, 0x2e, 0x3f, 0xe0, 0xb8, 0xf7, 0xc2,
|
||||
0xe3, 0xcf, 0x8b, 0x8f, 0x1f, 0x2e, 0x3c, 0x3d,
|
||||
0xb8, 0xf0, 0x7e, 0xe3, 0xc0, 0xff, 0x8f, 0x2,
|
||||
0xfe, 0x3c, 0x3, 0xf8, 0xf0, 0xb, 0xe3, 0xc0,
|
||||
0xf, 0x80,
|
||||
|
||||
/* U+004F "O" */
|
||||
0x2, 0xfe, 0x40, 0xf, 0xff, 0xd0, 0x2f, 0x47,
|
||||
0xf0, 0x3d, 0x0, 0xf8, 0x7c, 0x0, 0xbc, 0xbc,
|
||||
0x0, 0x7c, 0xf8, 0x0, 0x3d, 0xf8, 0x0, 0x3d,
|
||||
0xf8, 0x0, 0x3d, 0xbc, 0x0, 0x7c, 0xbc, 0x0,
|
||||
0xbc, 0x3d, 0x0, 0xf8, 0x2f, 0x43, 0xf0, 0xf,
|
||||
0xff, 0xd0, 0x2, 0xfe, 0x40,
|
||||
|
||||
/* U+0050 "P" */
|
||||
0x3f, 0xff, 0x80, 0x3f, 0xff, 0xf4, 0x3d, 0x1,
|
||||
0xfc, 0x3d, 0x0, 0x7d, 0x3d, 0x0, 0x3e, 0x3d,
|
||||
0x0, 0x3e, 0x3d, 0x0, 0x7d, 0x3d, 0x1, 0xfc,
|
||||
0x3f, 0xff, 0xf0, 0x3f, 0xff, 0x80, 0x3d, 0x0,
|
||||
0x0, 0x3d, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x3d,
|
||||
0x0, 0x0, 0x3d, 0x0, 0x0,
|
||||
|
||||
/* U+0051 "Q" */
|
||||
0x2, 0xfe, 0x40, 0x3, 0xff, 0xf4, 0x2, 0xf4,
|
||||
0x7f, 0x0, 0xf4, 0x3, 0xe0, 0x7c, 0x0, 0xbc,
|
||||
0x2f, 0x0, 0x1f, 0xf, 0x80, 0x3, 0xd3, 0xe0,
|
||||
0x0, 0xf4, 0xf8, 0x0, 0x3d, 0x2f, 0x0, 0x1f,
|
||||
0xb, 0xc0, 0x7, 0xc0, 0xf4, 0x3, 0xe0, 0x2f,
|
||||
0x42, 0xf0, 0x3, 0xff, 0xf8, 0x0, 0x2f, 0xef,
|
||||
0x40, 0x0, 0x1, 0xf0, 0x0, 0x0, 0x3f, 0x0,
|
||||
0x0, 0x7, 0xc0, 0x0, 0x0, 0x40,
|
||||
|
||||
/* U+0052 "R" */
|
||||
0x3f, 0xff, 0x80, 0x3f, 0xff, 0xf0, 0x3d, 0x1,
|
||||
0xf8, 0x3d, 0x0, 0xbc, 0x3d, 0x0, 0xbc, 0x3d,
|
||||
0x0, 0xbc, 0x3d, 0x2, 0xf4, 0x3e, 0xbf, 0xd0,
|
||||
0x3f, 0xf9, 0x0, 0x3e, 0xbd, 0x0, 0x3d, 0x1f,
|
||||
0x40, 0x3d, 0xb, 0xd0, 0x3d, 0x3, 0xf0, 0x3d,
|
||||
0x0, 0xfc, 0x3d, 0x0, 0x7e,
|
||||
|
||||
/* U+0053 "S" */
|
||||
0x2, 0xff, 0xe0, 0x3f, 0xff, 0xd2, 0xf4, 0x16,
|
||||
0xf, 0x80, 0x0, 0x3e, 0x0, 0x0, 0xfd, 0x0,
|
||||
0x0, 0xff, 0x90, 0x0, 0xbf, 0xf4, 0x0, 0x1f,
|
||||
0xf4, 0x0, 0x3, 0xf0, 0x0, 0xb, 0xc0, 0x0,
|
||||
0x2f, 0x39, 0x2, 0xf9, 0xff, 0xff, 0xc1, 0xbf,
|
||||
0xf4, 0x0,
|
||||
|
||||
/* U+0054 "T" */
|
||||
0x3f, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xe0, 0x2,
|
||||
0xf0, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x1f, 0x0,
|
||||
0x0, 0x7, 0xc0, 0x0, 0x1, 0xf0, 0x0, 0x0,
|
||||
0x7c, 0x0, 0x0, 0x1f, 0x0, 0x0, 0x7, 0xc0,
|
||||
0x0, 0x1, 0xf0, 0x0, 0x0, 0x7c, 0x0, 0x0,
|
||||
0x1f, 0x0, 0x0, 0x7, 0xc0, 0x0, 0x1, 0xf0,
|
||||
0x0,
|
||||
|
||||
/* U+0055 "U" */
|
||||
0x7c, 0x0, 0xbd, 0xf0, 0x2, 0xf7, 0xc0, 0xb,
|
||||
0xdf, 0x0, 0x2f, 0x7c, 0x0, 0xbd, 0xf0, 0x2,
|
||||
0xf7, 0xc0, 0xb, 0xdf, 0x0, 0x2f, 0x7c, 0x0,
|
||||
0xbd, 0xf0, 0x2, 0xf7, 0xc0, 0xb, 0xcf, 0x80,
|
||||
0x3e, 0x3f, 0x97, 0xf4, 0x3f, 0xff, 0x80, 0x2f,
|
||||
0xf4, 0x0,
|
||||
|
||||
/* U+0056 "V" */
|
||||
0x3d, 0x0, 0xf, 0x8f, 0xc0, 0x3, 0xd1, 0xf0,
|
||||
0x1, 0xf0, 0x3d, 0x0, 0xb8, 0xf, 0x80, 0x3d,
|
||||
0x2, 0xf0, 0x1f, 0x0, 0x7c, 0xb, 0xc0, 0xf,
|
||||
0x43, 0xd0, 0x2, 0xf0, 0xf0, 0x0, 0x7c, 0x7c,
|
||||
0x0, 0xf, 0x6e, 0x0, 0x3, 0xef, 0x40, 0x0,
|
||||
0x7f, 0xc0, 0x0, 0xf, 0xe0, 0x0, 0x3, 0xf4,
|
||||
0x0,
|
||||
|
||||
/* U+0057 "W" */
|
||||
0x3d, 0x0, 0xf, 0x8f, 0x40, 0x3, 0xd3, 0xe0,
|
||||
0x0, 0xf4, 0xb8, 0x20, 0x3c, 0x2e, 0xd, 0xf,
|
||||
0x7, 0xc3, 0x87, 0xc1, 0xf1, 0xf1, 0xf0, 0x3c,
|
||||
0xbc, 0xb8, 0xf, 0x3b, 0x6e, 0x3, 0xdc, 0xeb,
|
||||
0x40, 0xff, 0x2f, 0xd0, 0x2f, 0xc7, 0xf0, 0xb,
|
||||
0xe0, 0xfc, 0x1, 0xf4, 0x3f, 0x0, 0x7c, 0xb,
|
||||
0xc0,
|
||||
|
||||
/* U+0058 "X" */
|
||||
0x2f, 0x0, 0x2f, 0x3, 0xe0, 0xf, 0x40, 0x7c,
|
||||
0xb, 0xc0, 0xf, 0xc7, 0xd0, 0x1, 0xf7, 0xe0,
|
||||
0x0, 0x2f, 0xf0, 0x0, 0x3, 0xf8, 0x0, 0x0,
|
||||
0xfd, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x3e, 0xf4,
|
||||
0x0, 0x2f, 0x2f, 0x0, 0xf, 0x43, 0xe0, 0xb,
|
||||
0xc0, 0x7c, 0x7, 0xd0, 0xf, 0xc3, 0xe0, 0x1,
|
||||
0xf4,
|
||||
|
||||
/* U+0059 "Y" */
|
||||
0x3e, 0x0, 0xf, 0x8b, 0xd0, 0xb, 0xc0, 0xfc,
|
||||
0x3, 0xd0, 0x1f, 0x42, 0xf0, 0x3, 0xf1, 0xf4,
|
||||
0x0, 0x7d, 0xf8, 0x0, 0xb, 0xfc, 0x0, 0x0,
|
||||
0xfe, 0x0, 0x0, 0x2f, 0x0, 0x0, 0x7, 0xc0,
|
||||
0x0, 0x1, 0xf0, 0x0, 0x0, 0x7c, 0x0, 0x0,
|
||||
0x1f, 0x0, 0x0, 0x7, 0xc0, 0x0, 0x1, 0xf0,
|
||||
0x0,
|
||||
|
||||
/* U+005A "Z" */
|
||||
0x7f, 0xff, 0xfc, 0x7f, 0xff, 0xfc, 0x15, 0x56,
|
||||
0xf4, 0x0, 0x3, 0xe0, 0x0, 0xf, 0xc0, 0x0,
|
||||
0x2f, 0x40, 0x0, 0x3e, 0x0, 0x0, 0xfc, 0x0,
|
||||
0x2, 0xf4, 0x0, 0x3, 0xe0, 0x0, 0xf, 0xc0,
|
||||
0x0, 0x1f, 0x40, 0x0, 0x3f, 0x0, 0x0, 0xbf,
|
||||
0xff, 0xfc, 0xbf, 0xff, 0xfc,
|
||||
|
||||
/* U+005B "[" */
|
||||
0x0, 0x0, 0xf, 0xff, 0xe3, 0xff, 0xf8, 0xf4,
|
||||
0x0, 0x3d, 0x0, 0xf, 0x40, 0x3, 0xd0, 0x0,
|
||||
0xf4, 0x0, 0x3d, 0x0, 0xf, 0x40, 0x3, 0xd0,
|
||||
0x0, 0xf4, 0x0, 0x3d, 0x0, 0xf, 0x40, 0x3,
|
||||
0xd0, 0x0, 0xf4, 0x0, 0x3d, 0x0, 0xf, 0x40,
|
||||
0x3, 0xd0, 0x0, 0xf4, 0x0, 0x3f, 0xff, 0x8f,
|
||||
0xff, 0xe0,
|
||||
|
||||
/* U+005C "\\" */
|
||||
0x18, 0x0, 0x0, 0xb, 0xc0, 0x0, 0x0, 0xf0,
|
||||
0x0, 0x0, 0x2e, 0x0, 0x0, 0x3, 0xc0, 0x0,
|
||||
0x0, 0xb8, 0x0, 0x0, 0xf, 0x0, 0x0, 0x3,
|
||||
0xe0, 0x0, 0x0, 0x7c, 0x0, 0x0, 0xf, 0x80,
|
||||
0x0, 0x1, 0xf0, 0x0, 0x0, 0x3e, 0x0, 0x0,
|
||||
0x7, 0xc0, 0x0, 0x0, 0xf4, 0x0, 0x0, 0x1f,
|
||||
0x0, 0x0, 0x3, 0xd0, 0x0, 0x0, 0x7c, 0x0,
|
||||
0x0, 0xf, 0x40, 0x0, 0x2, 0xf0, 0x0, 0x0,
|
||||
0x3d,
|
||||
|
||||
/* U+005D "]" */
|
||||
0x0, 0x0, 0xf, 0xff, 0xe3, 0xff, 0xf8, 0x0,
|
||||
0x3e, 0x0, 0xf, 0x80, 0x3, 0xe0, 0x0, 0xf8,
|
||||
0x0, 0x3e, 0x0, 0xf, 0x80, 0x3, 0xe0, 0x0,
|
||||
0xf8, 0x0, 0x3e, 0x0, 0xf, 0x80, 0x3, 0xe0,
|
||||
0x0, 0xf8, 0x0, 0x3e, 0x0, 0xf, 0x80, 0x3,
|
||||
0xe0, 0x0, 0xf8, 0x0, 0x3e, 0x3f, 0xff, 0x8f,
|
||||
0xff, 0xe0,
|
||||
|
||||
/* U+005E "^" */
|
||||
0x0, 0x1a, 0x0, 0x0, 0xf, 0xe0, 0x0, 0xf,
|
||||
0xbd, 0x0, 0x7, 0xcb, 0xc0, 0x3, 0xe0, 0xf4,
|
||||
0x1, 0xf0, 0x2f, 0x0, 0xf8, 0x3, 0xd0, 0x7c,
|
||||
0x0, 0xbc, 0x3e, 0x0, 0xf, 0x40,
|
||||
|
||||
/* U+005F "_" */
|
||||
0x15, 0x55, 0x55, 0xff, 0xff, 0xf7, 0xff, 0xff,
|
||||
0xc0,
|
||||
|
||||
/* U+0060 "`" */
|
||||
0x1a, 0x40, 0x1f, 0xc0, 0xf, 0xd0, 0x3, 0xf0,
|
||||
0x2, 0xf4, 0x0, 0xf8, 0x0, 0x7c, 0x0, 0x3e,
|
||||
|
||||
/* U+0061 "a" */
|
||||
0x1f, 0xff, 0x40, 0x2f, 0xff, 0xe0, 0x4, 0x2,
|
||||
0xf0, 0x0, 0x1, 0xf0, 0x1, 0x6b, 0xf0, 0x2f,
|
||||
0xff, 0xf0, 0x7e, 0x41, 0xf0, 0xb8, 0x1, 0xf0,
|
||||
0xbc, 0xb, 0xf0, 0x7f, 0xff, 0xfe, 0x1f, 0xe4,
|
||||
0xbe,
|
||||
|
||||
/* U+0062 "b" */
|
||||
0x3d, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x3d, 0x0,
|
||||
0x0, 0x3d, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x3d,
|
||||
0x7f, 0x80, 0x3f, 0xff, 0xf0, 0x3f, 0x82, 0xf8,
|
||||
0x3d, 0x0, 0xbc, 0x3d, 0x0, 0x7d, 0x3d, 0x0,
|
||||
0x3d, 0x3d, 0x0, 0x7c, 0x3d, 0x0, 0xfc, 0x3e,
|
||||
0x47, 0xf4, 0x3f, 0xff, 0xe0, 0x36, 0xfe, 0x40,
|
||||
|
||||
/* U+0063 "c" */
|
||||
0x1, 0xff, 0x80, 0xb, 0xff, 0xf8, 0x2f, 0x91,
|
||||
0xb8, 0x3e, 0x0, 0x0, 0xbc, 0x0, 0x0, 0xbc,
|
||||
0x0, 0x0, 0xbc, 0x0, 0x0, 0x7e, 0x0, 0x0,
|
||||
0x3f, 0x81, 0xb8, 0xf, 0xff, 0xf8, 0x2, 0xff,
|
||||
0x80,
|
||||
|
||||
/* U+0064 "d" */
|
||||
0x0, 0x0, 0xf8, 0x0, 0x3, 0xe0, 0x0, 0xf,
|
||||
0x80, 0x0, 0x3e, 0x0, 0x0, 0xf8, 0xb, 0xf7,
|
||||
0xe1, 0xff, 0xff, 0x8f, 0xd0, 0xbe, 0x7d, 0x0,
|
||||
0xfb, 0xf0, 0x3, 0xef, 0x80, 0xf, 0xbf, 0x0,
|
||||
0x3e, 0xbc, 0x0, 0xf8, 0xfd, 0x1f, 0xe2, 0xff,
|
||||
0xff, 0x81, 0xfe, 0x2e,
|
||||
|
||||
/* U+0065 "e" */
|
||||
0x1, 0xff, 0x40, 0xf, 0xff, 0xf0, 0x2f, 0x41,
|
||||
0xf8, 0x3c, 0x0, 0xbc, 0x7f, 0xff, 0xfc, 0xbf,
|
||||
0xff, 0xfc, 0x7c, 0x0, 0x0, 0x7d, 0x0, 0x0,
|
||||
0x3f, 0x40, 0x0, 0x1f, 0xff, 0xc0, 0x2, 0xff,
|
||||
0xc0,
|
||||
|
||||
/* U+0066 "f" */
|
||||
0x0, 0x1b, 0xfc, 0x0, 0x7f, 0xfc, 0x0, 0xfd,
|
||||
0x0, 0x0, 0xf4, 0x0, 0x0, 0xf4, 0x0, 0x7f,
|
||||
0xff, 0xf4, 0x7f, 0xff, 0xf4, 0x0, 0xf4, 0x0,
|
||||
0x0, 0xf4, 0x0, 0x0, 0xf4, 0x0, 0x0, 0xf4,
|
||||
0x0, 0x0, 0xf4, 0x0, 0x0, 0xf4, 0x0, 0x0,
|
||||
0xf4, 0x0, 0x0, 0xf4, 0x0, 0x0, 0xf4, 0x0,
|
||||
|
||||
/* U+0067 "g" */
|
||||
0x2, 0xff, 0x68, 0x3f, 0xff, 0xe3, 0xf9, 0x1f,
|
||||
0x9f, 0x40, 0x3e, 0xbc, 0x0, 0xfb, 0xe0, 0x3,
|
||||
0xef, 0xc0, 0xf, 0xaf, 0x0, 0x3e, 0x3f, 0x47,
|
||||
0xf8, 0xbf, 0xff, 0xe0, 0x7f, 0x8f, 0x80, 0x0,
|
||||
0x3e, 0x0, 0x0, 0xf8, 0x0, 0x1f, 0xd0, 0xff,
|
||||
0xfe, 0x3, 0xff, 0xd0,
|
||||
|
||||
/* U+0068 "h" */
|
||||
0x3d, 0x0, 0x0, 0xf4, 0x0, 0x3, 0xd0, 0x0,
|
||||
0xf, 0x40, 0x0, 0x3d, 0x0, 0x0, 0xf4, 0x7f,
|
||||
0x43, 0xdb, 0xff, 0xf, 0xfd, 0xbe, 0x3f, 0x40,
|
||||
0xf8, 0xf8, 0x3, 0xe3, 0xd0, 0xf, 0x8f, 0x40,
|
||||
0x3e, 0x3d, 0x0, 0xf8, 0xf4, 0x3, 0xe3, 0xd0,
|
||||
0xf, 0x8f, 0x40, 0x3e,
|
||||
|
||||
/* U+0069 "i" */
|
||||
0x0, 0x50, 0x0, 0x3f, 0x80, 0x3, 0xfc, 0x0,
|
||||
0x1f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
|
||||
0xf4, 0x7, 0xff, 0x40, 0x1, 0xf4, 0x0, 0xf,
|
||||
0x40, 0x0, 0xf4, 0x0, 0xf, 0x40, 0x0, 0xf4,
|
||||
0x0, 0xf, 0x40, 0x1, 0xf4, 0xb, 0xff, 0xff,
|
||||
0xbf, 0xff, 0xf0,
|
||||
|
||||
/* U+006A "j" */
|
||||
0x0, 0x14, 0x0, 0x1f, 0xc0, 0xb, 0xf0, 0x0,
|
||||
0xa4, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xe2,
|
||||
0xff, 0xf8, 0x0, 0x3e, 0x0, 0xf, 0x80, 0x3,
|
||||
0xe0, 0x0, 0xf8, 0x0, 0x3e, 0x0, 0xf, 0x80,
|
||||
0x3, 0xe0, 0x0, 0xf8, 0x0, 0x3e, 0x0, 0xf,
|
||||
0x80, 0x3, 0xe0, 0x2, 0xf4, 0xff, 0xfc, 0x2f,
|
||||
0xf8, 0x0,
|
||||
|
||||
/* U+006B "k" */
|
||||
0xf8, 0x0, 0x3, 0xe0, 0x0, 0xf, 0x80, 0x0,
|
||||
0x3e, 0x0, 0x0, 0xf8, 0x0, 0x3, 0xe0, 0xf,
|
||||
0xcf, 0x80, 0xfc, 0x3e, 0xf, 0xc0, 0xf8, 0xfc,
|
||||
0x3, 0xef, 0xc0, 0xf, 0xfd, 0x0, 0x3e, 0xbd,
|
||||
0x0, 0xf8, 0xfd, 0x3, 0xe0, 0xfc, 0xf, 0x80,
|
||||
0xfc, 0x3e, 0x0, 0xfc,
|
||||
|
||||
/* U+006C "l" */
|
||||
0xbf, 0xf8, 0x2, 0xff, 0xe0, 0x0, 0xf, 0x80,
|
||||
0x0, 0x3e, 0x0, 0x0, 0xf8, 0x0, 0x3, 0xe0,
|
||||
0x0, 0xf, 0x80, 0x0, 0x3e, 0x0, 0x0, 0xf8,
|
||||
0x0, 0x3, 0xe0, 0x0, 0xf, 0x80, 0x0, 0x3e,
|
||||
0x0, 0x0, 0xf8, 0x0, 0x3, 0xf4, 0x0, 0x7,
|
||||
0xff, 0xc0, 0xb, 0xfe,
|
||||
|
||||
/* U+006D "m" */
|
||||
0xf0, 0xf4, 0x7c, 0xf3, 0xf8, 0xfd, 0xfb, 0xff,
|
||||
0xfe, 0xfc, 0x7e, 0x2e, 0xf0, 0x3c, 0x2e, 0xf0,
|
||||
0x3c, 0x2e, 0xf0, 0x3c, 0x2e, 0xf0, 0x3c, 0x2e,
|
||||
0xf0, 0x3c, 0x2e, 0xf0, 0x3c, 0x2e, 0xf0, 0x3c,
|
||||
0x2e,
|
||||
|
||||
/* U+006E "n" */
|
||||
0x3c, 0x1f, 0xd0, 0xf7, 0xff, 0xc3, 0xfe, 0x5f,
|
||||
0x8f, 0xd0, 0x3e, 0x3d, 0x0, 0xf8, 0xf4, 0x3,
|
||||
0xe3, 0xd0, 0xf, 0x8f, 0x40, 0x3e, 0x3d, 0x0,
|
||||
0xf8, 0xf4, 0x3, 0xe3, 0xd0, 0xf, 0x80,
|
||||
|
||||
/* U+006F "o" */
|
||||
0x2, 0xfe, 0x40, 0xf, 0xff, 0xe0, 0x3f, 0x46,
|
||||
0xf4, 0x7d, 0x0, 0xfc, 0xbc, 0x0, 0x7c, 0xbc,
|
||||
0x0, 0x7d, 0xbc, 0x0, 0x7c, 0x7d, 0x0, 0xfc,
|
||||
0x3f, 0x42, 0xf4, 0xf, 0xff, 0xe0, 0x2, 0xfe,
|
||||
0x40,
|
||||
|
||||
/* U+0070 "p" */
|
||||
0x3c, 0x7f, 0x80, 0x3e, 0xff, 0xf0, 0x3f, 0x41,
|
||||
0xf8, 0x3d, 0x0, 0xbc, 0x3d, 0x0, 0x7d, 0x3d,
|
||||
0x0, 0x3d, 0x3d, 0x0, 0x7c, 0x3d, 0x0, 0xfc,
|
||||
0x3f, 0x42, 0xf8, 0x3f, 0xff, 0xf0, 0x3d, 0xbf,
|
||||
0x40, 0x3d, 0x0, 0x0, 0x3d, 0x0, 0x0, 0x3d,
|
||||
0x0, 0x0, 0x3d, 0x0, 0x0, 0x3d, 0x0, 0x0,
|
||||
|
||||
/* U+0071 "q" */
|
||||
0x2, 0xff, 0x68, 0x3f, 0xff, 0xe3, 0xf8, 0x1f,
|
||||
0x9f, 0x40, 0x3e, 0xbc, 0x0, 0xfb, 0xe0, 0x3,
|
||||
0xef, 0xc0, 0xf, 0xaf, 0x0, 0x3e, 0x3f, 0x47,
|
||||
0xf8, 0xbf, 0xff, 0xe0, 0x7f, 0x8f, 0x80, 0x0,
|
||||
0x3e, 0x0, 0x0, 0xf8, 0x0, 0x3, 0xe0, 0x0,
|
||||
0xf, 0x80, 0x0, 0x3e,
|
||||
|
||||
/* U+0072 "r" */
|
||||
0x0, 0x0, 0x0, 0x7f, 0xc1, 0xfd, 0x7f, 0xcb,
|
||||
0xfd, 0x7, 0xdf, 0xe8, 0x7, 0xfc, 0x0, 0x7,
|
||||
0xf0, 0x0, 0x7, 0xd0, 0x0, 0x7, 0xc0, 0x0,
|
||||
0x7, 0xc0, 0x0, 0x7, 0xc0, 0x0, 0xff, 0xff,
|
||||
0x0, 0xff, 0xff, 0x0,
|
||||
|
||||
/* U+0073 "s" */
|
||||
0x2, 0xff, 0xe0, 0x7f, 0xff, 0xc3, 0xf0, 0x1,
|
||||
0xf, 0xc0, 0x0, 0x2f, 0xf9, 0x0, 0x1f, 0xff,
|
||||
0x80, 0x1, 0xbf, 0x40, 0x0, 0x3e, 0x14, 0x1,
|
||||
0xf8, 0xff, 0xff, 0xc2, 0xff, 0xf4, 0x0,
|
||||
|
||||
/* U+0074 "t" */
|
||||
0x1, 0xf0, 0x0, 0x7, 0xc0, 0x0, 0x1f, 0x0,
|
||||
0x0, 0x7c, 0x0, 0xff, 0xff, 0xf7, 0xff, 0xff,
|
||||
0xd0, 0x1f, 0x0, 0x0, 0x7c, 0x0, 0x1, 0xf0,
|
||||
0x0, 0x7, 0xc0, 0x0, 0x1f, 0x0, 0x0, 0x7c,
|
||||
0x0, 0x1, 0xf8, 0x0, 0x3, 0xff, 0xf0, 0x2,
|
||||
0xff, 0xc0,
|
||||
|
||||
/* U+0075 "u" */
|
||||
0x3d, 0x0, 0xf8, 0xf4, 0x3, 0xe3, 0xd0, 0xf,
|
||||
0x8f, 0x40, 0x3e, 0x3d, 0x0, 0xf8, 0xf4, 0x3,
|
||||
0xe3, 0xd0, 0xf, 0x8f, 0x40, 0xbe, 0x3f, 0x1f,
|
||||
0xf8, 0xbf, 0xf6, 0xe0, 0xbe, 0xb, 0x80,
|
||||
|
||||
/* U+0076 "v" */
|
||||
0xfc, 0x0, 0x7d, 0x7d, 0x0, 0xbc, 0x3e, 0x0,
|
||||
0xf8, 0x2f, 0x1, 0xf0, 0xf, 0x42, 0xf0, 0xf,
|
||||
0x83, 0xd0, 0x7, 0xc7, 0xc0, 0x3, 0xdf, 0x80,
|
||||
0x2, 0xff, 0x0, 0x1, 0xff, 0x0, 0x0, 0xfd,
|
||||
0x0,
|
||||
|
||||
/* U+0077 "w" */
|
||||
0x3c, 0x0, 0xb, 0x8f, 0x41, 0x3, 0xd2, 0xe0,
|
||||
0xd0, 0xf4, 0xb8, 0x38, 0x3c, 0x1f, 0x1f, 0x1f,
|
||||
0x3, 0xcf, 0xdb, 0x80, 0xf7, 0xba, 0xe0, 0x3e,
|
||||
0xcf, 0xf4, 0xb, 0xf1, 0xfc, 0x1, 0xf8, 0x3f,
|
||||
0x0, 0x7c, 0xf, 0xc0,
|
||||
|
||||
/* U+0078 "x" */
|
||||
0x7e, 0x0, 0xf8, 0x2f, 0x43, 0xf0, 0xf, 0xc7,
|
||||
0xd0, 0x3, 0xef, 0x80, 0x1, 0xff, 0x0, 0x0,
|
||||
0xfd, 0x0, 0x2, 0xff, 0x0, 0x7, 0xdf, 0xc0,
|
||||
0xf, 0x83, 0xe0, 0x3f, 0x2, 0xf4, 0xbd, 0x0,
|
||||
0xfc,
|
||||
|
||||
/* U+0079 "y" */
|
||||
0x3f, 0x0, 0x1f, 0x47, 0xd0, 0xb, 0xc0, 0xf8,
|
||||
0x3, 0xe0, 0x2f, 0x1, 0xf0, 0x3, 0xd0, 0xbc,
|
||||
0x0, 0xfc, 0x3d, 0x0, 0x1f, 0x1f, 0x0, 0x3,
|
||||
0xef, 0x80, 0x0, 0xbf, 0xc0, 0x0, 0xf, 0xf0,
|
||||
0x0, 0x3, 0xf4, 0x0, 0x0, 0xbc, 0x0, 0x0,
|
||||
0x3e, 0x0, 0x0, 0x2f, 0x0, 0x3, 0xff, 0x80,
|
||||
0x0, 0xff, 0x80, 0x0,
|
||||
|
||||
/* U+007A "z" */
|
||||
0x3f, 0xff, 0xf8, 0xff, 0xff, 0xd0, 0x0, 0x7f,
|
||||
0x0, 0x3, 0xf0, 0x0, 0x3f, 0x0, 0x3, 0xf4,
|
||||
0x0, 0x2f, 0x40, 0x2, 0xf4, 0x0, 0x2f, 0x80,
|
||||
0x0, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xc0,
|
||||
|
||||
/* U+007B "{" */
|
||||
0x0, 0x0, 0x0, 0x0, 0x1a, 0xfc, 0x1, 0xff,
|
||||
0xfd, 0x3, 0xf9, 0x40, 0x3, 0xf0, 0x0, 0x0,
|
||||
0xf8, 0x0, 0x0, 0x7e, 0x0, 0x0, 0x1f, 0x40,
|
||||
0x0, 0x1f, 0x80, 0x1, 0xbf, 0x0, 0x7f, 0xe4,
|
||||
0x0, 0xbd, 0x0, 0x0, 0x7f, 0xe4, 0x0, 0x1,
|
||||
0xff, 0x0, 0x0, 0x1f, 0x80, 0x0, 0x1f, 0x40,
|
||||
0x0, 0x7e, 0x0, 0x0, 0xf8, 0x0, 0x3, 0xf0,
|
||||
0x0, 0x3, 0xf9, 0x40, 0x1, 0xff, 0xfd, 0x0,
|
||||
0x1a, 0xfc, 0x0, 0x0, 0x0,
|
||||
|
||||
/* U+007C "|" */
|
||||
0x15, 0xf7, 0xdf, 0x7d, 0xf7, 0xdf, 0x7d, 0xf7,
|
||||
0xdf, 0x7d, 0xf7, 0xdf, 0x7d, 0xf7, 0xdf,
|
||||
|
||||
/* U+007D "}" */
|
||||
0x0, 0x0, 0x0, 0xbf, 0x90, 0x0, 0xff, 0xff,
|
||||
0x0, 0x5, 0xbf, 0x40, 0x0, 0x1f, 0x40, 0x0,
|
||||
0x7e, 0x0, 0x0, 0xfc, 0x0, 0x3, 0xf0, 0x0,
|
||||
0x3, 0xe0, 0x0, 0x2, 0xfe, 0x40, 0x0, 0x1f,
|
||||
0xf8, 0x0, 0x0, 0xbc, 0x0, 0x1f, 0xf8, 0x2,
|
||||
0xfe, 0x40, 0x3, 0xf0, 0x0, 0x3, 0xf0, 0x0,
|
||||
0x0, 0xfc, 0x0, 0x0, 0x7e, 0x0, 0x0, 0x1f,
|
||||
0x40, 0x1, 0xbf, 0x40, 0xff, 0xff, 0x0, 0xbf,
|
||||
0x94, 0x0, 0x0, 0x0, 0x0,
|
||||
|
||||
/* U+007E "~" */
|
||||
0x0, 0x40, 0x1, 0x1, 0xfc, 0x2, 0xe0, 0xff,
|
||||
0xd0, 0xf0, 0xbc, 0xbe, 0xbc, 0x3d, 0x7, 0xfd,
|
||||
0xf, 0x0, 0x3e, 0x0, 0x0, 0x0, 0x0
|
||||
};
|
||||
|
||||
|
||||
/*---------------------
|
||||
* GLYPH DESCRIPTION
|
||||
*--------------------*/
|
||||
|
||||
static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||
{.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */,
|
||||
{.bitmap_index = 0, .adv_w = 216, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 0, .adv_w = 216, .box_w = 6, .box_h = 16, .ofs_x = 4, .ofs_y = 0},
|
||||
{.bitmap_index = 24, .adv_w = 216, .box_w = 10, .box_h = 8, .ofs_x = 2, .ofs_y = 8},
|
||||
{.bitmap_index = 44, .adv_w = 216, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 93, .adv_w = 216, .box_w = 11, .box_h = 22, .ofs_x = 1, .ofs_y = -4},
|
||||
{.bitmap_index = 154, .adv_w = 216, .box_w = 14, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 207, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 252, .adv_w = 216, .box_w = 4, .box_h = 8, .ofs_x = 5, .ofs_y = 8},
|
||||
{.bitmap_index = 260, .adv_w = 216, .box_w = 10, .box_h = 23, .ofs_x = 2, .ofs_y = -4},
|
||||
{.bitmap_index = 318, .adv_w = 216, .box_w = 11, .box_h = 23, .ofs_x = 1, .ofs_y = -4},
|
||||
{.bitmap_index = 382, .adv_w = 216, .box_w = 12, .box_h = 11, .ofs_x = 1, .ofs_y = 3},
|
||||
{.bitmap_index = 415, .adv_w = 216, .box_w = 12, .box_h = 12, .ofs_x = 1, .ofs_y = 2},
|
||||
{.bitmap_index = 451, .adv_w = 216, .box_w = 8, .box_h = 7, .ofs_x = 2, .ofs_y = -4},
|
||||
{.bitmap_index = 465, .adv_w = 216, .box_w = 9, .box_h = 3, .ofs_x = 2, .ofs_y = 6},
|
||||
{.bitmap_index = 472, .adv_w = 216, .box_w = 6, .box_h = 5, .ofs_x = 4, .ofs_y = 0},
|
||||
{.bitmap_index = 480, .adv_w = 216, .box_w = 13, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 545, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 590, .adv_w = 216, .box_w = 10, .box_h = 15, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 628, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 673, .adv_w = 216, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 715, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 760, .adv_w = 216, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 802, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 847, .adv_w = 216, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 889, .adv_w = 216, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 931, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 976, .adv_w = 216, .box_w = 6, .box_h = 11, .ofs_x = 4, .ofs_y = 0},
|
||||
{.bitmap_index = 993, .adv_w = 216, .box_w = 8, .box_h = 15, .ofs_x = 2, .ofs_y = -4},
|
||||
{.bitmap_index = 1023, .adv_w = 216, .box_w = 11, .box_h = 13, .ofs_x = 1, .ofs_y = 1},
|
||||
{.bitmap_index = 1059, .adv_w = 216, .box_w = 11, .box_h = 7, .ofs_x = 1, .ofs_y = 4},
|
||||
{.bitmap_index = 1079, .adv_w = 216, .box_w = 12, .box_h = 13, .ofs_x = 1, .ofs_y = 1},
|
||||
{.bitmap_index = 1118, .adv_w = 216, .box_w = 11, .box_h = 16, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1162, .adv_w = 216, .box_w = 12, .box_h = 19, .ofs_x = 1, .ofs_y = -3},
|
||||
{.bitmap_index = 1219, .adv_w = 216, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 1268, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1313, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1358, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1403, .adv_w = 216, .box_w = 10, .box_h = 15, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 1441, .adv_w = 216, .box_w = 10, .box_h = 15, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 1479, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1524, .adv_w = 216, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1566, .adv_w = 216, .box_w = 9, .box_h = 15, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 1600, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 1645, .adv_w = 216, .box_w = 13, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1694, .adv_w = 216, .box_w = 11, .box_h = 15, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 1736, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1781, .adv_w = 216, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1823, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1868, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 1913, .adv_w = 216, .box_w = 13, .box_h = 19, .ofs_x = 1, .ofs_y = -4},
|
||||
{.bitmap_index = 1975, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2020, .adv_w = 216, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2062, .adv_w = 216, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 2111, .adv_w = 216, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2153, .adv_w = 216, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 2202, .adv_w = 216, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 2251, .adv_w = 216, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 2300, .adv_w = 216, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 2349, .adv_w = 216, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2394, .adv_w = 216, .box_w = 9, .box_h = 22, .ofs_x = 3, .ofs_y = -3},
|
||||
{.bitmap_index = 2444, .adv_w = 216, .box_w = 13, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2509, .adv_w = 216, .box_w = 9, .box_h = 22, .ofs_x = 1, .ofs_y = -3},
|
||||
{.bitmap_index = 2559, .adv_w = 216, .box_w = 13, .box_h = 9, .ofs_x = 0, .ofs_y = 6},
|
||||
{.bitmap_index = 2589, .adv_w = 216, .box_w = 11, .box_h = 3, .ofs_x = 1, .ofs_y = -3},
|
||||
{.bitmap_index = 2598, .adv_w = 216, .box_w = 8, .box_h = 8, .ofs_x = 2, .ofs_y = 9},
|
||||
{.bitmap_index = 2614, .adv_w = 216, .box_w = 12, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2647, .adv_w = 216, .box_w = 12, .box_h = 16, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2695, .adv_w = 216, .box_w = 12, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2728, .adv_w = 216, .box_w = 11, .box_h = 16, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2772, .adv_w = 216, .box_w = 12, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2805, .adv_w = 216, .box_w = 12, .box_h = 16, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2853, .adv_w = 216, .box_w = 11, .box_h = 16, .ofs_x = 1, .ofs_y = -5},
|
||||
{.bitmap_index = 2897, .adv_w = 216, .box_w = 11, .box_h = 16, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2941, .adv_w = 216, .box_w = 10, .box_h = 17, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 2984, .adv_w = 216, .box_w = 9, .box_h = 22, .ofs_x = 2, .ofs_y = -5},
|
||||
{.bitmap_index = 3034, .adv_w = 216, .box_w = 11, .box_h = 16, .ofs_x = 2, .ofs_y = 0},
|
||||
{.bitmap_index = 3078, .adv_w = 216, .box_w = 11, .box_h = 16, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3122, .adv_w = 216, .box_w = 12, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3155, .adv_w = 216, .box_w = 11, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3186, .adv_w = 216, .box_w = 12, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3219, .adv_w = 216, .box_w = 12, .box_h = 16, .ofs_x = 1, .ofs_y = -5},
|
||||
{.bitmap_index = 3267, .adv_w = 216, .box_w = 11, .box_h = 16, .ofs_x = 1, .ofs_y = -5},
|
||||
{.bitmap_index = 3311, .adv_w = 216, .box_w = 12, .box_h = 12, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3347, .adv_w = 216, .box_w = 11, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3378, .adv_w = 216, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3420, .adv_w = 216, .box_w = 11, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3451, .adv_w = 216, .box_w = 12, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3484, .adv_w = 216, .box_w = 13, .box_h = 11, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 3520, .adv_w = 216, .box_w = 12, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3553, .adv_w = 216, .box_w = 13, .box_h = 16, .ofs_x = 0, .ofs_y = -5},
|
||||
{.bitmap_index = 3605, .adv_w = 216, .box_w = 11, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 3636, .adv_w = 216, .box_w = 12, .box_h = 23, .ofs_x = 1, .ofs_y = -4},
|
||||
{.bitmap_index = 3705, .adv_w = 216, .box_w = 3, .box_h = 20, .ofs_x = 5, .ofs_y = -2},
|
||||
{.bitmap_index = 3720, .adv_w = 216, .box_w = 12, .box_h = 23, .ofs_x = 1, .ofs_y = -4},
|
||||
{.bitmap_index = 3789, .adv_w = 216, .box_w = 13, .box_h = 7, .ofs_x = 0, .ofs_y = 4}
|
||||
};
|
||||
|
||||
/*---------------------
|
||||
* CHARACTER MAPPING
|
||||
*--------------------*/
|
||||
|
||||
|
||||
|
||||
/*Collect the unicode lists and glyph_id offsets*/
|
||||
static const lv_font_fmt_txt_cmap_t cmaps[] =
|
||||
{
|
||||
{
|
||||
.range_start = 32, .range_length = 95, .glyph_id_start = 1,
|
||||
.unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*--------------------
|
||||
* ALL CUSTOM DATA
|
||||
*--------------------*/
|
||||
|
||||
static lv_font_fmt_txt_dsc_t font_dsc = {
|
||||
.glyph_bitmap = glyph_bitmap,
|
||||
.glyph_dsc = glyph_dsc,
|
||||
.cmaps = cmaps,
|
||||
.kern_dsc = NULL,
|
||||
.kern_scale = 0,
|
||||
.cmap_num = 1,
|
||||
.bpp = 2,
|
||||
.kern_classes = 0,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*-----------------
|
||||
* PUBLIC FONT
|
||||
*----------------*/
|
||||
|
||||
/*Initialize a public general font descriptor*/
|
||||
const lv_font_t intel_one_mono = {
|
||||
.dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */
|
||||
//.get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
|
||||
//.get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
|
||||
.line_height = 24, /*The maximum line height required by the font*/
|
||||
.base_line = 5, /*Baseline measured from the bottom of the line*/
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif /*#if INTEL_ONE_MONO*/
|
||||
|
||||
12
examples/dvhstx/CMakeLists.txt
Normal file
12
examples/dvhstx/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
add_executable(
|
||||
mandelbrot
|
||||
mandelbrot.cpp
|
||||
mandelf.c
|
||||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(mandelbrot pico_stdlib pico_multicore pico_dvhstx)
|
||||
pico_enable_stdio_usb(mandelbrot 1)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(mandelbrot)
|
||||
128
examples/dvhstx/mandelbrot.cpp
Normal file
128
examples/dvhstx/mandelbrot.cpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#include <stdio.h>
|
||||
#include "hardware/uart.h"
|
||||
#include "pico/multicore.h"
|
||||
#include "drivers/dvhstx/dvhstx.hpp"
|
||||
#include "libraries/pico_graphics/pico_graphics_dvhstx.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "mandelf.h"
|
||||
}
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
#define FRAME_WIDTH 640
|
||||
#define FRAME_HEIGHT 360
|
||||
|
||||
//#define FRAME_WIDTH 400
|
||||
//#define FRAME_HEIGHT 300
|
||||
|
||||
//#define FRAME_WIDTH 320
|
||||
//#define FRAME_HEIGHT 180
|
||||
|
||||
static DVHSTX display;
|
||||
static PicoGraphics_PenDVHSTX_P8 graphics(FRAME_WIDTH, FRAME_HEIGHT, display);
|
||||
|
||||
static FractalBuffer fractal;
|
||||
|
||||
static void init_palette() {
|
||||
graphics.create_pen(0, 0, 0);
|
||||
for (int i = 0; i < 64; ++i) {
|
||||
graphics.create_pen_hsv(i * (1.f / 63.f), 1.0f, 0.5f + (i & 7) * (0.5f / 7.f));
|
||||
}
|
||||
}
|
||||
|
||||
static void init_mandel() {
|
||||
fractal.rows = FRAME_HEIGHT / 2;
|
||||
fractal.cols = FRAME_WIDTH;
|
||||
fractal.max_iter = 63;
|
||||
fractal.iter_offset = 0;
|
||||
fractal.minx = -2.25f;
|
||||
fractal.maxx = 0.75f;
|
||||
fractal.miny = -1.6f;
|
||||
fractal.maxy = 0.f - (1.6f / FRAME_HEIGHT); // Half a row
|
||||
fractal.use_cycle_check = true;
|
||||
init_fractal(&fractal);
|
||||
}
|
||||
|
||||
#define NUM_ZOOMS 100
|
||||
static uint32_t zoom_count = 0;
|
||||
|
||||
static void zoom_mandel() {
|
||||
if (++zoom_count == NUM_ZOOMS)
|
||||
{
|
||||
init_mandel();
|
||||
zoom_count = 0;
|
||||
sleep_ms(2000);
|
||||
return;
|
||||
}
|
||||
|
||||
float zoomx = -.75f - .7f * ((float)zoom_count / (float)NUM_ZOOMS);
|
||||
float sizex = fractal.maxx - fractal.minx;
|
||||
float sizey = fractal.miny * -2.f;
|
||||
float zoomr = 0.974f * 0.5f;
|
||||
fractal.minx = zoomx - zoomr * sizex;
|
||||
fractal.maxx = zoomx + zoomr * sizex;
|
||||
fractal.miny = -zoomr * sizey;
|
||||
fractal.maxy = 0.f + fractal.miny / FRAME_HEIGHT;
|
||||
init_fractal(&fractal);
|
||||
}
|
||||
|
||||
static void display_row(int y, uint8_t* buf) {
|
||||
display.write_palette_pixel_span({0, y}, FRAME_WIDTH, buf);
|
||||
display.write_palette_pixel_span({0, FRAME_HEIGHT - 1 - y}, FRAME_WIDTH, buf);
|
||||
}
|
||||
|
||||
static uint8_t row_buf_core1[FRAME_WIDTH];
|
||||
void core1_main() {
|
||||
while (true) {
|
||||
int y = multicore_fifo_pop_blocking();
|
||||
generate_one_line(&fractal, row_buf_core1, y);
|
||||
multicore_fifo_push_blocking(y);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t row_buf[FRAME_WIDTH];
|
||||
static void draw_two_rows(int y) {
|
||||
multicore_fifo_push_blocking(y+1);
|
||||
generate_one_line(&fractal, row_buf, y);
|
||||
|
||||
display_row(y, row_buf);
|
||||
|
||||
multicore_fifo_pop_blocking();
|
||||
display_row(y+1, row_buf_core1);
|
||||
}
|
||||
|
||||
void draw_mandel() {
|
||||
//display.wait_for_flip();
|
||||
for (int y = 0; y < FRAME_HEIGHT / 2; y += 2)
|
||||
{
|
||||
draw_two_rows(y);
|
||||
}
|
||||
//display.flip_async();
|
||||
display.flip_now();
|
||||
}
|
||||
|
||||
int main() {
|
||||
stdio_init_all();
|
||||
|
||||
display.init(FRAME_WIDTH, FRAME_HEIGHT, DVHSTX::MODE_PALETTE);
|
||||
|
||||
init_palette();
|
||||
|
||||
graphics.set_pen(0);
|
||||
graphics.clear();
|
||||
display.flip_now();
|
||||
graphics.clear();
|
||||
|
||||
multicore_launch_core1(core1_main);
|
||||
|
||||
init_mandel();
|
||||
draw_mandel();
|
||||
|
||||
while(true) {
|
||||
absolute_time_t start_time = get_absolute_time();
|
||||
zoom_mandel();
|
||||
draw_mandel();
|
||||
printf("Drawing zoom %ld took %.2fms\n", zoom_count, absolute_time_diff_us(start_time, get_absolute_time()) * 0.001f);
|
||||
}
|
||||
}
|
||||
63
examples/dvhstx/mandelf.c
Normal file
63
examples/dvhstx/mandelf.c
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright (C) Michael Bell 2021
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "mandelf.h"
|
||||
|
||||
// Cycle checking parameters
|
||||
#define MAX_CYCLE_LEN 8 // Must be power of 2
|
||||
#define MIN_CYCLE_CHECK_ITER 24 // Must be multiple of max cycle len
|
||||
#define CYCLE_TOLERANCE 4e-3
|
||||
|
||||
#define ESCAPE_SQUARE 4.f
|
||||
|
||||
void init_fractal(FractalBuffer* f)
|
||||
{
|
||||
f->done = false;
|
||||
f->min_iter = f->max_iter - 1;
|
||||
f->incx = (f->maxx - f->minx) / (f->cols - 1);
|
||||
f->incy = (f->maxy - f->miny) / (f->rows - 1);
|
||||
f->count_inside = 0;
|
||||
}
|
||||
|
||||
static inline void generate_one(FractalBuffer* f, float x0, float y0, uint8_t* buffptr)
|
||||
{
|
||||
float x = x0;
|
||||
float y = y0;
|
||||
|
||||
uint16_t k = 1;
|
||||
for (; k < f->max_iter; ++k) {
|
||||
float x_square = x*x;
|
||||
float y_square = y*y;
|
||||
if (x_square + y_square > ESCAPE_SQUARE) break;
|
||||
|
||||
float nextx = x_square - y_square + x0;
|
||||
y = x*y*2.f + y0;
|
||||
x = nextx;
|
||||
}
|
||||
if (k == f->max_iter) {
|
||||
*buffptr = 0;
|
||||
f->count_inside++;
|
||||
} else {
|
||||
if (k > f->iter_offset) k -= f->iter_offset;
|
||||
else k = 1;
|
||||
*buffptr = k;
|
||||
if (f->min_iter > k) f->min_iter = k;
|
||||
}
|
||||
}
|
||||
|
||||
void generate_one_line(FractalBuffer* f, uint8_t* buf, uint16_t ipos)
|
||||
{
|
||||
if (f->done) return;
|
||||
|
||||
float y0 = f->miny + ipos * f->incy;
|
||||
float x0 = f->minx;
|
||||
|
||||
for (int16_t j = 0; j < f->cols; ++j) {
|
||||
generate_one(f, x0, y0, buf++);
|
||||
x0 += f->incx;
|
||||
}
|
||||
}
|
||||
24
examples/dvhstx/mandelf.h
Normal file
24
examples/dvhstx/mandelf.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
// Configuration
|
||||
int16_t rows;
|
||||
int16_t cols;
|
||||
|
||||
uint16_t max_iter;
|
||||
uint16_t iter_offset;
|
||||
float minx, miny, maxx, maxy;
|
||||
bool use_cycle_check;
|
||||
|
||||
// State
|
||||
volatile bool done;
|
||||
volatile uint16_t min_iter;
|
||||
float incx, incy;
|
||||
volatile uint32_t count_inside;
|
||||
} FractalBuffer;
|
||||
|
||||
// Generate a section of the fractal into buff
|
||||
// Result written to buff is 0 for inside Mandelbrot set
|
||||
// Otherwise iteration of escape minus min_iter (clamped to 1)
|
||||
void init_fractal(FractalBuffer* fractal);
|
||||
void generate_one_line(FractalBuffer* f, uint8_t* buf, uint16_t row);
|
||||
88
libraries/pico_graphics/pico_graphics_dvhstx.hpp
Normal file
88
libraries/pico_graphics/pico_graphics_dvhstx.hpp
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
#include "pico_graphics.hpp"
|
||||
#include "dvhstx.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
enum BlendMode {
|
||||
TARGET = 0,
|
||||
FIXED = 1,
|
||||
};
|
||||
|
||||
class PicoGraphicsDVHSTX : public PicoGraphics {
|
||||
public:
|
||||
DVHSTX &driver;
|
||||
BlendMode blend_mode = BlendMode::TARGET;
|
||||
|
||||
void set_blend_mode(BlendMode mode) {
|
||||
blend_mode = mode;
|
||||
}
|
||||
|
||||
virtual void set_depth(uint8_t new_depth) {}
|
||||
virtual void set_bg(uint c) {};
|
||||
|
||||
PicoGraphicsDVHSTX(uint16_t width, uint16_t height, DVHSTX &dv_display)
|
||||
: PicoGraphics(width, height, nullptr),
|
||||
driver(dv_display)
|
||||
{
|
||||
this->pen_type = PEN_DV_RGB555;
|
||||
}
|
||||
};
|
||||
|
||||
class PicoGraphics_PenDVHSTX_RGB565 : public PicoGraphicsDVHSTX {
|
||||
public:
|
||||
RGB565 color;
|
||||
RGB565 background;
|
||||
uint16_t depth = 0;
|
||||
|
||||
PicoGraphics_PenDVHSTX_RGB565(uint16_t width, uint16_t height, DVHSTX &dv_display);
|
||||
void set_pen(uint c) override;
|
||||
void set_bg(uint c) override;
|
||||
void set_depth(uint8_t new_depth) override;
|
||||
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
|
||||
int create_pen(uint8_t r, uint8_t g, uint8_t b) override;
|
||||
int create_pen_hsv(float h, float s, float v) override;
|
||||
void set_pixel(const Point &p) override;
|
||||
void set_pixel_span(const Point &p, uint l) override;
|
||||
void set_pixel_alpha(const Point &p, const uint8_t a) override;
|
||||
|
||||
bool supports_alpha_blend() override {return true;}
|
||||
|
||||
bool render_pico_vector_tile(const Rect &bounds, uint8_t* alpha_data, uint32_t stride, uint8_t alpha_type) override;
|
||||
|
||||
static size_t buffer_size(uint w, uint h) {
|
||||
return w * h * sizeof(RGB565);
|
||||
}
|
||||
};
|
||||
|
||||
class PicoGraphics_PenDVHSTX_P8 : public PicoGraphicsDVHSTX {
|
||||
public:
|
||||
static const uint16_t palette_size = 256;
|
||||
uint8_t color;
|
||||
uint8_t depth = 0;
|
||||
bool used[palette_size];
|
||||
|
||||
std::array<std::array<uint8_t, 16>, 512> candidate_cache;
|
||||
std::array<uint8_t, 16> candidates;
|
||||
bool cache_built = false;
|
||||
|
||||
PicoGraphics_PenDVHSTX_P8(uint16_t width, uint16_t height, DVHSTX &dv_display);
|
||||
void set_pen(uint c) override;
|
||||
void set_pen(uint8_t r, uint8_t g, uint8_t b) override;
|
||||
void set_depth(uint8_t new_depth) override;
|
||||
int update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) override;
|
||||
int create_pen(uint8_t r, uint8_t g, uint8_t b) override;
|
||||
int create_pen_hsv(float h, float s, float v) override;
|
||||
int reset_pen(uint8_t i) override;
|
||||
|
||||
int get_palette_size() override {return 0;};
|
||||
RGB* get_palette() override {return nullptr;};
|
||||
|
||||
void set_pixel(const Point &p) override;
|
||||
void set_pixel_span(const Point &p, uint l) override;
|
||||
void get_dither_candidates(const RGB &col, const RGB *palette, size_t len, std::array<uint8_t, 16> &candidates);
|
||||
void set_pixel_dither(const Point &p, const RGB &c) override;
|
||||
|
||||
static size_t buffer_size(uint w, uint h) {
|
||||
return w * h;
|
||||
}
|
||||
};
|
||||
}
|
||||
112
libraries/pico_graphics/pico_graphics_pen_dvhstx_p8.cpp
Normal file
112
libraries/pico_graphics/pico_graphics_pen_dvhstx_p8.cpp
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#include "pico_graphics_dvhstx.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
inline constexpr uint32_t RGB_to_RGB888(const uint8_t r, const uint8_t g, const uint8_t b) {
|
||||
return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
|
||||
}
|
||||
|
||||
PicoGraphics_PenDVHSTX_P8::PicoGraphics_PenDVHSTX_P8(uint16_t width, uint16_t height, DVHSTX &dv_display)
|
||||
: PicoGraphicsDVHSTX(width, height, dv_display)
|
||||
{
|
||||
this->pen_type = PEN_DV_P5;
|
||||
for(auto i = 0u; i < palette_size; i++) {
|
||||
driver.set_palette_colour(i, RGB_to_RGB888(i, i, i) << 3);
|
||||
used[i] = false;
|
||||
}
|
||||
cache_built = false;
|
||||
}
|
||||
void PicoGraphics_PenDVHSTX_P8::set_pen(uint c) {
|
||||
color = c;
|
||||
}
|
||||
void PicoGraphics_PenDVHSTX_P8::set_depth(uint8_t new_depth) {
|
||||
depth = new_depth > 0 ? 1 : 0;
|
||||
}
|
||||
void PicoGraphics_PenDVHSTX_P8::set_pen(uint8_t r, uint8_t g, uint8_t b) {
|
||||
RGB888 *driver_palette = driver.get_palette();
|
||||
RGB palette[palette_size];
|
||||
for(auto i = 0u; i < palette_size; i++) {
|
||||
palette[i] = RGB((uint)driver_palette[i]);
|
||||
}
|
||||
|
||||
int pen = RGB(r, g, b).closest(palette, palette_size);
|
||||
if(pen != -1) color = pen;
|
||||
}
|
||||
int PicoGraphics_PenDVHSTX_P8::update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) {
|
||||
used[i] = true;
|
||||
cache_built = false;
|
||||
driver.set_palette_colour(i, RGB_to_RGB888(r, g, b));
|
||||
return i;
|
||||
}
|
||||
int PicoGraphics_PenDVHSTX_P8::create_pen(uint8_t r, uint8_t g, uint8_t b) {
|
||||
// Create a colour and place it in the palette if there's space
|
||||
for(auto i = 0u; i < palette_size; i++) {
|
||||
if(!used[i]) {
|
||||
used[i] = true;
|
||||
cache_built = false;
|
||||
driver.set_palette_colour(i, RGB_to_RGB888(r, g, b));
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
int PicoGraphics_PenDVHSTX_P8::create_pen_hsv(float h, float s, float v) {
|
||||
RGB p = RGB::from_hsv(h, s, v);
|
||||
return create_pen(p.r, p.g, p.b);
|
||||
}
|
||||
int PicoGraphics_PenDVHSTX_P8::reset_pen(uint8_t i) {
|
||||
driver.set_palette_colour(i, 0);
|
||||
used[i] = false;
|
||||
cache_built = false;
|
||||
return i;
|
||||
}
|
||||
void PicoGraphics_PenDVHSTX_P8::set_pixel(const Point &p) {
|
||||
driver.write_palette_pixel(p, color);
|
||||
}
|
||||
|
||||
void PicoGraphics_PenDVHSTX_P8::set_pixel_span(const Point &p, uint l) {
|
||||
driver.write_palette_pixel_span(p, l, color);
|
||||
}
|
||||
|
||||
void PicoGraphics_PenDVHSTX_P8::get_dither_candidates(const RGB &col, const RGB *palette, size_t len, std::array<uint8_t, 16> &candidates) {
|
||||
RGB error;
|
||||
for(size_t i = 0; i < candidates.size(); i++) {
|
||||
candidates[i] = (col + error).closest(palette, len);
|
||||
error += (col - palette[candidates[i]]);
|
||||
}
|
||||
|
||||
// sort by a rough approximation of luminance, this ensures that neighbouring
|
||||
// pixels in the dither matrix are at extreme opposites of luminence
|
||||
// giving a more balanced output
|
||||
std::sort(candidates.begin(), candidates.end(), [palette](int a, int b) {
|
||||
return palette[a].luminance() > palette[b].luminance();
|
||||
});
|
||||
}
|
||||
|
||||
void PicoGraphics_PenDVHSTX_P8::set_pixel_dither(const Point &p, const RGB &c) {
|
||||
if(!bounds.contains(p)) return;
|
||||
|
||||
if(!cache_built) {
|
||||
RGB888 *driver_palette = driver.get_palette();
|
||||
RGB palette[palette_size];
|
||||
for(auto i = 0u; i < palette_size; i++) {
|
||||
palette[i] = RGB((uint)driver_palette[i]);
|
||||
}
|
||||
|
||||
for(uint i = 0; i < 512; i++) {
|
||||
RGB cache_col((i & 0x1C0) >> 1, (i & 0x38) << 2, (i & 0x7) << 5);
|
||||
get_dither_candidates(cache_col, palette, palette_size, candidate_cache[i]);
|
||||
}
|
||||
cache_built = true;
|
||||
}
|
||||
|
||||
uint cache_key = ((c.r & 0xE0) << 1) | ((c.g & 0xE0) >> 2) | ((c.b & 0xE0) >> 5);
|
||||
|
||||
// find the pattern coordinate offset
|
||||
uint pattern_index = (p.x & 0b11) | ((p.y & 0b11) << 2);
|
||||
|
||||
// set the pixel
|
||||
color = candidate_cache[cache_key][dither16_pattern[pattern_index]];
|
||||
set_pixel(p);
|
||||
}
|
||||
}
|
||||
72
libraries/pico_graphics/pico_graphics_pen_dvhstx_rgb565.cpp
Normal file
72
libraries/pico_graphics/pico_graphics_pen_dvhstx_rgb565.cpp
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
#include "pico_graphics_dvhstx.hpp"
|
||||
|
||||
#ifndef MICROPY_BUILD_TYPE
|
||||
#define mp_printf(_, ...) printf(__VA_ARGS__);
|
||||
#else
|
||||
extern "C" {
|
||||
#include "py/runtime.h"
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace pimoroni {
|
||||
RGB565 to_rgb565_noswap(const RGB& color) {
|
||||
uint16_t p = ((color.r & 0b11111000) << 8) |
|
||||
((color.g & 0b11111100) << 3) |
|
||||
((color.b & 0b11111000) >> 3);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
PicoGraphics_PenDVHSTX_RGB565::PicoGraphics_PenDVHSTX_RGB565(uint16_t width, uint16_t height, DVHSTX &dv_display)
|
||||
: PicoGraphicsDVHSTX(width, height, dv_display)
|
||||
{
|
||||
this->pen_type = PEN_DV_RGB555;
|
||||
}
|
||||
void PicoGraphics_PenDVHSTX_RGB565::set_pen(uint c) {
|
||||
color = c;
|
||||
}
|
||||
void PicoGraphics_PenDVHSTX_RGB565::set_bg(uint c) {
|
||||
background = c;
|
||||
}
|
||||
void PicoGraphics_PenDVHSTX_RGB565::set_depth(uint8_t new_depth) {
|
||||
depth = new_depth > 0 ? 0x8000 : 0;
|
||||
}
|
||||
void PicoGraphics_PenDVHSTX_RGB565::set_pen(uint8_t r, uint8_t g, uint8_t b) {
|
||||
RGB src_color{r, g, b};
|
||||
color = to_rgb565_noswap(src_color);
|
||||
}
|
||||
int PicoGraphics_PenDVHSTX_RGB565::create_pen(uint8_t r, uint8_t g, uint8_t b) {
|
||||
return to_rgb565_noswap(RGB(r, g, b));
|
||||
}
|
||||
int PicoGraphics_PenDVHSTX_RGB565::create_pen_hsv(float h, float s, float v) {
|
||||
return to_rgb565_noswap(RGB::from_hsv(h, s, v));
|
||||
}
|
||||
void PicoGraphics_PenDVHSTX_RGB565::set_pixel(const Point &p) {
|
||||
driver.write_pixel(p, color);
|
||||
}
|
||||
void PicoGraphics_PenDVHSTX_RGB565::set_pixel_span(const Point &p, uint l) {
|
||||
driver.write_pixel_span(p, l, color);
|
||||
}
|
||||
void PicoGraphics_PenDVHSTX_RGB565::set_pixel_alpha(const Point &p, const uint8_t a) {
|
||||
uint16_t src = background;
|
||||
if (blend_mode == BlendMode::TARGET) {
|
||||
driver.read_pixel_span(p, 1, &src);
|
||||
}
|
||||
|
||||
uint8_t src_r = (src >> 8) & 0b11111000;
|
||||
uint8_t src_g = (src >> 3) & 0b11111100;
|
||||
uint8_t src_b = (src << 3) & 0b11111000;
|
||||
|
||||
uint8_t dst_r = (color >> 8) & 0b11111000;
|
||||
uint8_t dst_g = (color >> 3) & 0b11111100;
|
||||
uint8_t dst_b = (color << 3) & 0b11111000;
|
||||
|
||||
RGB565 blended = to_rgb565_noswap(RGB(src_r, src_g, src_b).blend(RGB(dst_r, dst_g, dst_b), a));
|
||||
|
||||
driver.write_pixel(p, blended);
|
||||
}
|
||||
|
||||
bool PicoGraphics_PenDVHSTX_RGB565::render_pico_vector_tile(const Rect &src_bounds, uint8_t* alpha_data, uint32_t stride, uint8_t alpha_type) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
22
pico_dvhstx.cmake
Normal file
22
pico_dvhstx.cmake
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
add_subdirectory(drivers/dvhstx)
|
||||
|
||||
set(LIB_NAME pico_dvhstx)
|
||||
add_library(${LIB_NAME} INTERFACE)
|
||||
|
||||
target_sources(${LIB_NAME} INTERFACE
|
||||
${PIMORONI_PICO_PATH}/libraries/pico_graphics/pico_graphics.cpp
|
||||
# ${CMAKE_CURRENT_LIST_DIR}/libraries/pico_graphics/pico_graphics_pen_dvhstx_rgb888.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/libraries/pico_graphics/pico_graphics_pen_dvhstx_rgb565.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/libraries/pico_graphics/pico_graphics_pen_dvhstx_p8.cpp
|
||||
${PIMORONI_PICO_PATH}/libraries/pico_graphics/types.cpp
|
||||
)
|
||||
|
||||
target_include_directories(${LIB_NAME} INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/libraries/pico_graphics # for pico_graphics_dv.hpp
|
||||
${PIMORONI_PICO_PATH}/libraries/pico_graphics # for pico_graphics.hpp
|
||||
${PIMORONI_PICO_PATH}/libraries/pngdec
|
||||
)
|
||||
|
||||
target_link_libraries(${LIB_NAME} INTERFACE dvhstx pico_stdlib hardware_i2c hardware_dma)
|
||||
73
pico_sdk_import.cmake
Normal file
73
pico_sdk_import.cmake
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
|
||||
|
||||
# This can be dropped into an external project to help locate this SDK
|
||||
# It should be include()ed prior to project()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
|
||||
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
|
||||
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
|
||||
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
|
||||
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
||||
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of Pico SDK from git if not otherwise locatable")
|
||||
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download Pico SDK")
|
||||
|
||||
if (NOT PICO_SDK_PATH)
|
||||
if (PICO_SDK_FETCH_FROM_GIT)
|
||||
include(FetchContent)
|
||||
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||
endif ()
|
||||
# GIT_SUBMODULES_RECURSE was added in 3.17
|
||||
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG master
|
||||
GIT_SUBMODULES_RECURSE FALSE
|
||||
)
|
||||
else ()
|
||||
FetchContent_Declare(
|
||||
pico_sdk
|
||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||
GIT_TAG master
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (NOT pico_sdk)
|
||||
message("Downloading Raspberry Pi Pico SDK")
|
||||
FetchContent_Populate(pico_sdk)
|
||||
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
|
||||
endif ()
|
||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||
else ()
|
||||
message(FATAL_ERROR
|
||||
"Pico SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
|
||||
)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${PICO_SDK_PATH})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
|
||||
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
|
||||
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
|
||||
endif ()
|
||||
|
||||
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||
|
||||
include(${PICO_SDK_INIT_CMAKE_FILE})
|
||||
56
pimoroni_pico_import.cmake
Normal file
56
pimoroni_pico_import.cmake
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# This file can be dropped into a project to help locate the Pimoroni Pico libraries
|
||||
# It will also set up the required include and module search paths.
|
||||
|
||||
if (DEFINED ENV{PIMORONI_PICO_FETCH_FROM_GIT} AND (NOT PIMORONI_PICO_FETCH_FROM_GIT))
|
||||
set(PIMORONI_PICO_FETCH_FROM_GIT $ENV{PIMORONI_PICO_FETCH_FROM_GIT})
|
||||
message("Using PIMORONI_PICO_FETCH_FROM_GIT from environment ('${PIMORONI_PICO_FETCH_FROM_GIT}')")
|
||||
endif ()
|
||||
|
||||
if (DEFINED ENV{PIMORONI_PICO_FETCH_FROM_GIT_PATH} AND (NOT PIMORONI_PICO_FETCH_FROM_GIT_PATH))
|
||||
set(PIMORONI_PICO_FETCH_FROM_GIT_PATH $ENV{PIMORONI_PICO_FETCH_FROM_GIT_PATH})
|
||||
message("Using PIMORONI_PICO_FETCH_FROM_GIT_PATH from environment ('${PIMORONI_PICO_FETCH_FROM_GIT_PATH}')")
|
||||
endif ()
|
||||
|
||||
if (NOT PIMORONI_PICO_PATH)
|
||||
if (PIMORONI_PICO_FETCH_FROM_GIT)
|
||||
include(FetchContent)
|
||||
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
|
||||
if (PIMORONI_PICO_FETCH_FROM_GIT_PATH)
|
||||
get_filename_component(FETCHCONTENT_BASE_DIR "${PIMORONI_PICO_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||
endif ()
|
||||
FetchContent_Declare(
|
||||
pimoroni_pico
|
||||
GIT_REPOSITORY https://github.com/pimoroni/pimoroni-pico
|
||||
GIT_TAG main
|
||||
)
|
||||
if (NOT pimoroni_pico)
|
||||
message("Downloading PIMORONI_PICO SDK")
|
||||
FetchContent_Populate(pimoroni_pico)
|
||||
set(PIMORONI_PICO_PATH ${pimoroni_pico_SOURCE_DIR})
|
||||
endif ()
|
||||
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
|
||||
elseif(PICO_SDK_PATH AND EXISTS "${PICO_SDK_PATH}/../pimoroni-pico")
|
||||
set(PIMORONI_PICO_PATH ${PICO_SDK_PATH}/../pimoroni-pico)
|
||||
message("Defaulting PIMORONI_PICO_PATH as sibling of PICO_SDK_PATH: ${PIMORONI_PICO_PATH}")
|
||||
elseif(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/../../pimoroni-pico/")
|
||||
set(PIMORONI_PICO_PATH ${CMAKE_CURRENT_BINARY_DIR}/../../pimoroni-pico/)
|
||||
else()
|
||||
message(FATAL_ERROR "Pimoroni Pico location was not specified. Please set PIMORONI_PICO_PATH.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
get_filename_component(PIMORONI_PICO_PATH "${PIMORONI_PICO_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||
if (NOT EXISTS ${PIMORONI_PICO_PATH})
|
||||
message(FATAL_ERROR "Directory '${PIMORONI_PICO_PATH}' not found")
|
||||
endif ()
|
||||
|
||||
if (NOT EXISTS ${PIMORONI_PICO_PATH}/pimoroni_pico_import.cmake)
|
||||
message(FATAL_ERROR "Directory '${PIMORONI_PICO_PATH}' does not appear to contain the Pimoroni Pico libraries")
|
||||
endif ()
|
||||
|
||||
message("PIMORONI_PICO_PATH is ${PIMORONI_PICO_PATH}")
|
||||
|
||||
set(PIMORONI_PICO_PATH ${PIMORONI_PICO_PATH} CACHE PATH "Path to the Pimoroni Pico libraries" FORCE)
|
||||
|
||||
include_directories(${PIMORONI_PICO_PATH})
|
||||
list(APPEND CMAKE_MODULE_PATH ${PIMORONI_PICO_PATH})
|
||||
Loading…
Reference in a new issue