CI, clang, readme

This commit is contained in:
Liz 2025-02-24 12:29:05 -05:00
parent cd1a9b39c5
commit d4a26331dd
19 changed files with 2290 additions and 1796 deletions

46
.github/ISSUE_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,46 @@
Thank you for opening an issue on an Adafruit Arduino library repository. To
improve the speed of resolution please review the following guidelines and
common troubleshooting steps below before creating the issue:
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
something isn't working as expected. In many cases the problem is a common issue
that you will more quickly receive help from the forum community. GitHub issues
are meant for known defects in the code. If you don't know if there is a defect
in the code then start with troubleshooting on the forum first.
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
check all of the steps and commands to run have been followed. Consult the
forum if you're unsure or have questions about steps in a guide/tutorial.
- **For Arduino projects check these very common issues to ensure they don't apply**:
- For uploading sketches or communicating with the board make sure you're using
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
very hard to tell the difference between a data and charge cable! Try using the
cable with other devices or swapping to another cable to confirm it is not
the problem.
- **Be sure you are supplying adequate power to the board.** Check the specs of
your board and plug in an external power supply. In many cases just
plugging a board into your computer is not enough to power it and other
peripherals.
- **Double check all soldering joints and connections.** Flakey connections
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
- **Ensure you are using an official Arduino or Adafruit board.** We can't
guarantee a clone board will have the same functionality and work as expected
with this code and don't support them.
If you're sure this issue is a defect in the code and checked the steps above
please fill in the following fields to provide enough troubleshooting information.
You may delete the guideline and text above to just leave the following details:
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
VERSION HERE**
- List the steps to reproduce the problem below (if possible attach a sketch or
copy the sketch code in too): **LIST REPRO STEPS BELOW**

26
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,26 @@
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
Before you open the request please review the following guidelines and tips to
help it be more easily integrated:
- **Describe the scope of your change--i.e. what the change does and what parts
of the code were modified.** This will help us understand any risks of integrating
the code.
- **Describe any known limitations with your change.** For example if the change
doesn't apply to a supported platform of the library please mention it.
- **Please run any tests or examples that can exercise your modified code.** We
strive to not break users of the code and running tests/examples helps with this
process.
Thank you again for contributing! We will try to test and integrate the change
as soon as we can, but be aware we have many GitHub repositories to manage and
can't immediately respond to every request. There is no need to bump or check in
on a pull request (it will clutter the discussion of the request).
Also don't be worried if the request is closed or not integrated--sometimes the
priorities of Adafruit's GitHub code (education, ease of use) might not match the
priorities of the pull request. Don't fret, the open source community thrives on
forks and GitHub makes it easy to keep your changes in a forked repo.
After reviewing the guidelines above you can delete this text from the pull request.

32
.github/workflows/githubci.yml vendored Normal file
View file

@ -0,0 +1,32 @@
name: Arduino Library CI
on: [pull_request, push, repository_dispatch]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v4
with:
python-version: '3.x'
- uses: actions/checkout@v3
- uses: actions/checkout@v3
with:
repository: adafruit/ci-arduino
path: ci
- name: pre-install
run: bash ci/actions_install.sh
- name: test platforms
run: python3 ci/build_platform.py main_platforms
- name: clang
run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .
- name: doxygen
env:
GH_REPO_TOKEN: ${{ secrets.GH_REPO_TOKEN }}
PRETTYNAME : "Adafruit DVI HSTX Arduino Library"
run: bash ci/doxy_gen_and_deploy.sh

View file

@ -1,49 +1,28 @@
# DVI for HSTX <!-- omit in toc -->
# Adafruit DVI HSTX Library [![Build Status](https://github.com/adafruit/Adafruit-DVI-HSTX/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit-DVI-HSTX/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit-DVI-HSTX/html/index.html)
This repository is home to the Pimoroni PicoGraphics compatible DVI driver for RP2 chips with HSTX (e.g. RP2350).
This library is based on the [dvhstx library by MichaelBell](https://github.com/MichaelBell/dvhstx)
[![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/)
It is an Arduino library for DVI over HSTX with Adafruit GFX.
- [Introduction](#introduction)
- [Download MicroPython](#download-micropython)
- [Documentation](#documentation)
- [C/C++ Resources](#cc-resources)
- [C/C++ Community Projects](#cc-community-projects)
## Dependencies
* [Adafruit_GFX](https://github.com/adafruit/Adafruit-GFX-Library)
## Introduction
# Contributing
DV HSTX will enable you to create big, bold audio visual projects using MicroPython and an HDMI display of your choice.
Contributions are welcome! Please read our [Code of Conduct](https://github.com/adafruit/Adafruit-DVI-HSTX/blob/main/CODE_OF_CONDUCT.md>)
before contributing to help this project stay welcoming.
![Mandelbrot fractal displayed on a monitor](Mandelbrot.jpg)
## Documentation and doxygen
Documentation is produced by doxygen. Contributions should include documentation for any new code added.
## Download MicroPython
Some examples of how to use doxygen can be found in these guide pages:
TODO
https://learn.adafruit.com/the-well-automated-arduino-library/doxygen
* [DV HSTX MicroPython Releases](https://github.com/MichaelBell/dvhstx/releases)
https://learn.adafruit.com/the-well-automated-arduino-library/doxygen-tips
## Documentation
Written by Jeff Epler for Adafruit Industries.
MIT license, check license.txt for more information
All text above must be included in any redistribution
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
To install, use the Arduino Library Manager and search for "Adafruit DVI HSTX" and install the library.

127
code-of-conduct.md Normal file
View file

@ -0,0 +1,127 @@
# Adafruit Community Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and leaders pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level or type of
experience, education, socio-economic status, nationality, personal appearance,
race, religion, or sexual identity and orientation.
## Our Standards
We are committed to providing a friendly, safe and welcoming environment for
all.
Examples of behavior that contributes to creating a positive environment
include:
* Be kind and courteous to others
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Collaborating with other community members
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and sexual attention or advances
* The use of inappropriate images, including in a community member's avatar
* The use of inappropriate language, including in a community member's nickname
* Any spamming, flaming, baiting or other attention-stealing behavior
* Excessive or unwelcome helping; answering outside the scope of the question
asked
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate
The goal of the standards and moderation guidelines outlined here is to build
and maintain a respectful community. We ask that you dont just aim to be
"technically unimpeachable", but rather try to be your best self.
We value many things beyond technical expertise, including collaboration and
supporting others within our community. Providing a positive experience for
other community members can have a much more significant impact than simply
providing the correct answer.
## Our Responsibilities
Project leaders are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project leaders have the right and responsibility to remove, edit, or
reject messages, comments, commits, code, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any community member for other behaviors that they deem
inappropriate, threatening, offensive, or harmful.
## Moderation
Instances of behaviors that violate the Adafruit Community Code of Conduct
may be reported by any member of the community. Community members are
encouraged to report these situations, including situations they witness
involving other community members.
You may report in the following ways:
In any situation, you may send an email to <support@adafruit.com>.
On the Adafruit Discord, you may send an open message from any channel
to all Community Helpers by tagging @community helpers. You may also send an
open message from any channel, or a direct message to @kattni#1507,
@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or
@Andon#8175.
Email and direct message reports will be kept confidential.
In situations on Discord where the issue is particularly egregious, possibly
illegal, requires immediate action, or violates the Discord terms of service,
you should also report the message directly to Discord.
These are the steps for upholding our communitys standards of conduct.
1. Any member of the community may report any situation that violates the
Adafruit Community Code of Conduct. All reports will be reviewed and
investigated.
2. If the behavior is an egregious violation, the community member who
committed the violation may be banned immediately, without warning.
3. Otherwise, moderators will first respond to such behavior with a warning.
4. Moderators follow a soft "three strikes" policy - the community member may
be given another chance, if they are receptive to the warning and change their
behavior.
5. If the community member is unreceptive or unreasonable when warned by a
moderator, or the warning goes unheeded, they may be banned for a first or
second offense. Repeated offenses will result in the community member being
banned.
## Scope
This Code of Conduct and the enforcement policies listed above apply to all
Adafruit Community venues. This includes but is not limited to any community
spaces (both public and private), the entire Adafruit Discord server, and
Adafruit GitHub repositories. Examples of Adafruit Community spaces include
but are not limited to meet-ups, audio chats on the Adafruit Discord, or
interaction at a conference.
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. As a community
member, you are representing our community, and are expected to behave
accordingly.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.4, available at
<https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>,
and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html).
For other projects adopting the Adafruit Community Code of
Conduct, please contact the maintainers of those projects for enforcement.
If you wish to use this code of conduct for your own project, consider
explicitly mentioning your moderation policy or making a copy with your
own moderation policy so as to avoid confusion.

View file

@ -2,24 +2,29 @@
#include <Adafruit_dvhstx.h>
// If your board definition has PIN_CKP and related defines, DVHSTX_PINOUT_DEFAULT is available
// 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);
// 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);
// while(!Serial);
if (!display.begin()) { // Blink LED if insufficient RAM
pinMode(LED_BUILTIN, OUTPUT);
for (;;) digitalWrite(LED_BUILTIN, (millis() / 500) & 1);
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));
display.drawLine(random(display.width()), random(display.height()),
random(display.width()), random(display.height()),
random(65536));
sleep_ms(1);
}

View file

@ -2,24 +2,29 @@
#include <Adafruit_dvhstx.h>
// If your board definition has PIN_CKP and related defines, DVHSTX_PINOUT_DEFAULT is available
// 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);
// 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);
// while(!Serial);
if (!display.begin()) { // Blink LED if insufficient RAM
pinMode(LED_BUILTIN, OUTPUT);
for (;;) digitalWrite(LED_BUILTIN, (millis() / 500) & 1);
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));
display.drawLine(random(display.width()), random(display.height()),
random(display.width()), random(display.height()),
random(65536));
sleep_ms(1);
}

View file

@ -12,22 +12,20 @@ DVHSTXText3 display(DVHSTX_PINOUT_DEFAULT);
// 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,
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,
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
};
const static TextColor intensity[] = {TextColor::ATTR_NORMAL_INTEN,
TextColor::ATTR_LOW_INTEN,
TextColor::ATTR_V_LOW_INTEN};
void setup() {
Serial.begin(115200);
@ -40,18 +38,19 @@ void setup() {
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'.");
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.printf(" %d ri vli ", (int)d >> 3);
}
display.write('\n');
for (TextColor c : colors) {
display.printf(" %d ", (int)c);
display.printf(" %d ", (int)c);
for (TextColor d : background_colors) {
display.setColor(c, d);
display.write('*');
@ -83,10 +82,12 @@ void loop() {
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
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]);
display.setColor(colors[fg_idx], background_colors[bg_idx],
intensity[inten_idx]);
for (int j = random(6); j; j--)
display.write(' ');
}

23
keywords.txt Normal file
View file

@ -0,0 +1,23 @@
#######################################
# Syntax Coloring Map for DVI HSTX library
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
#######################################
# Structures (KEYWORD3)
#######################################
######################################
# Constants (LITERAL1)
#######################################

View file

@ -1,5 +1,5 @@
name=Adafruit DVI HSTX
version=0.1.0
version=1.0.0
author=Jeff Epler
maintainer=Adafruit <info@adafruit.com>
sentence=Arduino library for RP2350 DVI output, based on dvhstx

View file

@ -79,12 +79,13 @@ void DVHSTX8::swap(bool copy_framebuffer) {
}
void DVHSTXText3::clear() {
std::fill(getBuffer(), getBuffer() + WIDTH*HEIGHT, attr << 8);
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 (!*this)
return 0;
if (c == '\r') { // Carriage return
cursor_x = 0;
@ -95,7 +96,8 @@ size_t DVHSTXText3::write(uint8_t c) {
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
drawFastHLine(0, HEIGHT - 1, WIDTH,
' ' | (attr << 8)); // Clear bottom line
cursor_y = HEIGHT - 1;
} else {
cursor_y++;

View file

@ -195,7 +195,10 @@ public:
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 setColor(TextColor fg, TextColor bg,
TextColor inten = TextColor::ATTR_NORMAL_INTEN) {
attr = fg | bg | inten;
}
void hideCursor() {
cursor_visible = false;
@ -225,6 +228,7 @@ public:
int getCursorX() const { return cursor_x; }
int getCursorY() const { return cursor_y; }
private:
DVHSTXPinout pinout;
DVHSTXResolution res;

File diff suppressed because it is too large Load diff

View file

@ -2,156 +2,167 @@
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"
#include "pico/stdlib.h"
// DVI HSTX driver for use with Pimoroni PicoGraphics
namespace pimoroni {
struct DVHSTXPinout {
uint8_t clk_p, rgb_p[3];
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,
};
typedef uint32_t RGB888;
enum TextColour {
TEXT_BLACK = 0,
TEXT_RED,
TEXT_GREEN,
TEXT_BLUE,
TEXT_YELLOW,
TEXT_MAGENTA,
TEXT_CYAN,
TEXT_WHITE,
// 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;
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,
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;
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;
};
} // namespace pimoroni

View file

@ -3,263 +3,239 @@
#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,
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,
.v_sync_polarity = false,
.v_front_porch = 10,
.v_sync_width = 2,
.v_back_porch = 33,
.v_active_lines = 480,
.bit_clk_khz = 252000
};
.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,
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,
.v_sync_polarity = false,
.v_front_porch = 1,
.v_sync_width = 4,
.v_back_porch = 23,
.v_active_lines = 600,
.bit_clk_khz = 400000
};
.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,
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,
.v_sync_polarity = false,
.v_front_porch = 9,
.v_sync_width = 6,
.v_back_porch = 30,
.v_active_lines = 480,
.bit_clk_khz = 270000
};
.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,
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,
.v_sync_polarity = false,
.v_front_porch = 5,
.v_sync_width = 5,
.v_back_porch = 39,
.v_active_lines = 576,
.bit_clk_khz = 270000
};
.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,
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,
.v_sync_polarity = true,
.v_front_porch = 13,
.v_sync_width = 2,
.v_back_porch = 34,
.v_active_lines = 400,
.bit_clk_khz = 283200
};
.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,
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,
.v_sync_polarity = true,
.v_front_porch = 3,
.v_sync_width = 10,
.v_back_porch = 7,
.v_active_lines = 480,
.bit_clk_khz = 295200
};
.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,
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,
.v_sync_polarity = true,
.v_front_porch = 3,
.v_sync_width = 5,
.v_back_porch = 10,
.v_active_lines = 450,
.bit_clk_khz = 278400
};
.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,
.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,
.v_sync_polarity = false,
.v_front_porch = 3,
.v_sync_width = 4,
.v_back_porch = 11,
.v_active_lines = 600,
.bit_clk_khz = 354000
};
.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,
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,
.v_sync_polarity = true,
.v_front_porch = 3,
.v_sync_width = 5,
.v_back_porch = 14,
.v_active_lines = 540,
.bit_clk_khz = 408000
};
.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,
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,
.v_sync_polarity = true,
.v_front_porch = 3,
.v_sync_width = 5,
.v_back_porch = 11,
.v_active_lines = 540,
.bit_clk_khz = 336000
};
.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,
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,
.v_sync_polarity = false,
.v_front_porch = 3,
.v_sync_width = 4,
.v_back_porch = 15,
.v_active_lines = 768,
.bit_clk_khz = 560000
};
.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,
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,
.v_sync_polarity =
false,
.v_front_porch = 3,
.v_sync_width = 5,
.v_back_porch = 9,
.v_active_lines = 720,
.bit_clk_khz = 528000
};
.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,
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,
.v_sync_polarity =
false,
.v_front_porch = 3,
.v_sync_width = 5,
.v_back_porch = 13,
.v_active_lines = 720,
.bit_clk_khz = 640000
};
.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!
// 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,
.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,
.v_sync_polarity = false,
.v_front_porch = 7,
.v_sync_width = 8,
.v_back_porch = 6,
.v_active_lines = 1080,
.bit_clk_khz = 660000
};
.bit_clk_khz = 660000};
// 1440p24 YOLO - works on my Dell Ultrasharp, that most forgiving of monitors. May require a little more than 1.3V
// 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,
.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,
.v_sync_polarity = false,
.v_front_porch = 2,
.v_sync_width = 6,
.v_back_porch = 2,
.v_active_lines = 1440,
.bit_clk_khz = 912000
};
.bit_clk_khz = 912000};

View file

@ -8,7 +8,7 @@
#define TMDS_CTRL_10 0x154u
#define TMDS_CTRL_11 0x2abu
#define TMDS_BALANCED_LOW 0x307u
#define TMDS_BALANCED_LOW 0x307u
#define TMDS_BALANCED_HIGH 0x2f0u
#define TMDS_BLACK_A 0x100u
@ -18,31 +18,35 @@
#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 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_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)
#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 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;
bool v_sync_polarity;
int v_front_porch;
int v_sync_width;
int v_back_porch;
int v_active_lines;
uint bit_clk_khz;
uint bit_clk_khz;
};
extern const struct dvi_timing dvi_timing_640x480p_60hz;

View file

@ -10,33 +10,31 @@
#include "pico/types.h"
typedef struct {
uint16_t bitmap_index;
uint16_t adv_w;
int8_t box_w, box_h, ofs_x, ofs_y;
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;
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;
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_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
#endif // SOFTWARE_FONT_H

File diff suppressed because it is too large Load diff