Compare commits

..

No commits in common. "line-callback" and "main" have entirely different histories.

6 changed files with 24 additions and 161 deletions

View file

@ -38,13 +38,6 @@ Wire up your DVI breakout as follows:
If using jumper jerky, twist the - and + wires for each signal together to help with signal integrity.
Other pinouts can be used by passing a `pinout` parameter to the `init`
function.
This pinout consists of 4 numbers giving the *positive* pin in each differential pair, in the order CK, D0, D1, D2, D3, using GPIO numbering.
The default pinout is written `{13, 15, 17, 19}`.
Only pin numbers from 12 to 20 are valid, as other pins are not connected to the HSTX peripheral.
Using invalid pin numbers is an undignosed error.
TODO
## C/C++ Resources

View file

@ -29,7 +29,6 @@ using namespace pimoroni;
#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];
__attribute__((section(".uninitialized_data"))) RGB888 *global_palette[PALETTE_SIZE];
#endif
#include "font.h"
@ -159,9 +158,7 @@ void __scratch_x("display") DVHSTX::gfx_dma_handler() {
line_num = new_line_num;
uint32_t* dst_ptr = &line_buffers[line_num * line_buf_total_len + count_of(vactive_line_header)];
if (callback) {
callback(cb_data, y, dst_ptr);
} else if (line_bytes_per_pixel == 2) {
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) {
@ -602,7 +599,7 @@ DVHSTX::DVHSTX()
dma_claim_mask((1 << NUM_CHANS) - 1);
}
bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_, Pinout pinout)
bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_)
{
if (inited) reset();
@ -646,8 +643,8 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_, Pinout pinout)
}
else
{
volatile uint16_t full_width = display_width;
volatile uint16_t full_height = display_height;
uint16_t full_width = display_width;
uint16_t full_height = display_height;
h_repeat_shift = 0;
v_repeat_shift = 0;
@ -664,9 +661,6 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_, Pinout pinout)
if (full_width == 640) {
if (full_height == 480) timing_mode = &dvi_timing_640x480p_60hz;
}
else if (full_width == 1280 && full_height == 720) {
timing_mode = &dvi_timing_1280x720p_rb_50hz;
}
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;
@ -687,19 +681,11 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_, Pinout pinout)
if (!timing_mode) {
dvhstx_debug("Unsupported resolution %dx%d", width, height);
__builtin_trap();
return false;
}
display = this;
if (mode == MODE_PALETTE) {
#ifdef MICROPY_BUILD_TYPE
palette = global_palette;
#else
palette = (RGB888*)malloc(sizeof(RGB888) * PALETTE_SIZE);
display_palette = get_palette();
#endif
}
display_palette = get_palette();
dvhstx_debug("Setup clock\n");
display_setup_clock();
@ -745,7 +731,6 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_, Pinout pinout)
frame_bytes_per_pixel = 1;
line_bytes_per_pixel = 4;
break;
case MODE_LINE_CALLBACK:
case MODE_RGB888:
frame_bytes_per_pixel = 4;
line_bytes_per_pixel = 4;
@ -770,29 +755,14 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_, Pinout pinout)
frame_buffer_display = frame_buffer_a;
frame_buffer_back = frame_buffer_b;
palette = global_palette;
#else
if (mode != MODE_LINE_CALLBACK ) {
frame_buffer_display = (uint8_t*)malloc(frame_width * frame_height * frame_bytes_per_pixel);
frame_buffer_back = (uint8_t*)malloc(frame_width * frame_height * frame_bytes_per_pixel);
if (!frame_buffer_display) return false;
if (!frame_buffer_back) { free (frame_buffer_display); return false; }
if (mode == MODE_PALETTE) {
palette = (RGB888*)malloc(sizeof(RGB888) * PALETTE_SIZE);
if (!palette) {
free (frame_buffer_display);
free (frame_buffer_back);
return false;
}
}
}
frame_buffer_display = (uint8_t*)malloc(frame_width * frame_height * frame_bytes_per_pixel);
frame_buffer_back = (uint8_t*)malloc(frame_width * frame_height * frame_bytes_per_pixel);
#endif
if (mode != MODE_LINE_CALLBACK ) {
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);
}
if(mode == MODE_PALETTE)
memset(palette, 0, PALETTE_SIZE * sizeof(palette[0]));
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");
@ -846,7 +816,6 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_, Pinout pinout)
0 << HSTX_CTRL_EXPAND_SHIFT_RAW_SHIFT_LSB;
break;
case MODE_LINE_CALLBACK:
case MODE_PALETTE:
// Configure HSTX's TMDS encoder for RGB888
hstx_ctrl_hw->expand_tmds =
@ -920,28 +889,24 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_, Pinout pinout)
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:
{
int bit = pinout.clk_p - HSTX_FIRST_PIN;
hstx_ctrl_hw->bit[bit ] = HSTX_CTRL_BIT0_CLK_BITS;
hstx_ctrl_hw->bit[bit ^ 1] = HSTX_CTRL_BIT0_CLK_BITS | HSTX_CTRL_BIT0_INV_BITS;
}
hstx_ctrl_hw->bit[1] = HSTX_CTRL_BIT0_CLK_BITS;
hstx_ctrl_hw->bit[0] = HSTX_CTRL_BIT0_CLK_BITS | HSTX_CTRL_BIT0_INV_BITS;
for (uint lane = 0; lane < 3; ++lane) {
// For each TMDS lane, assign it to the correct GPIO pair based on the
// desired pinout:
int bit = pinout.rgb_p[lane] - HSTX_FIRST_PIN;
static const int lane_to_output_bit[3] = {2, 4, 6};
int bit = lane_to_output_bit[lane];
// Output even bits during first half of each HSTX cycle, and odd bits
// during second half. The shifter advances by two bits each cycle.
uint32_t lane_data_sel_bits =
(lane * 10 ) << HSTX_CTRL_BIT0_SEL_P_LSB |
(lane * 10 + 1) << HSTX_CTRL_BIT0_SEL_N_LSB;
// The two halves of each pair get identical data, but one pin is inverted.
hstx_ctrl_hw->bit[bit ] = lane_data_sel_bits;
hstx_ctrl_hw->bit[bit ^ 1] = lane_data_sel_bits | HSTX_CTRL_BIT0_INV_BITS;
}
hstx_ctrl_hw->bit[bit ] = lane_data_sel_bits | HSTX_CTRL_BIT0_INV_BITS;
hstx_ctrl_hw->bit[bit + 1] = lane_data_sel_bits;
}
for (int i = 12; i <= 19; ++i) {
gpio_set_function(i, GPIO_FUNC_HSTX);
@ -1005,10 +970,8 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_, Pinout pinout)
dvhstx_debug("DVHSTX started\n");
if (frame_buffer_display) {
for (int i = 0; i < frame_height; ++i) {
memset(&frame_buffer_display[i * frame_width * frame_bytes_per_pixel], i, frame_width * frame_bytes_per_pixel);
}
for (int i = 0; i < frame_height; ++i) {
memset(&frame_buffer_display[i * frame_width * frame_bytes_per_pixel], i, frame_width * frame_bytes_per_pixel);
}
dvhstx_debug("Frame buffer filled\n");
@ -1038,9 +1001,6 @@ void DVHSTX::reset() {
#ifndef MICROPY_BUILD_TYPE
free(frame_buffer_display);
free(frame_buffer_back);
if (palette) {
free(palette);
}
#endif
}
@ -1064,7 +1024,3 @@ void DVHSTX::flip_async() {
void DVHSTX::wait_for_flip() {
while (flip_next) __wfe();
}
int DVHSTX::get_h_active_pixels() const {
return timing_mode->h_active_pixels;
}

View file

@ -29,17 +29,12 @@ namespace pimoroni {
public:
static constexpr int PALETTE_SIZE = 256;
struct Pinout {
uint8_t clk_p, rgb_p[3];
};
enum Mode {
MODE_PALETTE = 2,
MODE_RGB565 = 1,
MODE_RGB888 = 3,
MODE_TEXT_MONO = 4,
MODE_TEXT_RGB111 = 5,
MODE_LINE_CALLBACK = 6,
};
enum TextColour {
@ -97,21 +92,9 @@ namespace pimoroni {
void clear();
typedef void(*line_fun_t)(void *cb_data, int line_num, uint32_t *data);
void set_callback(line_fun_t cb, void *data) {
callback = cb;
cb_data = data;
}
bool init(uint16_t width, uint16_t height, Mode mode = MODE_RGB565, Pinout pinout = {13, 15, 17, 19});
bool init(uint16_t width, uint16_t height, line_fun_t cb, void *data, Pinout pinout = {13, 15, 17, 19}) {
set_callback(cb, data);
return init(width, height, MODE_LINE_CALLBACK, pinout);
}
bool init(uint16_t width, uint16_t height, Mode mode = MODE_RGB565);
void reset();
int get_h_repeat_shift() const { return h_repeat_shift; }
int get_h_active_pixels() const;
// Wait for vsync and then flip the buffers
void flip_blocking();
@ -130,8 +113,7 @@ namespace pimoroni {
void text_dma_handler();
private:
bool do_init(uint16_t width, uint16_t height, line_fun_t cb, void *cb_data, Mode mode, Pinout pinout);
RGB888 *palette;
RGB888 palette[PALETTE_SIZE];
uint8_t* frame_buffer_display;
uint8_t* frame_buffer_back;
@ -172,8 +154,5 @@ namespace pimoroni {
int line_bytes_per_pixel;
uint32_t* display_palette = nullptr;
line_fun_t callback = nullptr;
void *cb_data = nullptr;
};
}

View file

@ -1,15 +1,3 @@
add_executable(
otf
otf.cpp
)
# Pull in pico libraries that we need
target_link_libraries(otf pico_stdlib pico_multicore pico_dvhstx)
pico_enable_stdio_usb(otf 1)
# create map/bin/hex file etc.
pico_add_extra_outputs(otf)
add_executable(
mandelbrot
mandelbrot.cpp

View file

@ -105,7 +105,7 @@ void draw_mandel() {
}
int main() {
display.init(FRAME_WIDTH, FRAME_HEIGHT, DVHSTX::MODE_PALETTE, {13, 15, 17, 19});
display.init(FRAME_WIDTH, FRAME_HEIGHT, DVHSTX::MODE_PALETTE);
stdio_init_all();

View file

@ -1,53 +0,0 @@
#include <stdio.h>
#include "hardware/uart.h"
#include "pico/multicore.h"
#include "drivers/dvhstx/dvhstx.hpp"
#include "libraries/pico_graphics/pico_graphics_dvhstx.hpp"
extern "C" {
#include "mandelf.h"
}
using namespace pimoroni;
#define FRAME_WIDTH 640
#define FRAME_HEIGHT 240
static DVHSTX display;
static PicoGraphics_PenDVHSTX_P8 graphics(FRAME_WIDTH, FRAME_HEIGHT, display);
inline constexpr uint32_t RGB_to_RGB888(const uint8_t r, const uint8_t g, const uint8_t b) {
return ((uint32_t)r << 16) | ((uint32_t)g << 8) | b;
}
static uint32_t palette[256];
static void init_palette() {
for (int i = 0; i < 256; ++i) {
#if 0
int h = i * (1.f / 255.f), s = 1.0f, v = 0.5f + (i & 7) * (0.5f / 7.f);
RGB p = RGB::from_hsv(h, s, v);
palette[i] = RGB_to_RGB888(p.r, p.g, p.b);
#endif
palette[i] = RGB_to_RGB888(i, i, i);
}
}
void gen_line(void *cb_data, int line_num, uint32_t *dest) {
int y1 = line_num - FRAME_HEIGHT / 2;
int ysq = y1*y1 * 4;
for(int h=0; h<FRAME_WIDTH; h++) {
int x = h - FRAME_WIDTH / 2;
int r2 = x*x + ysq;
#define LIM (320*320)
*dest++ = palette[r2 / 256 % 256];
}
}
int main() {
display.init(FRAME_WIDTH, FRAME_HEIGHT, gen_line, &display, {13, 15, 17, 19});
init_palette();
while(true) {
}
}