clean gh-pages

This commit is contained in:
Liz 2025-02-24 12:12:20 -05:00
parent cd1a9b39c5
commit e369f16d13
15 changed files with 0 additions and 2945 deletions

1
.gitignore vendored
View file

@ -1 +0,0 @@
build/*

21
LICENSE
View file

@ -1,21 +0,0 @@
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.

View file

@ -1,49 +0,0 @@
# 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).
[![Build Status](https://img.shields.io/github/actions/workflow/status/MichaelBell/dvhstx/micropython.yml?branch=main&label=MicroPython)](https://github.com/MichaelBell/dvhstx/actions/workflows/micropython.yml)
[![GitHub release (latest by date)](https://img.shields.io/github/v/release/MichaelBell/dvhstx)](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.
![Mandelbrot fractal displayed on a monitor](Mandelbrot.jpg)
## Download MicroPython
TODO
* [DV HSTX MicroPython Releases](https://github.com/MichaelBell/dvhstx/releases)
## Documentation
Wire up your DVI breakout as follows:
GPIO 12 - CK-
GPIO 13 - CK+
GPIO 14 - D0-
GPIO 15 - D0+
GPIO 16 - D1-
GPIO 17 - D1+
GPIO 18 - D2-
GPIO 19 - D2+
If using jumper jerky, twist the - and + wires for each signal together to help with signal integrity.
TODO
## C/C++ Resources
* :link: [C++ Boilerplate](https://github.com/MichaelBell/dvhstx-boilerplate/)
## C/C++ Community Projects
TODO

View file

@ -1,25 +0,0 @@
// 16-bit Adafruit_GFX-compatible framebuffer for RP2350 HSTX
#include <Adafruit_dvhstx.h>
// If your board definition has PIN_CKP and related defines, DVHSTX_PINOUT_DEFAULT is available
DVHSTX16 display(DVHSTX_PINOUT_DEFAULT, DVHSTX_RESOLUTION_320x240);
// If you get the message "error: 'DVHSTX_PINOUT_DEFAULTx' was not declared" then you need to give
// the pins numbers explicitly, like the example below. The order is: {CKP, D0P, D1P, D2P}
// DVHSTX16 display({12, 14, 16, 18}, DVHSTX_RESOLUTION_320x240);
void setup() {
Serial.begin(115200);
//while(!Serial);
if (!display.begin()) { // Blink LED if insufficient RAM
pinMode(LED_BUILTIN, OUTPUT);
for (;;) digitalWrite(LED_BUILTIN, (millis() / 500) & 1);
}
Serial.println("display initialized");
}
void loop() {
// Draw random lines
display.drawLine(random(display.width()), random(display.height()), random(display.width()), random(display.height()), random(65536));
sleep_ms(1);
}

View file

@ -1,25 +0,0 @@
// 16-bit Adafruit_GFX-compatible framebuffer for RP2350 HSTX
#include <Adafruit_dvhstx.h>
// If your board definition has PIN_CKP and related defines, DVHSTX_PINOUT_DEFAULT is available
DVHSTX8 display(DVHSTX_PINOUT_DEFAULT, DVHSTX_RESOLUTION_640x360);
// If you get the message "error: 'DVHSTX_PINOUT_DEFAULTx' was not declared" then you need to give
// the pins numbers explicitly, like the example below. The order is: {CKP, D0P, D1P, D2P}
// DVHSTX8 display({12, 14, 16, 18}, DVHSTX_RESOLUTION_640x360);
void setup() {
Serial.begin(115200);
//while(!Serial);
if (!display.begin()) { // Blink LED if insufficient RAM
pinMode(LED_BUILTIN, OUTPUT);
for (;;) digitalWrite(LED_BUILTIN, (millis() / 500) & 1);
}
Serial.println("display initialized");
}
void loop() {
// Draw random lines
display.drawLine(random(display.width()), random(display.height()), random(display.width()), random(display.height()), random(65536));
sleep_ms(1);
}

View file

@ -1,101 +0,0 @@
// Text mode demo
// With apologies to Stanley Kubrick et al
#include <Adafruit_dvhstx.h>
// If your board definition has PIN_CKP and related defines,
// DVHSTX_PINOUT_DEFAULT is available
DVHSTXText3 display(DVHSTX_PINOUT_DEFAULT);
// If you get the message "error: 'DVHSTX_PINOUT_DEFAULTx' was not declared"
// then you need to give the pins numbers explicitly, like the example below.
// The order is: {CKP, D0P, D1P, D2P}.
//
// DVHSTXText3 display({12, 14, 16, 18});
const static TextColor colors[] = {
TextColor::TEXT_BLACK,
TextColor::TEXT_RED, TextColor::TEXT_GREEN, TextColor::TEXT_BLUE,
TextColor::TEXT_YELLOW, TextColor::TEXT_MAGENTA, TextColor::TEXT_CYAN,
TextColor::TEXT_WHITE,
};
const static TextColor background_colors[] = {
TextColor::BG_BLACK,
TextColor::BG_RED, TextColor::BG_GREEN, TextColor::BG_BLUE,
TextColor::BG_YELLOW, TextColor::BG_MAGENTA, TextColor::BG_CYAN,
TextColor::BG_WHITE,
};
const static TextColor intensity[] = {
TextColor::ATTR_NORMAL_INTEN, TextColor::ATTR_LOW_INTEN, TextColor::ATTR_V_LOW_INTEN
};
void setup() {
Serial.begin(115200);
if (!display.begin()) { // Blink LED if insufficient RAM
pinMode(LED_BUILTIN, OUTPUT);
for (;;)
digitalWrite(LED_BUILTIN, (millis() / 500) & 1);
}
display.setColor(TextColor::TEXT_BLACK, TextColor::BG_WHITE);
display.clear();
display.showCursor();
display.print("display initialized (black on white background)\n\n\n\n\n");
display.println("line wrap test. one line should be full of 'w's and the next line should start 'xy'.");
for (int i = 0; i < display.width(); i++)
display.write('w');
display.println("xy");
display.println("\n\nAttribute test\n");
display.print(" ");
for (int d : background_colors) {
display.printf(" %d ri vli ", (int)d >> 3 );
}
display.write('\n');
for (TextColor c : colors) {
display.printf(" %d ", (int)c);
for (TextColor d : background_colors) {
display.setColor(c, d);
display.write('*');
display.write('*');
display.write('*');
display.setColor(c, d, TextColor::ATTR_LOW_INTEN);
display.write('*');
display.write('*');
display.write('*');
display.setColor(c, d, TextColor::ATTR_V_LOW_INTEN);
display.write('*');
display.write('*');
display.write('*');
display.setColor(TextColor::TEXT_BLACK, TextColor::BG_WHITE);
display.write(' ');
}
display.write('\n');
}
display.write('\n');
display.write('\n');
}
const char message[] = "All work and no play makes Jack a dull boy ";
int cx, cy, i;
void loop() {
if (i == 0) {
static_assert(std::size(colors) == std::size(background_colors));
auto fg_idx = random(std::size(colors));
auto bg_idx = random(std::size(colors)) - 1;
auto inten_idx = random(std::size(intensity));
if(bg_idx == fg_idx) bg_idx ++; // never bg == fg
for (int j = random(6); j; j--)
display.write(' ');
display.setColor(colors[fg_idx], background_colors[bg_idx], intensity[inten_idx]);
for (int j = random(6); j; j--)
display.write(' ');
}
int ch = message[i++];
if (ch) {
display.write(ch);
} else
i = 0;
sleep_ms(32 + random(32));
}

View file

@ -1,10 +0,0 @@
name=Adafruit DVI HSTX
version=0.1.0
author=Jeff Epler
maintainer=Adafruit <info@adafruit.com>
sentence=Arduino library for RP2350 DVI output, based on dvhstx
paragraph=Arduino library for RP2350 DVI output, based on dvhstx
category=Display
url=https://github.com/adafruit/Adafruit_dvhstx
architectures=rp2040
depends=Adafruit GFX Library

View file

@ -1,110 +0,0 @@
#include "Adafruit_dvhstx.h"
int16_t dvhstx_width(DVHSTXResolution r) {
switch (r) {
default:
case DVHSTX_RESOLUTION_320x180:
return 320;
case DVHSTX_RESOLUTION_640x360:
return 640;
case DVHSTX_RESOLUTION_480x270:
return 480;
case DVHSTX_RESOLUTION_400x225:
return 400;
case DVHSTX_RESOLUTION_320x240:
return 320;
case DVHSTX_RESOLUTION_360x240:
return 360;
case DVHSTX_RESOLUTION_360x200:
return 360;
case DVHSTX_RESOLUTION_360x288:
return 360;
case DVHSTX_RESOLUTION_400x300:
return 400;
case DVHSTX_RESOLUTION_512x384:
return 512;
case DVHSTX_RESOLUTION_400x240:
return 400;
}
return 0;
}
int16_t dvhstx_height(DVHSTXResolution r) {
switch (r) {
default:
case DVHSTX_RESOLUTION_320x180:
return 180;
case DVHSTX_RESOLUTION_640x360:
return 360;
case DVHSTX_RESOLUTION_480x270:
return 270;
case DVHSTX_RESOLUTION_400x225:
return 225;
case DVHSTX_RESOLUTION_320x240:
return 240;
case DVHSTX_RESOLUTION_360x240:
return 240;
case DVHSTX_RESOLUTION_360x200:
return 200;
case DVHSTX_RESOLUTION_360x288:
return 288;
case DVHSTX_RESOLUTION_400x300:
return 300;
case DVHSTX_RESOLUTION_512x384:
return 384;
case DVHSTX_RESOLUTION_400x240:
return 240;
}
}
void DVHSTX16::swap(bool copy_framebuffer) {
if (!double_buffered) {
return;
}
hstx.flip_blocking();
if (copy_framebuffer) {
memcpy(hstx.get_front_buffer<uint8_t>(), hstx.get_back_buffer<uint8_t>(),
sizeof(uint16_t) * _width * _height);
}
}
void DVHSTX8::swap(bool copy_framebuffer) {
if (!double_buffered) {
return;
}
hstx.flip_blocking();
if (copy_framebuffer) {
memcpy(hstx.get_front_buffer<uint8_t>(), hstx.get_back_buffer<uint8_t>(),
sizeof(uint8_t) * _width * _height);
}
}
void DVHSTXText3::clear() {
std::fill(getBuffer(), getBuffer() + WIDTH*HEIGHT, attr << 8);
}
// Character framebuffer is actually a small GFXcanvas16, so...
size_t DVHSTXText3::write(uint8_t c) {
if (!*this) return 0;
if (c == '\r') { // Carriage return
cursor_x = 0;
} else if ((c == '\n') ||
(c >= 32 &&
cursor_x >= WIDTH)) { // Newline OR right edge and printing
cursor_x = 0;
if (cursor_y >= (HEIGHT - 1)) { // Vert scroll?
memmove(getBuffer(), getBuffer() + WIDTH,
WIDTH * (HEIGHT - 1) * sizeof(uint16_t));
drawFastHLine(0, HEIGHT - 1, WIDTH, ' ' | (attr << 8)); // Clear bottom line
cursor_y = HEIGHT - 1;
} else {
cursor_y++;
}
}
if (c >= 32) {
drawPixel(cursor_x, cursor_y, (attr << 8) | c);
cursor_x++;
}
sync_cursor_with_hstx();
return 1;
}

View file

@ -1,242 +0,0 @@
#pragma once
#include "Adafruit_GFX.h"
#include "drivers/dvhstx/dvhstx.hpp"
enum DVHSTXResolution {
/* well supported, square pixels on a 16:9 display, actual resolution
1280x720@50Hz */
DVHSTX_RESOLUTION_320x180,
DVHSTX_RESOLUTION_640x360,
/* sometimes supported, square pixels on a 16:9 display, actual resolution
960x540@60Hz */
DVHSTX_RESOLUTION_480x270,
/* sometimes supported, square pixels on a 16:9 display, actual resolution
800x450@60Hz */
DVHSTX_RESOLUTION_400x225,
/* well supported, but pixels aren't square on a 16:9 display */
DVHSTX_RESOLUTION_320x240, /* 4:3, actual resolution 640x480@60Hz */
DVHSTX_RESOLUTION_360x240, /* 3:2, actual resolution 720x480@60Hz */
DVHSTX_RESOLUTION_360x200, /* 18:10, actual resolution 720x400@70Hz */
DVHSTX_RESOLUTION_360x288, /* 5:4, actual resolution 720x576@60Hz */
DVHSTX_RESOLUTION_400x300, /* 4:3, actual resolution 800x600@60Hz */
DVHSTX_RESOLUTION_512x384, /* 4:3, actual resolution 1024x768@60Hz */
/* sometimes supported, but pixels aren't square on a 16:9 display */
DVHSTX_RESOLUTION_400x240, /* 5:3, actual resolution 800x480@60Hz */
};
using pimoroni::DVHSTXPinout;
// If the board definition provides pre-defined pins for the HSTX connection,
// use them to define a default pinout object.
// This object can be used as the first argument of the DVHSTX constructor.
// Otherwise you must provide the pin nubmers directly as a list of 4 numbers
// in curly brackets such as {12, 14, 16, 18}. These give the location of the
// positive ("P") pins in the order: Clock, Data 0, Data 1, Data 2; check your
// board's schematic for details.
#if defined(PIN_CKP)
#define DVHSTX_PINOUT_DEFAULT \
{ PIN_CKP, PIN_D0P, PIN_D1P, PIN_D2P }
#endif
int16_t dvhstx_width(DVHSTXResolution r);
int16_t dvhstx_height(DVHSTXResolution r);
class DVHSTX16 : public GFXcanvas16 {
public:
/**************************************************************************/
/*!
@brief Instatiate a DVHSTX 16-bit canvas context for graphics
@param res Display resolution
@param double_buffered Whether to allocate two buffers
*/
/**************************************************************************/
DVHSTX16(DVHSTXPinout pinout, DVHSTXResolution res,
bool double_buffered = false)
: GFXcanvas16(dvhstx_width(res), dvhstx_height(res), false),
pinout(pinout), res{res}, double_buffered{double_buffered} {}
~DVHSTX16() { end(); }
bool begin() {
bool result =
hstx.init(dvhstx_width(res), dvhstx_height(res),
pimoroni::DVHSTX::MODE_RGB565, double_buffered, pinout);
if (!result)
return false;
buffer = hstx.get_back_buffer<uint16_t>();
fillScreen(0);
return true;
}
void end() { hstx.reset(); }
/**********************************************************************/
/*!
@brief If double-buffered, wait for retrace and swap buffers. Otherwise,
do nothing (returns immediately)
@param copy_framebuffer if true, copy the new screen to the new back buffer.
Otherwise, the content is undefined.
*/
/**********************************************************************/
void swap(bool copy_framebuffer = false);
/**********************************************************************/
/*!
@brief Convert 24-bit RGB value to a framebuffer value
@param r The input red value, 0 to 255
@param g The input red value, 0 to 255
@param b The input red value, 0 to 255
@return The corresponding 16-bit pixel value
*/
/**********************************************************************/
uint16_t color565(uint8_t red, uint8_t green, uint8_t blue) {
return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3);
}
private:
DVHSTXPinout pinout;
DVHSTXResolution res;
mutable pimoroni::DVHSTX hstx;
bool double_buffered;
};
class DVHSTX8 : public GFXcanvas8 {
public:
/**************************************************************************/
/*!
@brief Instatiate a DVHSTX 8-bit canvas context for graphics
@param res Display resolution
@param double_buffered Whether to allocate two buffers
*/
/**************************************************************************/
DVHSTX8(DVHSTXPinout pinout, DVHSTXResolution res,
bool double_buffered = false)
: GFXcanvas8(dvhstx_width(res), dvhstx_height(res), false),
pinout(pinout), res{res}, double_buffered{double_buffered} {}
~DVHSTX8() { end(); }
bool begin() {
bool result =
hstx.init(dvhstx_width(res), dvhstx_height(res),
pimoroni::DVHSTX::MODE_PALETTE, double_buffered, pinout);
if (!result)
return false;
for (int i = 0; i < 255; i++) {
uint8_t r = (i >> 6) * 255 / 3;
uint8_t g = ((i >> 2) & 7) * 255 / 7;
uint8_t b = (i & 3) * 255 / 3;
setColor(i, r, g, b);
}
buffer = hstx.get_back_buffer<uint8_t>();
fillScreen(0);
return true;
}
void end() { hstx.reset(); }
void setColor(uint8_t idx, uint8_t red, uint8_t green, uint8_t blue) {
hstx.get_palette()[idx] = (red << 16) | (green << 8) | blue;
}
void setColor(uint8_t idx, uint32_t rgb) { hstx.get_palette()[idx] = rgb; }
/**********************************************************************/
/*!
@brief If double-buffered, wait for retrace and swap buffers. Otherwise,
do nothing (returns immediately)
@param copy_framebuffer if true, copy the new screen to the new back buffer.
Otherwise, the content is undefined.
*/
/**********************************************************************/
void swap(bool copy_framebuffer = false);
private:
DVHSTXPinout pinout;
DVHSTXResolution res;
mutable pimoroni::DVHSTX hstx;
bool double_buffered;
};
using TextColor = pimoroni::DVHSTX::TextColour;
class DVHSTXText3 : public GFXcanvas16 {
public:
struct Cell {
uint16_t value;
Cell(uint8_t c, uint8_t attr = TextColor::TEXT_WHITE)
: value(c | (attr << 8)) {}
};
/**************************************************************************/
/*!
@brief Instatiate a DVHSTX 8-bit canvas context for graphics
@param res Display resolution
@param double_buffered Whether to allocate two buffers
*/
/**************************************************************************/
DVHSTXText3(DVHSTXPinout pinout)
: GFXcanvas16(91, 30, false),
pinout(pinout), res{res}, attr{TextColor::TEXT_WHITE} {}
~DVHSTXText3() { end(); }
operator bool() const { return hstx.get_back_buffer<uint16_t>(); }
bool begin() {
bool result =
hstx.init(91, 30, pimoroni::DVHSTX::MODE_TEXT_RGB111, false, pinout);
if (!result)
return false;
buffer = hstx.get_back_buffer<uint16_t>();
return true;
}
void end() { hstx.reset(); }
void clear();
void setColor(uint8_t a) { attr = a; }
void setColor(TextColor fg, TextColor bg, TextColor inten = TextColor::ATTR_NORMAL_INTEN) { attr = fg | bg | inten; }
void hideCursor() {
cursor_visible = false;
hstx.cursor_off();
}
void showCursor() {
cursor_visible = true;
sync_cursor_with_hstx();
}
void setCursor(int x, int y) {
if (x < 0)
x = 0;
if (x > _width)
x = _width;
if (y < 0)
y = 0;
if (y >= _height)
y = _height - 1;
cursor_x = x;
cursor_y = y;
sync_cursor_with_hstx();
}
size_t write(uint8_t c);
int getCursorX() const { return cursor_x; }
int getCursorY() const { return cursor_y; }
private:
DVHSTXPinout pinout;
DVHSTXResolution res;
mutable pimoroni::DVHSTX hstx;
bool double_buffered;
bool cursor_visible = false;
uint8_t attr;
uint8_t cursor_x = 0, cursor_y = 0;
void sync_cursor_with_hstx() {
if (cursor_visible) {
hstx.set_cursor(cursor_x == _width ? _width - 1 : cursor_x, cursor_y);
}
}
};

View file

@ -1,940 +0,0 @@
#include <string.h>
#include <pico/stdlib.h>
#if F_CPU != 150000000
#error "Adafruit_DVHSTX controls overclocking (setting CPU frequency to 264MHz). However, the Tools > CPU Speed selector *MUST* be set to 150MHz"
#endif
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;
#ifdef MICROPY_BUILD_TYPE
#define FRAME_BUFFER_SIZE (640*360)
__attribute__((section(".uninitialized_data"))) static uint8_t frame_buffer_a[FRAME_BUFFER_SIZE];
__attribute__((section(".uninitialized_data"))) static uint8_t frame_buffer_b[FRAME_BUFFER_SIZE];
#endif
#include "font.h"
// If changing the font, note this code will not handle glyphs wider than 13 pixels
#define FONT (&intel_one_mono)
#ifdef MICROPY_BUILD_TYPE
extern "C" {
void dvhstx_debug(const char *fmt, ...);
}
#elif defined(ARDUINO)
#include <Arduino.h>
// #define dvhstx_debug Serial.printf
#define dvhstx_debug(...) ((void)0)
#else
#include <cstdio>
#define dvhstx_debug printf
#endif
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 const uint32_t vblank_line_vsync_off_src[] = {
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_off[count_of(vblank_line_vsync_off_src)];
static const uint32_t vblank_line_vsync_on_src[] = {
HSTX_CMD_RAW_REPEAT,
SYNC_V0_H1,
HSTX_CMD_RAW_REPEAT,
SYNC_V0_H0,
HSTX_CMD_RAW_REPEAT,
SYNC_V0_H1
};
static uint32_t vblank_line_vsync_on[count_of(vblank_line_vsync_on_src)];
static const uint32_t vactive_line_header_src[] = {
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_line_header[count_of(vactive_line_header_src)];
static const uint32_t vactive_text_line_header_src[] = {
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
};
static uint32_t vactive_text_line_header[count_of(vactive_text_line_header_src)];
#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)];
if (h_repeat_shift == 2) {
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 {
for (int i = 0; i < timing_mode->h_active_pixels >> 1; ++i) {
uint32_t val = (uint32_t)(*src_ptr++) * 0x10001;
*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)];
if (h_repeat_shift == 2) {
for (int i = 0; i < timing_mode->h_active_pixels >> 2; ++i) {
uint32_t val = (uint32_t)(*src_ptr++) * 0x01010101;
*dst_ptr++ = val;
}
}
else {
for (int i = 0; i < timing_mode->h_active_pixels >> 2; ++i) {
uint32_t val = ((uint32_t)(*src_ptr++) * 0x0101);
val |= ((uint32_t)(*src_ptr++) * 0x01010000);
*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();
}
uint8_t color_lut[8] = {
#define CLUT_ENTRY(i) (i)
#define CLUT_R CLUT_ENTRY(1 << 6)
#define CLUT_G CLUT_ENTRY(1 << 3)
#define CLUT_B CLUT_ENTRY(1 << 0)
0,
CLUT_R,
CLUT_G,
CLUT_R | CLUT_G,
CLUT_B,
CLUT_R | CLUT_B,
CLUT_G | CLUT_B,
CLUT_R | CLUT_G | CLUT_B,
#undef CLUT_R
#undef CLUT_G
#undef CLUT_B
#undef CLUT_ENTRY
};
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* src_ptr = &frame_buffer_display[(y / 24) * frame_width * 2];
uint32_t* dst_ptr = &line_buffers[ch_num * line_buf_total_len + count_of(vactive_text_line_header)];
for (int i = 0; i < frame_width; i += 2) {
uint32_t tmp_h, tmp_l;
uint8_t c = (*src_ptr++ - 0x20);
uint32_t bits = (c < 95) ? font_cache[c * 24 + char_y] : 0;
uint8_t attr = *src_ptr++;
uint32_t bg = color_lut[(attr >> 3) & 7];
uint32_t colour = color_lut[attr & 7] ^ bg;
uint32_t bg_xor = bg * 0x3030303;
if (attr & ATTR_LOW_INTEN) bits = bits & 0xaaaaaaaa;
if ((attr & ATTR_V_LOW_INTEN) == ATTR_V_LOW_INTEN) bits >>= 1;
*dst_ptr++ = colour * ((bits >> 6) & 0x3030303) ^ bg_xor;
*dst_ptr++ = colour * ((bits >> 4) & 0x3030303) ^ bg_xor;
*dst_ptr++ = colour * ((bits >> 2) & 0x3030303) ^ bg_xor;
tmp_l = colour * ((bits >> 0) & 0x3030303) ^ bg_xor;
if (i == frame_width - 1) {
*dst_ptr++ = tmp_l;
break;
}
c = (*src_ptr++ - 0x20);
bits = (c < 95) ? font_cache[c * 24 + char_y] : 0;
attr = *src_ptr++;
if (attr & ATTR_LOW_INTEN) bits = bits & 0xaaaaaaaa;
if ((attr & ATTR_V_LOW_INTEN) == ATTR_V_LOW_INTEN) bits >>= 1;
bg = color_lut[(attr >> 3) & 7] ;
colour = color_lut[attr & 7] ^ bg;
bg_xor = bg * 0x3030303;
tmp_h = colour * ((bits >> 6) & 0x3030303) ^ bg_xor;
*dst_ptr++ = tmp_l & 0xffff | (tmp_h << 16);
tmp_l = tmp_h >> 16;
tmp_h = colour * ((bits >> 4) & 0x3030303) ^ bg_xor;
*dst_ptr++ = tmp_l & 0xffff | (tmp_h << 16);
tmp_l = tmp_h >> 16;
tmp_h = colour * ((bits >> 2) & 0x3030303) ^ bg_xor;
*dst_ptr++ = tmp_l & 0xffff | (tmp_h << 16);
tmp_l = tmp_h >> 16;
tmp_h = colour * ((bits >> 0) & 0x3030303) ^ bg_xor;
*dst_ptr++ = tmp_l & 0xffff | (tmp_h << 16);
}
if (y / 24 == cursor_y) {
uint8_t* dst_ptr = (uint8_t*)&line_buffers[ch_num * line_buf_total_len + count_of(vactive_text_line_header)] + 14 * cursor_x;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
*dst_ptr++ ^= 0xff;
}
}
}
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
#ifndef MICROPY_BUILD_TYPE
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;
}
#endif
extern "C" void __no_inline_not_in_flash_func(display_setup_clock_preinit)() {
uint32_t intr_stash = save_and_disable_interrupts();
// 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;
// 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 USB PLL to 528MHz
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);
// Now we are running fast set fast QSPI clock and read delay
// On MicroPython this is setup by main.
#ifndef MICROPY_BUILD_TYPE
set_qmi_timing();
#endif
restore_interrupts(intr_stash);
}
#ifndef MICROPY_BUILD_TYPE
// Trigger clock setup early - on MicroPython this is done by a hook in main.
namespace {
class DV_preinit {
public:
DV_preinit() {
display_setup_clock_preinit();
}
};
DV_preinit dv_preinit __attribute__ ((init_priority (101))) ;
}
#endif
void DVHSTX::display_setup_clock() {
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);
// Set the sys PLL to the requested freq
pll_init(pll_sys, PLL_COMMON_REFDIV, vco_freq, post_div1, post_div2);
// CLK HSTX = Requested freq
clock_configure(clk_hstx,
0,
CLOCKS_CLK_HSTX_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
freq, freq);
}
RGB888* DVHSTX::get_palette()
{
return palette;
}
DVHSTX::DVHSTX()
{
// Always use the bottom channels
dma_claim_mask((1 << NUM_CHANS) - 1);
}
bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_, bool double_buffered, const DVHSTXPinout &pinout)
{
if (inited) reset();
cursor_y = -1;
ch_num = 0;
line_num = -1;
v_scanline = 2;
flip_next = false;
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) {
dvhstx_debug("Unsupported resolution %dx%d", width, height);
return false;
}
display = this;
display_palette = get_palette();
dvhstx_debug("Setup clock\n");
display_setup_clock();
#if !defined(MICROPY_BUILD_TYPE) && !defined(ARDUINO)
stdio_init_all();
#endif
dvhstx_debug("Clock setup done\n");
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;
memcpy(vblank_line_vsync_off, vblank_line_vsync_off_src, sizeof(vblank_line_vsync_off_src));
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;
memcpy(vblank_line_vsync_on, vblank_line_vsync_on_src, sizeof(vblank_line_vsync_on_src));
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;
memcpy(vactive_line_header, vactive_line_header_src, sizeof(vactive_line_header_src));
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;
memcpy(vactive_text_line_header, vactive_text_line_header_src, sizeof(vactive_text_line_header_src));
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:
dvhstx_debug("Unsupported mode %d", (int)mode);
return false;
}
#ifdef MICROPY_BUILD_TYPE
if (frame_width * frame_height * frame_bytes_per_pixel > sizeof(frame_buffer_a)) {
panic("Frame buffer too large");
}
frame_buffer_display = frame_buffer_a;
frame_buffer_back = double_buffered ? frame_buffer_b : frame_buffer_a;
#else
frame_buffer_display = (uint8_t*)malloc(frame_width * frame_height * frame_bytes_per_pixel);
frame_buffer_back = double_buffered ? (uint8_t*)malloc(frame_width * frame_height * frame_bytes_per_pixel) : frame_buffer_display;
#endif
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 * sizeof(palette[0]));
frame_buffer_display = frame_buffer_display;
dvhstx_debug("Frame buffers inited\n");
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) {
auto scramble = [](uint32_t b) {
auto take = [b](int shift1, int shift2) {
return ((b >> shift1) & 3) << shift2;
};
return
take( 0, 0) |
take( 2, 26) |
take( 4, 18) |
take( 6, 10) |
take( 8, 2) |
take(10, 28) |
take(12, 20) |
take(14, 12) |
take(16, 4) |
take(18, 30) |
take(20, 22) |
take(22, 14) |
take(24, 6) |
take(26, 28);
};
// Need to pre-render the font to RAM to be fast enough.
font_cache = (uint32_t*)malloc(4 * FONT->line_height * 96);
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++ = scramble(render_char_line(c, y));
}
}
}
// Ensure HSTX FIFO is clear
reset_block_num(RESET_HSTX);
sleep_us(10);
unreset_block_num_wait_blocking(RESET_HSTX);
sleep_us(10);
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:
dvhstx_debug("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.
constexpr int HSTX_FIRST_PIN = 12;
// Assign clock pair to two neighbouring pins:
hstx_ctrl_hw->bit[(pinout.clk_p ) - HSTX_FIRST_PIN] = HSTX_CTRL_BIT0_CLK_BITS;
hstx_ctrl_hw->bit[(pinout.clk_p ^ 1) - HSTX_FIRST_PIN] = 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:
int bit = pinout.rgb_p[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 ) - HSTX_FIRST_PIN] = lane_data_sel_bits;
hstx_ctrl_hw->bit[(bit ^ 1) - HSTX_FIRST_PIN] = lane_data_sel_bits | HSTX_CTRL_BIT0_INV_BITS;
}
for (int i = 12; i <= 19; ++i) {
gpio_set_function(i, GPIO_FUNC_HSTX);
gpio_set_drive_strength(i, GPIO_DRIVE_STRENGTH_4MA);
}
dvhstx_debug("GPIO configured\n");
// 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
);
}
dvhstx_debug("DMA channels claimed\n");
dma_hw->intr = (1 << NUM_CHANS) - 1;
dma_hw->ints2 = (1 << NUM_CHANS) - 1;
dma_hw->inte2 = (1 << NUM_CHANS) - 1;
if (is_text_mode) irq_set_exclusive_handler(DMA_IRQ_2, dma_irq_handler_text);
else irq_set_exclusive_handler(DMA_IRQ_2, dma_irq_handler);
irq_set_priority(DMA_IRQ_2, PICO_HIGHEST_IRQ_PRIORITY);
irq_set_enabled(DMA_IRQ_2, true);
dma_channel_start(0);
dvhstx_debug("DVHSTX started\n");
inited = true;
return true;
}
void DVHSTX::reset() {
if (!inited) return;
inited = false;
hstx_ctrl_hw->csr = 0;
irq_set_enabled(DMA_IRQ_2, false);
irq_remove_handler(DMA_IRQ_2, irq_get_exclusive_handler(DMA_IRQ_2));
for (int i = 0; i < NUM_CHANS; ++i)
dma_channel_abort(i);
if (font_cache) {
free(font_cache);
font_cache = nullptr;
}
free(line_buffers);
line_buffers = nullptr;
#ifndef MICROPY_BUILD_TYPE
free(frame_buffer_display);
if (frame_buffer_display != frame_buffer_back) {
free(frame_buffer_back);
}
frame_buffer_display = frame_buffer_back = nullptr;
#endif
}
void DVHSTX::flip_blocking() {
if (get_single_buffered())
return;
wait_for_vsync();
flip_now();
}
void DVHSTX::flip_now() {
if (get_single_buffered())
return;
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() {
if (get_single_buffered())
return;
flip_next = true;
}
void DVHSTX::wait_for_flip() {
if (get_single_buffered())
return;
while (flip_next) __wfe();
}

View file

@ -1,157 +0,0 @@
#pragma once
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
// DVI HSTX driver for use with Pimoroni PicoGraphics
namespace pimoroni {
struct DVHSTXPinout {
uint8_t clk_p, rgb_p[3];
};
typedef uint32_t RGB888;
// 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,
TEXT_GREEN,
TEXT_BLUE,
TEXT_YELLOW,
TEXT_MAGENTA,
TEXT_CYAN,
TEXT_WHITE,
BG_BLACK = 0,
BG_RED = TEXT_RED << 3,
BG_GREEN = TEXT_GREEN << 3,
BG_BLUE = TEXT_BLUE << 3,
BG_YELLOW = TEXT_YELLOW << 3,
BG_MAGENTA = TEXT_MAGENTA << 3,
BG_CYAN = TEXT_CYAN << 3,
BG_WHITE = TEXT_WHITE << 3,
ATTR_NORMAL_INTEN = 0,
ATTR_LOW_INTEN = 1 << 6,
ATTR_V_LOW_INTEN = 1 << 7 | ATTR_LOW_INTEN,
};
//--------------------------------------------------
// 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 h_repeat = 4;
uint8_t v_repeat = 4;
Mode mode = MODE_RGB565;
public:
DVHSTX();
//--------------------------------------------------
// Methods
//--------------------------------------------------
public:
bool get_single_buffered() { return frame_buffer_display && frame_buffer_display == frame_buffer_back; }
bool get_double_buffered() { return frame_buffer_display && frame_buffer_display != frame_buffer_back; }
template<class T>
T *get_back_buffer() { return (T*)(frame_buffer_back); }
template<class T>
T *get_front_buffer() { return (T*)(frame_buffer_display); }
uint16_t get_width() const { return frame_width; }
uint16_t get_height() const { return frame_height; }
RGB888* get_palette();
bool init(uint16_t width, uint16_t height, Mode mode, bool double_buffered, const DVHSTXPinout &pinout);
void reset();
// 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();
void set_cursor(int x, int y) { cursor_x = x; cursor_y = y; }
void cursor_off(void) { cursor_y = -1; }
private:
RGB888 palette[PALETTE_SIZE];
bool double_buffered;
uint8_t* frame_buffer_display;
uint8_t* frame_buffer_back;
uint32_t* font_cache = nullptr;
void display_setup_clock();
// DMA scanline filling
uint ch_num = 0;
int line_num = -1;
volatile int v_scanline = 2;
volatile bool flip_next;
bool inited = false;
uint32_t* line_buffers;
const struct dvi_timing* timing_mode;
int v_inactive_total;
int v_total_active_lines;
uint h_repeat_shift;
uint v_repeat_shift;
int line_bytes_per_pixel;
uint32_t* display_palette = nullptr;
int cursor_x, cursor_y;
};
}

View file

@ -1,265 +0,0 @@
#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
};

View file

@ -1,62 +0,0 @@
#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;
int h_front_porch;
int h_sync_width;
int h_back_porch;
int h_active_pixels;
bool v_sync_polarity;
int v_front_porch;
int v_sync_width;
int v_back_porch;
int 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;

View file

@ -1,42 +0,0 @@
/*
* 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

View file

@ -1,895 +0,0 @@
/*******************************************************************************
* 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*/