got it working, just a small bug left
This commit is contained in:
parent
4ade3a5f00
commit
f3a619decc
7 changed files with 356 additions and 178 deletions
|
@ -43,8 +43,8 @@ tft_driver_ili9341::init(uint8_t *dma_buf, size_t dma_sz)
|
|||
SpiHandle::Result res;
|
||||
|
||||
dcx_pin = daisy::seed::D12; // Pin(PORTB, 8);
|
||||
dcx.Init(dcx_pin, GPIO::Mode::OUTPUT, GPIO::Pull::PULLUP,
|
||||
GPIO::Speed::VERY_HIGH);
|
||||
dcx.Init(dcx_pin, GPIO::Mode::OUTPUT, GPIO::Pull::NOPULL,
|
||||
GPIO::Speed::HIGH);
|
||||
|
||||
spi_conf.datasize = 8;
|
||||
|
||||
|
@ -79,7 +79,9 @@ tft_driver_ili9341::init(uint8_t *dma_buf, size_t dma_sz)
|
|||
|
||||
_async_dma_buf = dma_buf;
|
||||
_async_dma_sz = dma_sz;
|
||||
_async_stat = async_status::READY;
|
||||
_async_curr_rd = _async_curr_wr = (tft_dma_cmd *)dma_buf;
|
||||
_async_id = 0;
|
||||
_async_stat = async_status::INIT;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -113,31 +115,81 @@ tft_driver_ili9341::async_on_finish(async_on_finish_f cb, void *ctx)
|
|||
}
|
||||
|
||||
int
|
||||
tft_driver_ili9341::async_start(void)
|
||||
tft_driver_ili9341::async_ready(void)
|
||||
{
|
||||
if (_async_stat != async_status::READY &&
|
||||
_async_stat != async_status::DONE)
|
||||
async_status stat;
|
||||
|
||||
stat = (async_status)_async_stat;
|
||||
switch (stat) {
|
||||
case async_status::INIT:
|
||||
case async_status::DONE:
|
||||
if (_async_cb_fun == NULL ||
|
||||
_async_cb_ctx == NULL ||
|
||||
_async_id < 0)
|
||||
return (-1);
|
||||
_async_stat = async_status::READY;
|
||||
|
||||
__attribute__((fallthrough));
|
||||
case async_status::READY:
|
||||
return (0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int
|
||||
tft_driver_ili9341::dma_buf_reset(void)
|
||||
{
|
||||
async_status stat;
|
||||
tft_dma_cmd *cmd;
|
||||
|
||||
if (dma_buf_sz_tx_pend() > 0)
|
||||
return (-1);
|
||||
|
||||
if (_async_cb_fun == NULL)
|
||||
stat = _async_stat;
|
||||
switch (stat) {
|
||||
case async_status::INIT:
|
||||
case async_status::TX_NONE:
|
||||
case async_status::TX_ACTIVE:
|
||||
return (-1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
_async_curr_wr = (tft_dma_cmd *)_async_dma_buf;
|
||||
_async_curr_rd = _async_curr_wr;
|
||||
cmd = (tft_dma_cmd *)_async_dma_buf;
|
||||
cmd->size = 0;
|
||||
|
||||
_async_curr_wr->size = 0;
|
||||
|
||||
_async_wr = async_wr::START;
|
||||
_async_stat = async_status::NO_TX;
|
||||
_async_curr_wr = cmd;
|
||||
_async_curr_rd = cmd;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
tft_driver_ili9341::async_start(void)
|
||||
{
|
||||
if (async_ready() == -1)
|
||||
return (-1);
|
||||
|
||||
if (dma_buf_reset() == -1)
|
||||
return (-1);
|
||||
|
||||
_async_wr = async_wr::START;
|
||||
_async_stat = async_status::TX_NONE;
|
||||
|
||||
return (async_id());
|
||||
}
|
||||
|
||||
int
|
||||
tft_driver_ili9341::async_end(void)
|
||||
{
|
||||
_async_wr = async_wr::END;
|
||||
async_id_next();
|
||||
|
||||
async_flush();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -147,57 +199,103 @@ tft_driver_ili9341::async_stat(void)
|
|||
return (_async_stat);
|
||||
}
|
||||
|
||||
void
|
||||
tft_driver_ili9341::async_finalize(void)
|
||||
{
|
||||
AC_PRECOND(_async_cb_fun != NULL && _async_cb_ctx != NULL);
|
||||
AC_PRECOND(_async_stat == async_status::TX_NONE ||
|
||||
_async_stat == async_status::TX_INACTIVE ||
|
||||
_async_stat == async_status::TX_ACTIVE);
|
||||
AC_PRECOND(_async_wr == async_wr::END);
|
||||
AC_PRECOND(dma_buf_sz_tx_pend() == 0);
|
||||
|
||||
_async_stat = async_status::DONE;
|
||||
_async_cb_fun((void *)_async_cb_ctx);
|
||||
}
|
||||
|
||||
void
|
||||
tft_driver_ili9341::async_flush(void)
|
||||
{
|
||||
async_tx();
|
||||
}
|
||||
async_status stat;
|
||||
async_wr wr;
|
||||
|
||||
int
|
||||
tft_driver_ili9341::async_hline_row_bg_fill(tft_color *bg, tft_color *fg,
|
||||
uint16_t hline_idx_st, uint16_t hline_idx_end, uint16_t row_idx)
|
||||
{
|
||||
if (render_dma_buf_hline_row_bg_fill(bg, fg, hline_idx_st,
|
||||
hline_idx_end, row_idx) != 0) {
|
||||
return (-1);
|
||||
stat = _async_stat;
|
||||
wr = _async_wr;
|
||||
|
||||
switch (stat) {
|
||||
case async_status::TX_NONE:
|
||||
case async_status::TX_INACTIVE:
|
||||
if (dma_buf_sz_tx_pend() > 0) {
|
||||
async_tx();
|
||||
return;
|
||||
}
|
||||
if (wr == async_wr::END) {
|
||||
async_finalize();
|
||||
return;
|
||||
}
|
||||
dma_buf_reset();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
async_tx_try();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define TFT_ASYNC_TRY_TX_MIN 4096
|
||||
#define TFT_ASYNC_TRY_TX_MIN 2048
|
||||
void
|
||||
tft_driver_ili9341::async_tx_try(void)
|
||||
{
|
||||
if (dma_buf_sz_tx_pend() > TFT_ASYNC_TRY_TX_MIN)
|
||||
if (dma_buf_sz_tx_pend() < (_async_dma_sz / 2))
|
||||
return;
|
||||
|
||||
async_tx();
|
||||
async_flush();
|
||||
}
|
||||
|
||||
void
|
||||
tft_driver_ili9341::async_tx(void)
|
||||
{
|
||||
if (_async_wr == async_wr::END && _async_stat == async_status::NO_TX &&
|
||||
dma_buf_sz_tx_pend() == 0) {
|
||||
_async_stat = async_status::DONE;
|
||||
_async_cb_fun((void *)_async_cb_ctx);
|
||||
return;
|
||||
}
|
||||
async_status stat;
|
||||
|
||||
if (_async_stat != async_status::NO_TX)
|
||||
return;
|
||||
stat = _async_stat;
|
||||
|
||||
AC_ASSERT(stat == async_status::TX_NONE ||
|
||||
stat == async_status::TX_INACTIVE);
|
||||
AC_ASSERT(dma_buf_sz_tx_pend() > sizeof(tft_dma_cmd));
|
||||
AC_ASSERT(_async_curr_rd->size > 0);
|
||||
|
||||
_async_stat = async_status::TX;
|
||||
_async_stat = async_status::TX_ACTIVE;
|
||||
|
||||
async_send_raw((const uint8_t *)_async_curr_rd->buf, 1,
|
||||
async_tx_cmd_scb, async_tx_cmd_ecb, this);
|
||||
}
|
||||
|
||||
/* ret < 0: if error
|
||||
* ret = 0: if success
|
||||
* ret > 0: need reentrant call, ret == async_id that should be used in next
|
||||
* call
|
||||
*/
|
||||
int
|
||||
tft_driver_ili9341::async_hline_row_bg_fill(int id, tft_color *bg,
|
||||
tft_color *fg, uint16_t hline_idx_st, uint16_t hline_idx_end,
|
||||
uint16_t row_idx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (id != _async_id)
|
||||
return (-1);
|
||||
|
||||
ret = render_dma_buf_hline_row_bg_fill(bg, fg, hline_idx_st,
|
||||
hline_idx_end, row_idx);
|
||||
if (ret < 0)
|
||||
return (ret);
|
||||
|
||||
if (ret > 0)
|
||||
async_flush();
|
||||
async_tx_try();
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
tft_driver_ili9341::async_tx_cmd_scb(void *ctx)
|
||||
{
|
||||
|
@ -205,7 +303,7 @@ tft_driver_ili9341::async_tx_cmd_scb(void *ctx)
|
|||
|
||||
tft = (tft_driver_ili9341 *)ctx;
|
||||
|
||||
AC_ASSERT(tft->_async_stat == async_status::TX);
|
||||
AC_ASSERT(tft->_async_stat == async_status::TX_ACTIVE);
|
||||
|
||||
tft->dcx_low();
|
||||
}
|
||||
|
@ -219,6 +317,8 @@ tft_driver_ili9341::async_tx_cmd_ecb(void *ctx, SpiHandle::Result res)
|
|||
tft = (tft_driver_ili9341 *)ctx;
|
||||
cmd = tft->dma_buf_curr_rd();
|
||||
|
||||
AC_ASSERT(tft->_async_stat == async_status::TX_ACTIVE);
|
||||
|
||||
tft->async_send_raw(&cmd->buf[1], cmd->size, async_tx_param_scb,
|
||||
async_tx_param_ecb, tft);
|
||||
}
|
||||
|
@ -229,6 +329,9 @@ tft_driver_ili9341::async_tx_param_scb(void *ctx)
|
|||
tft_driver_ili9341 *tft;
|
||||
|
||||
tft = (tft_driver_ili9341 *)ctx;
|
||||
|
||||
AC_ASSERT(tft->_async_stat == async_status::TX_ACTIVE);
|
||||
|
||||
tft->dcx_high();
|
||||
}
|
||||
|
||||
|
@ -240,20 +343,23 @@ tft_driver_ili9341::async_tx_param_ecb(void *ctx, SpiHandle::Result res)
|
|||
|
||||
|
||||
tft = (tft_driver_ili9341 *)ctx;
|
||||
|
||||
AC_PRECOND(tft->_async_stat == async_status::TX_ACTIVE);
|
||||
|
||||
cmd = tft->dma_buf_next_rd();
|
||||
|
||||
AUDIOC_ASSERT(tft->async_stat() == async_status::TX);
|
||||
|
||||
if (cmd->size == 0) {
|
||||
tft->_async_stat = async_status::NO_TX;
|
||||
if (tft->dma_buf_sz_tx_pend() == 0 &&
|
||||
tft->_async_wr == async_wr::END) {
|
||||
tft->_async_stat = async_status::DONE;
|
||||
tft->_async_cb_fun((void *)tft->_async_cb_ctx);
|
||||
if (tft->_async_wr == async_wr::END) {
|
||||
AC_ASSERT(tft->dma_buf_sz_tx_pend() == 0);
|
||||
tft->async_finalize();
|
||||
} else {
|
||||
tft->_async_stat = async_status::TX_INACTIVE;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
AC_ASSERT(tft->dma_buf_sz_tx_pend() > sizeof(tft_dma_cmd));
|
||||
|
||||
tft->async_send_raw(cmd->buf, 1, async_tx_cmd_scb, async_tx_cmd_ecb,
|
||||
tft);
|
||||
}
|
||||
|
@ -270,9 +376,8 @@ tft_driver_ili9341::dma_buf_sz_used(void)
|
|||
{
|
||||
size_t buf_fill;
|
||||
|
||||
buf_fill = (size_t)((uint8_t *)_async_curr_wr - _async_dma_buf);
|
||||
if (_async_curr_wr->size > 0)
|
||||
buf_fill += sizeof(tft_dma_cmd) + _async_curr_wr->size;
|
||||
buf_fill = (size_t)((uint8_t *)_async_curr_wr - _async_dma_buf) +
|
||||
sizeof(tft_dma_cmd);
|
||||
|
||||
return (buf_fill);
|
||||
}
|
||||
|
@ -284,19 +389,28 @@ tft_driver_ili9341::dma_buf_curr_wr(void)
|
|||
}
|
||||
|
||||
tft_dma_cmd *
|
||||
tft_driver_ili9341::dma_buf_next_wr(void)
|
||||
tft_driver_ili9341::dma_buf_next_wr(size_t curr_sz)
|
||||
{
|
||||
size_t sz;
|
||||
uint8_t *bytes;
|
||||
tft_dma_cmd *tmp;
|
||||
size_t tot_sz;
|
||||
volatile tft_dma_cmd *curr, *next;
|
||||
volatile uint8_t *bytes;
|
||||
|
||||
sz = sizeof(tft_dma_cmd) + _async_curr_wr->size;
|
||||
bytes = (uint8_t *)_async_curr_wr;
|
||||
AC_PRECOND(_async_dma_sz - dma_buf_sz_used() >=
|
||||
curr_sz + sizeof(tft_dma_cmd));
|
||||
|
||||
tmp = (tft_dma_cmd *)&bytes[sz];
|
||||
tmp->size = 0;
|
||||
curr = (volatile tft_dma_cmd *)_async_curr_wr;
|
||||
tot_sz = sizeof(*curr) + curr_sz;
|
||||
|
||||
return ((tft_dma_cmd *)(_async_curr_wr = tmp));
|
||||
bytes = (volatile uint8_t *)curr;
|
||||
bytes += tot_sz;
|
||||
|
||||
next = (volatile tft_dma_cmd *)bytes;
|
||||
next->size = 0;
|
||||
|
||||
curr->size = curr_sz;
|
||||
|
||||
_async_curr_wr = next;
|
||||
return ((tft_dma_cmd *)next);
|
||||
}
|
||||
|
||||
const tft_dma_cmd *
|
||||
|
@ -309,18 +423,26 @@ const tft_dma_cmd *
|
|||
tft_driver_ili9341::dma_buf_next_rd(void)
|
||||
{
|
||||
size_t sz;
|
||||
uint8_t *bytes;
|
||||
volatile const tft_dma_cmd *cmd;
|
||||
volatile const uint8_t *bytes;
|
||||
|
||||
sz = sizeof(tft_dma_cmd) + _async_curr_rd->size;
|
||||
bytes = (uint8_t *)_async_curr_rd;
|
||||
|
||||
return ((const tft_dma_cmd *)
|
||||
(_async_curr_rd = (tft_dma_cmd *)&bytes[sz]));
|
||||
cmd = (volatile const tft_dma_cmd *)_async_curr_rd;
|
||||
sz = sizeof(*cmd) + cmd->size;
|
||||
|
||||
bytes = (volatile const uint8_t *)cmd;
|
||||
bytes += sz;
|
||||
|
||||
cmd = (volatile const tft_dma_cmd *)bytes;
|
||||
_async_curr_rd = cmd;
|
||||
|
||||
return ((const tft_dma_cmd *)cmd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#define SET_ADDR_WINDOW_SZ (sizeof(tft_dma_cmd) + 5 + \
|
||||
sizeof(tft_dma_cmd) + 5)
|
||||
int
|
||||
tft_driver_ili9341::render_dma_buf_set_addr_window(uint16_t col_st,
|
||||
uint16_t col_end, uint16_t row_st, uint16_t row_end)
|
||||
|
@ -328,9 +450,8 @@ tft_driver_ili9341::render_dma_buf_set_addr_window(uint16_t col_st,
|
|||
size_t n;
|
||||
tft_dma_cmd *cmd;
|
||||
|
||||
if (_async_dma_sz - dma_buf_sz_used() <
|
||||
2 * (sizeof(tft_dma_cmd) + sizeof(uint8_t) + 2 * sizeof(uint16_t)))
|
||||
return (-1);
|
||||
if (_async_dma_sz - dma_buf_sz_used() < SET_ADDR_WINDOW_SZ)
|
||||
return (1);
|
||||
|
||||
cmd = dma_buf_curr_wr();
|
||||
|
||||
|
@ -341,9 +462,7 @@ tft_driver_ili9341::render_dma_buf_set_addr_window(uint16_t col_st,
|
|||
cmd->buf[n++] = (uint8_t)((col_end >> 8) & 0xff);
|
||||
cmd->buf[n++] = (uint8_t)(col_end & 0xff);
|
||||
|
||||
cmd->size = n;
|
||||
|
||||
cmd = dma_buf_next_wr();
|
||||
cmd = dma_buf_next_wr(n);
|
||||
|
||||
n = 0;
|
||||
cmd->buf[n++] = ILI9341_PASET;
|
||||
|
@ -352,13 +471,12 @@ tft_driver_ili9341::render_dma_buf_set_addr_window(uint16_t col_st,
|
|||
cmd->buf[n++] = (uint8_t)((row_end >> 8) & 0xff);
|
||||
cmd->buf[n++] = (uint8_t)(row_end & 0xff);
|
||||
|
||||
cmd->size = n;
|
||||
|
||||
dma_buf_next_wr();
|
||||
dma_buf_next_wr(n);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define MEMWR_SZ(num) (sizeof(tft_dma_cmd) + 1 + (num) * sizeof(uint16_t))
|
||||
int
|
||||
tft_driver_ili9341::render_dma_buf_memwr(const tft_color *col, size_t num)
|
||||
{
|
||||
|
@ -366,9 +484,8 @@ tft_driver_ili9341::render_dma_buf_memwr(const tft_color *col, size_t num)
|
|||
uint16_t c16;
|
||||
tft_dma_cmd *cmd;
|
||||
|
||||
if (_async_dma_sz - dma_buf_sz_used() <
|
||||
sizeof(tft_dma_cmd) + sizeof(uint8_t) + num * sizeof(uint16_t))
|
||||
return (-1);
|
||||
if (_async_dma_sz - dma_buf_sz_used() < MEMWR_SZ(num))
|
||||
return (1);
|
||||
|
||||
cmd = dma_buf_curr_wr();
|
||||
|
||||
|
@ -380,13 +497,12 @@ tft_driver_ili9341::render_dma_buf_memwr(const tft_color *col, size_t num)
|
|||
cmd->buf[i++] = (uint8_t)(c16 & 0xff);
|
||||
}
|
||||
|
||||
cmd->size = i;
|
||||
|
||||
dma_buf_next_wr();
|
||||
dma_buf_next_wr(i);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#define MEMWR_CONT_SZ(num) MEMWR_SZ(num)
|
||||
int
|
||||
tft_driver_ili9341::render_dma_buf_memwr_cont(const tft_color *col, size_t num)
|
||||
{
|
||||
|
@ -394,9 +510,9 @@ tft_driver_ili9341::render_dma_buf_memwr_cont(const tft_color *col, size_t num)
|
|||
uint16_t c16;
|
||||
tft_dma_cmd *cmd;
|
||||
|
||||
if (_async_dma_sz - dma_buf_sz_used() <
|
||||
sizeof(tft_dma_cmd) + sizeof(uint8_t) + num * sizeof(uint16_t))
|
||||
return (-1);
|
||||
if (_async_dma_sz - dma_buf_sz_used() < MEMWR_CONT_SZ(num)) {
|
||||
return (1);
|
||||
}
|
||||
|
||||
cmd = dma_buf_curr_wr();
|
||||
|
||||
|
@ -408,43 +524,60 @@ tft_driver_ili9341::render_dma_buf_memwr_cont(const tft_color *col, size_t num)
|
|||
cmd->buf[i++] = (uint8_t)(c16 & 0xff);
|
||||
}
|
||||
|
||||
cmd->size = i;
|
||||
|
||||
dma_buf_next_wr();
|
||||
dma_buf_next_wr(i);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
tft_driver_ili9341::render_dma_buf_hline(const tft_color *c, uint16_t col_s,
|
||||
uint16_t col_e, uint16_t row)
|
||||
{
|
||||
if (render_dma_buf_set_addr_window(col_s, col_e, row, row + 1) == -1)
|
||||
return (-1);
|
||||
int ret;
|
||||
|
||||
if (render_dma_buf_memwr(c, (size_t)(col_e - col_s)) == -1)
|
||||
return (-1);
|
||||
AC_PRECOND(col_s <= col_e);
|
||||
|
||||
return (0);
|
||||
if (_async_dma_sz - dma_buf_sz_used() <
|
||||
SET_ADDR_WINDOW_SZ + MEMWR_SZ(col_e - col_s))
|
||||
return (1);
|
||||
|
||||
ret = render_dma_buf_set_addr_window(col_s, col_e, row, row + 1);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
ret = render_dma_buf_memwr(c, (size_t)(col_e - col_s));
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int
|
||||
tft_driver_ili9341::render_dma_buf_hline_row_bg_fill(const tft_color *bg,
|
||||
const tft_color *fg, uint16_t col_s, uint16_t col_e, uint16_t row)
|
||||
{
|
||||
if (col_e < col_s || width() < col_e)
|
||||
return (-1);
|
||||
int ret;
|
||||
|
||||
if (render_dma_buf_set_addr_window(0, width(), row, row+1) == -1)
|
||||
return (-1);
|
||||
AC_PRECOND(col_s <= col_s && col_e <= width());
|
||||
|
||||
if (render_dma_buf_memwr(bg, (size_t)col_s) == -1)
|
||||
return (-1);
|
||||
if (render_dma_buf_memwr_cont(fg, (size_t)(col_e - col_s)) == -1)
|
||||
return (-1);
|
||||
if (render_dma_buf_memwr_cont(bg, (size_t)(width() - col_e)) == -1)
|
||||
return (-1);
|
||||
if (_async_dma_sz - dma_buf_sz_used() <
|
||||
SET_ADDR_WINDOW_SZ + MEMWR_SZ(col_s) + MEMWR_CONT_SZ(col_e - col_s))
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
ret = render_dma_buf_set_addr_window(0, width(), row, row+1);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
ret = render_dma_buf_memwr(bg, (size_t)col_s);
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
ret = render_dma_buf_memwr_cont(fg, (size_t)(col_e - col_s));
|
||||
if (ret != 0)
|
||||
return (ret);
|
||||
|
||||
ret = render_dma_buf_memwr_cont(bg, (size_t)(width() - col_e));
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#define TFT_N_PIXELS (ILI9341_TFTWIDTH * ILI9341_TFTHEIGHT)
|
||||
|
@ -517,8 +650,8 @@ tft_driver_ili9341::send_raw_sync(const uint8_t *buf, size_t len)
|
|||
SpiHandle::Result res;
|
||||
|
||||
res = SpiHandle::Result::OK;
|
||||
for (block_st = 0; block_st < len; block_st += block_sz()) {
|
||||
transfer_sz = std::min(block_sz(), len - block_st);
|
||||
for (block_st = 0; block_st < len; block_st += TFT_BLOCK_SZ) {
|
||||
transfer_sz = std::min(TFT_BLOCK_SZ, len - block_st);
|
||||
res = spi.BlockingTransmit((uint8_t *)&buf[block_st],
|
||||
transfer_sz);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue