640x480 and 800x480 monochrome now working

Required diverging libdvi a little further from the original, sorry
pull/46/head
Phillip Burgess 2023-01-17 09:42:09 -08:00
rodzic e85c2d39b0
commit 86fd338d7c
7 zmienionych plików z 57 dodań i 16 usunięć

Wyświetl plik

@ -22,6 +22,13 @@ generated during the Pico SDK build process, is provided here for Arduino
build to work. If any changes are made in dvi_serialiser.pio (either here
or by bringing in updates from upstream code), this header will need to be
regenerated.
- extern "C" around most function defs, to be linkable with C++ (Arduino).
- A couple compile-time constants have been changed to run-time configurable
because some color and resolution things aren't known until a constructor is
called: dvi_vertical_repeat and dvi_monochrome_tmds.
- DVI_1BPP_BIT_REVERSE is set '1' by default. This might affect some examples
built with the Pico SDK (moon, bad_apple), but could be fixed by changing the
compile definitions in CMakeLists.txt in those app subdirectories.
All files from the PicoDVI repo are kept even if not used in this build
(e.g. apps and assets directories, among others) so same repo can still be

Wyświetl plik

@ -0,0 +1,20 @@
// 1-bit Adafruit_GFX-compatible framebuffer for PicoDVI.
#include <PicoDVI.h>
//DVIGFX1 display(640, 480, dvi_timing_640x480p_60hz, VREG_VOLTAGE_1_30, pimoroni_demo_hdmi_cfg);
DVIGFX1 display(800, 480, dvi_timing_800x480p_60hz, VREG_VOLTAGE_1_30, pimoroni_demo_hdmi_cfg);
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);
}
}
void loop() {
// Draw random lines
display.drawLine(random(display.width()), random(display.height()), random(display.width()), random(display.height()), random(2));
}

Wyświetl plik

@ -7,6 +7,10 @@
#include "dvi_serialiser.h"
#include "tmds_encode.h"
// Adafruit PicoDVI fork requires a couple global items run-time configurable:
uint8_t dvi_vertical_repeat = DVI_VERTICAL_REPEAT;
bool dvi_monochrome_tmds = DVI_MONOCHROME_TMDS;
// Time-critical functions pulled into RAM but each in a unique section to
// allow garbage collection
#define __dvi_func(f) __not_in_flash_func(f)
@ -46,11 +50,10 @@ void dvi_init(struct dvi_inst *inst, uint spinlock_tmds_queue, uint spinlock_col
for (int i = 0; i < DVI_N_TMDS_BUFFERS; ++i) {
void *tmdsbuf;
#if DVI_MONOCHROME_TMDS
tmdsbuf = malloc(inst->timing->h_active_pixels / DVI_SYMBOLS_PER_WORD * sizeof(uint32_t));
#else
tmdsbuf = malloc(3 * inst->timing->h_active_pixels / DVI_SYMBOLS_PER_WORD * sizeof(uint32_t));
#endif
if (dvi_monochrome_tmds)
tmdsbuf = malloc(inst->timing->h_active_pixels / DVI_SYMBOLS_PER_WORD * sizeof(uint32_t));
else
tmdsbuf = malloc(3 * inst->timing->h_active_pixels / DVI_SYMBOLS_PER_WORD * sizeof(uint32_t));
if (!tmdsbuf)
panic("TMDS buffer allocation failed");
queue_add_blocking_u32(&inst->q_tmds_free, &tmdsbuf);
@ -205,7 +208,7 @@ static void __dvi_func(dvi_dma_irq_handler)(struct dvi_inst *inst) {
tmdsbuf = NULL;
}
else if (queue_try_peek_u32(&inst->q_tmds_valid, &tmdsbuf)) {
if (inst->timing_state.v_ctr % DVI_VERTICAL_REPEAT == DVI_VERTICAL_REPEAT - 1) {
if (inst->timing_state.v_ctr % dvi_vertical_repeat == dvi_vertical_repeat - 1) {
queue_remove_blocking_u32(&inst->q_tmds_valid, &tmdsbuf);
inst->tmds_buf_release_next = tmdsbuf;
}
@ -213,7 +216,7 @@ static void __dvi_func(dvi_dma_irq_handler)(struct dvi_inst *inst) {
else {
// No valid scanline was ready (generates solid red scanline)
tmdsbuf = NULL;
if (inst->timing_state.v_ctr % DVI_VERTICAL_REPEAT == DVI_VERTICAL_REPEAT - 1)
if (inst->timing_state.v_ctr % dvi_vertical_repeat == dvi_vertical_repeat - 1)
++inst->late_scanline_ctr;
}
@ -226,7 +229,7 @@ static void __dvi_func(dvi_dma_irq_handler)(struct dvi_inst *inst) {
else {
_dvi_load_dma_op(inst->dma_cfg, &inst->dma_list_error);
}
if (inst->scanline_callback && inst->timing_state.v_ctr % DVI_VERTICAL_REPEAT == DVI_VERTICAL_REPEAT - 1) {
if (inst->scanline_callback && inst->timing_state.v_ctr % dvi_vertical_repeat == dvi_vertical_repeat - 1) {
inst->scanline_callback();
}
break;

Wyświetl plik

@ -118,7 +118,7 @@
// If 1, reverse the order of pixels within each byte. Order of bytes within
// each word is still little-endian.
#ifndef DVI_1BPP_BIT_REVERSE
#define DVI_1BPP_BIT_REVERSE 0
#define DVI_1BPP_BIT_REVERSE 1 // Adafruit_GFX GFXcanvas1 requires this 1
#endif
// ----------------------------------------------------------------------------

Wyświetl plik

@ -7,6 +7,8 @@
// achievable bit clock from 12 MHz crystal)
// - Helper functions for generating DMA lists based on these timings
extern bool dvi_monochrome_tmds; // In dvi.c
// Pull into RAM but apply unique section suffix to allow linker GC
#define __dvi_func(x) __not_in_flash_func(x)
#define __dvi_const(x) __not_in_flash_func(x)
@ -312,11 +314,7 @@ void dvi_setup_scanline_for_active(const struct dvi_timing *t, const struct dvi_
void __dvi_func(dvi_update_scanline_data_dma)(const struct dvi_timing *t, const uint32_t *tmdsbuf, struct dvi_scanline_dma_list *l) {
for (int i = 0; i < N_TMDS_LANES; ++i) {
#if DVI_MONOCHROME_TMDS
const uint32_t *lane_tmdsbuf = tmdsbuf;
#else
const uint32_t *lane_tmdsbuf = tmdsbuf + i * t->h_active_pixels / DVI_SYMBOLS_PER_WORD;
#endif
const uint32_t *lane_tmdsbuf = dvi_monochrome_tmds ? tmdsbuf : tmdsbuf + i * t->h_active_pixels / DVI_SYMBOLS_PER_WORD;
if (i == TMDS_SYNC_LANE)
dvi_lane_from_list(l, i)[3].read_addr = lane_tmdsbuf;
else

Wyświetl plik

@ -47,7 +47,10 @@ static void *gfxptr = NULL; // For C access to active C++ object
DVIGFX16::DVIGFX16(const uint16_t w, const uint16_t h,
const struct dvi_timing &t, vreg_voltage v,
const struct dvi_serialiser_cfg &c)
: PicoDVI(t, v, c), GFXcanvas16(w, h) {}
: PicoDVI(t, v, c), GFXcanvas16(w, h) {
dvi_vertical_repeat = 2;
dvi_monochrome_tmds = false;
}
DVIGFX16::~DVIGFX16(void) { gfxptr = NULL; }
@ -102,6 +105,8 @@ DVIGFX8::DVIGFX8(const uint16_t w, const uint16_t h, const struct dvi_timing &t,
vreg_voltage v, const struct dvi_serialiser_cfg &c)
: PicoDVI(t, v, c), GFXcanvas8(w, ((h + 1) & ~1) + 4) {
HEIGHT = _height = h;
dvi_vertical_repeat = 2;
dvi_monochrome_tmds = false;
}
DVIGFX8::~DVIGFX8(void) { gfxptr = NULL; }
@ -162,6 +167,8 @@ DVIGFX8x2::DVIGFX8x2(const uint16_t w, const uint16_t h,
: PicoDVI(t, v, c), GFXcanvas8(w, h * 2 + 4) {
HEIGHT = _height = h;
buffer_save = buffer;
dvi_vertical_repeat = 2;
dvi_monochrome_tmds = false;
}
DVIGFX8x2::~DVIGFX8x2(void) {
@ -242,7 +249,10 @@ void DVIGFX8x2::swap(bool copy_framebuffer, bool copy_palette) {
DVIGFX1::DVIGFX1(const uint16_t w, const uint16_t h, const struct dvi_timing &t,
vreg_voltage v, const struct dvi_serialiser_cfg &c)
: PicoDVI(t, v, c), GFXcanvas1(w, h) {}
: PicoDVI(t, v, c), GFXcanvas1(w, h) {
dvi_vertical_repeat = 1;
dvi_monochrome_tmds = true;
}
DVIGFX1::~DVIGFX1(void) { gfxptr = NULL; }

Wyświetl plik

@ -6,6 +6,9 @@
#include "pico/stdlib.h" // In Pico SDK
#include <Adafruit_GFX.h>
extern uint8_t dvi_vertical_repeat; // In libdvi/dvi.c
extern bool dvi_monochrome_tmds; // In libdvi/dvi.c
class PicoDVI {
public:
PicoDVI(const struct dvi_timing &t = dvi_timing_640x480p_60hz,