Implement reset
This commit is contained in:
parent
6b2e2ef5cc
commit
58dba1f0bf
4 changed files with 73 additions and 16 deletions
2
.github/workflows/micropython.yml
vendored
2
.github/workflows/micropython.yml
vendored
|
|
@ -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: |
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue