Implement reset

This commit is contained in:
Mike Bell 2024-10-13 19:51:22 +01:00
parent 6b2e2ef5cc
commit 58dba1f0bf
4 changed files with 73 additions and 16 deletions

View file

@ -62,7 +62,7 @@ jobs:
- name: Install Arm GNU Toolchain (arm-none-eabi-gcc) - name: Install Arm GNU Toolchain (arm-none-eabi-gcc)
uses: carlosperate/arm-none-eabi-gcc-action@v1 uses: carlosperate/arm-none-eabi-gcc-action@v1
with: with:
release: '9-2020-q2' release: '13.3.Rel1'
- name: "CCache: Install" - name: "CCache: Install"
run: | run: |

View file

@ -70,7 +70,7 @@ static inline __attribute__((always_inline)) uint32_t render_char_line(int c, in
// Lists are padded with NOPs to be >= HSTX FIFO size, to avoid DMA rapidly // Lists are padded with NOPs to be >= HSTX FIFO size, to avoid DMA rapidly
// pingponging and tripping up the IRQs. // pingponging and tripping up the IRQs.
static uint32_t vblank_line_vsync_off[] = { static const uint32_t vblank_line_vsync_off_src[] = {
HSTX_CMD_RAW_REPEAT, HSTX_CMD_RAW_REPEAT,
SYNC_V1_H1, SYNC_V1_H1,
HSTX_CMD_RAW_REPEAT, HSTX_CMD_RAW_REPEAT,
@ -78,8 +78,9 @@ static uint32_t vblank_line_vsync_off[] = {
HSTX_CMD_RAW_REPEAT, HSTX_CMD_RAW_REPEAT,
SYNC_V1_H1 SYNC_V1_H1
}; };
static uint32_t vblank_line_vsync_off[count_of(vblank_line_vsync_off_src)];
static uint32_t vblank_line_vsync_on[] = { static const uint32_t vblank_line_vsync_on_src[] = {
HSTX_CMD_RAW_REPEAT, HSTX_CMD_RAW_REPEAT,
SYNC_V0_H1, SYNC_V0_H1,
HSTX_CMD_RAW_REPEAT, HSTX_CMD_RAW_REPEAT,
@ -87,8 +88,9 @@ static uint32_t vblank_line_vsync_on[] = {
HSTX_CMD_RAW_REPEAT, HSTX_CMD_RAW_REPEAT,
SYNC_V0_H1 SYNC_V0_H1
}; };
static uint32_t vblank_line_vsync_on[count_of(vblank_line_vsync_on_src)];
static uint32_t vactive_line_header[] = { static const uint32_t vactive_line_header_src[] = {
HSTX_CMD_RAW_REPEAT, HSTX_CMD_RAW_REPEAT,
SYNC_V1_H1, SYNC_V1_H1,
HSTX_CMD_RAW_REPEAT, HSTX_CMD_RAW_REPEAT,
@ -97,8 +99,9 @@ static uint32_t vactive_line_header[] = {
SYNC_V1_H1, SYNC_V1_H1,
HSTX_CMD_TMDS HSTX_CMD_TMDS
}; };
static uint32_t vactive_line_header[count_of(vactive_line_header_src)];
static uint32_t vactive_text_line_header[] = { static const uint32_t vactive_text_line_header_src[] = {
HSTX_CMD_RAW_REPEAT, HSTX_CMD_RAW_REPEAT,
SYNC_V1_H1, SYNC_V1_H1,
HSTX_CMD_RAW_REPEAT, HSTX_CMD_RAW_REPEAT,
@ -114,6 +117,7 @@ static uint32_t vactive_text_line_header[] = {
BLACK_PIXEL_B, BLACK_PIXEL_B,
HSTX_CMD_TMDS HSTX_CMD_TMDS
}; };
static uint32_t vactive_text_line_header[count_of(vactive_text_line_header_src)];
#define NUM_FRAME_LINES 2 #define NUM_FRAME_LINES 2
#define NUM_CHANS 3 #define NUM_CHANS 3
@ -572,8 +576,21 @@ void DVHSTX::clear()
memset(frame_buffer_back, 0, frame_width * frame_height * frame_bytes_per_pixel); memset(frame_buffer_back, 0, frame_width * frame_height * frame_bytes_per_pixel);
} }
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 DVHSTX::init(uint16_t width, uint16_t height, Mode mode_)
{ {
if (inited) reset();
ch_num = 0;
line_num = -1;
v_scanline = 2;
flip_next = false;
display_width = width; display_width = width;
display_height = height; display_height = height;
frame_width = width; frame_width = width;
@ -646,7 +663,7 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_)
} }
if (!timing_mode) { if (!timing_mode) {
printf("Unsupported resolution %dx%d", width, height); dvhstx_debug("Unsupported resolution %dx%d", width, height);
return false; return false;
} }
@ -666,19 +683,23 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_)
v_repeat = 1 << v_repeat_shift; v_repeat = 1 << v_repeat_shift;
h_repeat = 1 << h_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[0] |= timing_mode->h_front_porch;
vblank_line_vsync_off[2] |= timing_mode->h_sync_width; vblank_line_vsync_off[2] |= timing_mode->h_sync_width;
vblank_line_vsync_off[4] |= timing_mode->h_back_porch + timing_mode->h_active_pixels; vblank_line_vsync_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[0] |= timing_mode->h_front_porch;
vblank_line_vsync_on[2] |= timing_mode->h_sync_width; 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; 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[0] |= timing_mode->h_front_porch;
vactive_line_header[2] |= timing_mode->h_sync_width; vactive_line_header[2] |= timing_mode->h_sync_width;
vactive_line_header[4] |= timing_mode->h_back_porch; vactive_line_header[4] |= timing_mode->h_back_porch;
vactive_line_header[6] |= timing_mode->h_active_pixels; 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[0] |= timing_mode->h_front_porch;
vactive_text_line_header[2] |= timing_mode->h_sync_width; vactive_text_line_header[2] |= timing_mode->h_sync_width;
vactive_text_line_header[4] |= timing_mode->h_back_porch; vactive_text_line_header[4] |= timing_mode->h_back_porch;
@ -706,7 +727,7 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_)
line_bytes_per_pixel = 14; line_bytes_per_pixel = 14;
break; break;
default: default:
printf("Unsupported mode %d", (int)mode); dvhstx_debug("Unsupported mode %d", (int)mode);
return false; return false;
} }
@ -752,6 +773,12 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_)
} }
} }
// 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) { switch (mode) {
case MODE_RGB565: case MODE_RGB565:
// Configure HSTX's TMDS encoder for RGB565 // Configure HSTX's TMDS encoder for RGB565
@ -830,7 +857,7 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_)
break; break;
default: default:
printf("Unsupported mode %d", (int)mode); dvhstx_debug("Unsupported mode %d", (int)mode);
return false; return false;
} }
@ -871,9 +898,6 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_)
dvhstx_debug("GPIO configured\n"); dvhstx_debug("GPIO configured\n");
// Always use the bottom channels
dma_claim_mask((1 << NUM_CHANS) - 1);
// The channels are set up identically, to transfer a whole scanline and // The channels are set up identically, to transfer a whole scanline and
// then chain to the next channel. Each time a channel finishes, we // then chain to the next channel. Each time a channel finishes, we
// reconfigure the one that just finished, meanwhile the other channel(s) // reconfigure the one that just finished, meanwhile the other channel(s)
@ -918,6 +942,7 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_)
dvhstx_debug("DMA channels claimed\n"); dvhstx_debug("DMA channels claimed\n");
dma_hw->intr = (1 << NUM_CHANS) - 1;
dma_hw->ints2 = (1 << NUM_CHANS) - 1; dma_hw->ints2 = (1 << NUM_CHANS) - 1;
dma_hw->inte2 = (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); if (is_text_mode) irq_set_exclusive_handler(DMA_IRQ_2, dma_irq_handler_text);
@ -934,9 +959,34 @@ bool DVHSTX::init(uint16_t width, uint16_t height, Mode mode_)
dvhstx_debug("Frame buffer filled\n"); dvhstx_debug("Frame buffer filled\n");
inited = true;
return 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);
#ifndef MICROPY_BUILD_TYPE
free(frame_buffer_display);
free(frame_buffer_back);
#endif
}
void DVHSTX::flip_blocking() { void DVHSTX::flip_blocking() {
wait_for_vsync(); wait_for_vsync();
flip_now(); flip_now();

View file

@ -59,14 +59,12 @@ namespace pimoroni {
uint16_t frame_width = 320; uint16_t frame_width = 320;
uint16_t frame_height = 180; uint16_t frame_height = 180;
uint8_t frame_bytes_per_pixel = 2; uint8_t frame_bytes_per_pixel = 2;
uint8_t bank = 0;
uint8_t h_repeat = 4; uint8_t h_repeat = 4;
uint8_t v_repeat = 4; uint8_t v_repeat = 4;
Mode mode = MODE_RGB565; Mode mode = MODE_RGB565;
public: public:
DVHSTX() DVHSTX();
{}
//-------------------------------------------------- //--------------------------------------------------
// Methods // Methods
@ -95,6 +93,7 @@ namespace pimoroni {
void clear(); void clear();
bool init(uint16_t width, uint16_t height, Mode mode = MODE_RGB565); bool init(uint16_t width, uint16_t height, Mode mode = MODE_RGB565);
void reset();
// Wait for vsync and then flip the buffers // Wait for vsync and then flip the buffers
void flip_blocking(); void flip_blocking();
@ -118,7 +117,7 @@ namespace pimoroni {
uint8_t* frame_buffer_display; uint8_t* frame_buffer_display;
uint8_t* frame_buffer_back; uint8_t* frame_buffer_back;
uint32_t* font_cache; uint32_t* font_cache = nullptr;
uint16_t* point_to_ptr16(const Point &p) const { uint16_t* point_to_ptr16(const Point &p) const {
return ((uint16_t*)frame_buffer_back) + (p.y * (uint32_t)frame_width) + p.x; return ((uint16_t*)frame_buffer_back) + (p.y * (uint32_t)frame_width) + p.x;
@ -143,6 +142,8 @@ namespace pimoroni {
volatile int v_scanline = 2; volatile int v_scanline = 2;
volatile bool flip_next; volatile bool flip_next;
bool inited = false;
uint32_t* line_buffers; uint32_t* line_buffers;
const struct dvi_timing* timing_mode; const struct dvi_timing* timing_mode;
int v_inactive_total; int v_inactive_total;

View file

@ -123,7 +123,13 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
} }
mp_obj_t ModPicoGraphics__del__(mp_obj_t self_in) { mp_obj_t ModPicoGraphics__del__(mp_obj_t self_in) {
//dv_display.reset(); ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t);
dv_display.reset();
if (self->graphics) {
m_del_class(PicoGraphicsDVHSTX, self->graphics);
self->graphics = nullptr;
}
return mp_const_none; return mp_const_none;
} }