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
|
@ -1,15 +1,25 @@
|
|||
#ifndef _AUDIOC_HPP
|
||||
#define _AUDIOC_HPP
|
||||
|
||||
#include "daisy_seed.h"
|
||||
|
||||
#define AUDIOC_LOG (daisy_hw.PrintLine)
|
||||
extern daisy::DaisySeed daisy_hw;
|
||||
|
||||
#define AUDIOC_DEBUG
|
||||
|
||||
#ifdef AUDIOC_DEBUG
|
||||
|
||||
#define AUDIOC_DBG_IND() (daisy_hw.SetLed(true))
|
||||
#define AUDIOC_DBG_BRK() __asm("BKPT 234")
|
||||
|
||||
#define AUDIOC_PRECOND(cond) \
|
||||
do { \
|
||||
if (! (cond)) { \
|
||||
AUDIOC_LOG("AC_PRECOND(" #cond ") @ %s: line %u failed\n", \
|
||||
__FILE__, __LINE__); \
|
||||
AUDIOC_DBG_IND(); \
|
||||
AUDIOC_DBG_BRK(); \
|
||||
} \
|
||||
} while (0)
|
||||
#define AUDIOC_POSTCOND(cond) \
|
||||
|
@ -17,6 +27,8 @@
|
|||
if (! (cond)) { \
|
||||
AUDIOC_LOG("AC_POSTCOND(" #cond ") @ %s: line %u failed\n", \
|
||||
__FILE__, __LINE__); \
|
||||
AUDIOC_DBG_IND(); \
|
||||
AUDIOC_DBG_BRK(); \
|
||||
} \
|
||||
} while (0)
|
||||
#define AUDIOC_ASSERT(cond) \
|
||||
|
@ -24,6 +36,8 @@
|
|||
if (! (cond)) { \
|
||||
AUDIOC_LOG("AC_ASSERT(" #cond ") @ %s: line %u failed\n", \
|
||||
__FILE__, __LINE__); \
|
||||
AUDIOC_DBG_IND(); \
|
||||
AUDIOC_DBG_BRK(); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
|
|
|
@ -309,47 +309,71 @@ int
|
|||
osclsk_scope::render_block(void)
|
||||
{
|
||||
int res;
|
||||
size_t render_idx;
|
||||
static int async_id;
|
||||
float block_norm;
|
||||
|
||||
float block_norm = 1.f;
|
||||
res = 0;
|
||||
switch (st) {
|
||||
case osc_state::SAMPLE_DONE:
|
||||
block_norm = 1.f;
|
||||
for (render_idx = 0; render_idx < OSCLSK_BLOCK_LEN;
|
||||
render_idx++) {
|
||||
block_norm = std::max(
|
||||
std::abs(block_y_max[render_idx]),
|
||||
block_norm
|
||||
);
|
||||
block_norm = std::max(
|
||||
std::abs(block_y_min[render_idx]),
|
||||
block_norm
|
||||
);
|
||||
}
|
||||
for (render_idx = 0; render_idx < OSCLSK_BLOCK_LEN;
|
||||
render_idx++) {
|
||||
block_y_max[render_idx] =
|
||||
block_y_max[render_idx] / block_norm;
|
||||
block_y_min[render_idx] =
|
||||
block_y_min[render_idx] / block_norm;
|
||||
}
|
||||
for (render_idx = 0; render_idx < OSCLSK_BLOCK_LEN;
|
||||
render_idx++) {
|
||||
screen_px_y_max[render_idx] = 1u + (uint16_t)(
|
||||
OSCLSK_Y_MAX_PX * (.5f + block_y_max[render_idx])
|
||||
);
|
||||
screen_px_y_min[render_idx] = (uint16_t)(
|
||||
OSCLSK_Y_MAX_PX * (.5f + block_y_min[render_idx])
|
||||
);
|
||||
}
|
||||
|
||||
if (st != osc_state::SAMPLE_DONE)
|
||||
return (-1);
|
||||
tft.async_on_finish(render_finish_tft_cb, this);
|
||||
|
||||
st = osc_state::RENDER;
|
||||
res = tft.async_start();
|
||||
AC_ASSERT(res >= 0);
|
||||
if (res < 0)
|
||||
return (-1);
|
||||
|
||||
for (render_idx = 0; render_idx < OSCLSK_BLOCK_LEN; render_idx++) {
|
||||
block_norm = std::max( std::abs(block_y_max[render_idx]),
|
||||
block_norm);
|
||||
block_norm = std::max( std::abs(block_y_min[render_idx]),
|
||||
block_norm);
|
||||
async_id = res;
|
||||
render_idx = 0;
|
||||
st = osc_state::RENDER;
|
||||
|
||||
__attribute__((fallthrough));
|
||||
case osc_state::RENDER:
|
||||
for (; render_idx < OSCLSK_BLOCK_LEN; render_idx++) {
|
||||
res = tft.async_hline_row_bg_fill(async_id, &bg, &fg,
|
||||
screen_px_y_min[render_idx],
|
||||
screen_px_y_max[render_idx],
|
||||
render_idx);
|
||||
if (res < 0)
|
||||
return (-1);
|
||||
if (res > 0)
|
||||
return (1);
|
||||
}
|
||||
tft.async_end();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (render_idx = 0; render_idx < OSCLSK_BLOCK_LEN; render_idx++) {
|
||||
block_y_max[render_idx] = block_y_max[render_idx] / block_norm;
|
||||
block_y_min[render_idx] = block_y_min[render_idx] / block_norm;
|
||||
}
|
||||
|
||||
for (render_idx = 0; render_idx < OSCLSK_BLOCK_LEN; render_idx++) {
|
||||
screen_px_y_max[render_idx] = 1u + (uint16_t)(
|
||||
OSCLSK_Y_MAX_PX * (.5f + block_y_max[render_idx]));
|
||||
screen_px_y_min[render_idx] = (uint16_t)(
|
||||
OSCLSK_Y_MAX_PX * (.5f + block_y_min[render_idx]));
|
||||
}
|
||||
|
||||
res = -1;
|
||||
tft.async_on_finish(render_finish_tft_cb, this);
|
||||
tft.async_start();
|
||||
for (render_idx = 0; render_idx < OSCLSK_BLOCK_LEN; render_idx++) {
|
||||
res = tft.async_hline_row_bg_fill(&bg, &fg,
|
||||
screen_px_y_min[render_idx], screen_px_y_max[render_idx],
|
||||
render_idx);
|
||||
if (res == -1)
|
||||
break;
|
||||
}
|
||||
tft.async_end();
|
||||
|
||||
return (res);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -79,6 +79,7 @@ struct osclsk_scope {
|
|||
|
||||
uint16_t screen_px_y_max[OSCLSK_SCREEN_XSZ];
|
||||
uint16_t screen_px_y_min[OSCLSK_SCREEN_XSZ];
|
||||
size_t render_idx;
|
||||
|
||||
osclsk_scope(void) : st(osc_state::INIT),
|
||||
block_fill(0), block_fill_nsamp(0),
|
||||
|
@ -87,7 +88,8 @@ struct osclsk_scope {
|
|||
trig_margin(.05f), trig_num(0),
|
||||
trig_num_req(2),
|
||||
trig_state(osc_trig_state::INIT),
|
||||
trig_mode(osc_trig_mode::RISING_EDGE) {};
|
||||
trig_mode(osc_trig_mode::RISING_EDGE),
|
||||
render_idx(0) {};
|
||||
|
||||
int init(uint8_t *dma_buf, size_t dma_sz);
|
||||
int init_block(void);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
using namespace daisy;
|
||||
using namespace daisysp;
|
||||
|
||||
#define DMA_AREA_SIZE (3*(1 << 16))
|
||||
#define DMA_AREA_SIZE (1 << 12)
|
||||
#define SCOPE_RING_BUF_SIZE 1024
|
||||
#define AUDIO_BLOCK_SIZE 2
|
||||
|
||||
|
@ -32,14 +32,14 @@ Switch kick, snare;
|
|||
|
||||
RingBuffer<float, SCOPE_RING_BUF_SIZE> scope_in;
|
||||
|
||||
static void
|
||||
void
|
||||
audio_cb(AudioHandle::InputBuffer in,
|
||||
AudioHandle::OutputBuffer out, size_t sz)
|
||||
{
|
||||
float osc_out, noise_out, snr_env_out, kck_env_out;
|
||||
float sig[AUDIO_BLOCK_SIZE];
|
||||
|
||||
load_meter.OnBlockStart();
|
||||
// load_meter.OnBlockStart();
|
||||
//Get rid of any bouncing
|
||||
snare.Debounce();
|
||||
kick.Debounce();
|
||||
|
@ -81,15 +81,15 @@ audio_cb(AudioHandle::InputBuffer in,
|
|||
sig[i] = .5 * noise_out + .5 * osc_out;
|
||||
}
|
||||
|
||||
/* write to output */
|
||||
for (size_t i = 0; i < sz; i++) {
|
||||
out[0][i] = sig[i];
|
||||
out[1][i] = sig[i];
|
||||
|
||||
}
|
||||
|
||||
scope_in.Overwrite(sig, sz);
|
||||
|
||||
load_meter.OnBlockEnd();
|
||||
// load_meter.OnBlockEnd();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -137,20 +137,20 @@ setup_drums(void)
|
|||
}
|
||||
|
||||
|
||||
#define LOAD_METER_TICKS (1 << 16)
|
||||
#define LOAD_METER_TICKS (1 << 20)
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
size_t read;
|
||||
float s[AUDIO_BLOCK_SIZE];
|
||||
int load_tick;
|
||||
uint32_t load_tick;
|
||||
daisy_hw.Configure();
|
||||
daisy_hw.Init();
|
||||
daisy_hw.StartLog(false); /* true = wait for usb connection */
|
||||
daisy_hw.SetAudioBlockSize(AUDIO_BLOCK_SIZE);
|
||||
|
||||
load_meter.Init(daisy_hw.AudioSampleRate(), daisy_hw.AudioBlockSize());
|
||||
load_tick = LOAD_METER_TICKS;
|
||||
//load_meter.Init(daisy_hw.AudioSampleRate(), daisy_hw.AudioBlockSize());
|
||||
//load_tick = LOAD_METER_TICKS;
|
||||
|
||||
if (scope.init(dma_area, sizeof(dma_area)) == -1)
|
||||
daisy_hw.PrintLine("scope.init failed");
|
||||
|
@ -175,6 +175,9 @@ main(void)
|
|||
case osclsk_scope::osc_state::SAMPLE_DONE:
|
||||
scope.render_block();
|
||||
break;
|
||||
case osclsk_scope::osc_state::RENDER:
|
||||
scope.render_block();
|
||||
break;
|
||||
case osclsk_scope::osc_state::RENDER_DONE:
|
||||
scope.prep();
|
||||
break;
|
||||
|
@ -185,18 +188,18 @@ main(void)
|
|||
break;
|
||||
}
|
||||
|
||||
if (--load_tick == 0) {
|
||||
load_tick = LOAD_METER_TICKS;
|
||||
// get the current load (smoothed value and peak values)
|
||||
const float avgLoad = load_meter.GetAvgCpuLoad();
|
||||
const float maxLoad = load_meter.GetMaxCpuLoad();
|
||||
const float minLoad = load_meter.GetMinCpuLoad();
|
||||
// print it to the serial connection (as percentages)
|
||||
daisy_hw.PrintLine("Processing Load %:");
|
||||
daisy_hw.PrintLine("Max: " FLT_FMT3, FLT_VAR3(maxLoad * 100.0f));
|
||||
daisy_hw.PrintLine("Avg: " FLT_FMT3, FLT_VAR3(avgLoad * 100.0f));
|
||||
daisy_hw.PrintLine("Min: " FLT_FMT3, FLT_VAR3(minLoad * 100.0f));
|
||||
}
|
||||
// if (--load_tick == 0) {
|
||||
// load_tick = LOAD_METER_TICKS;
|
||||
// // get the current load (smoothed value and peak values)
|
||||
// const float avgLoad = load_meter.GetAvgCpuLoad();
|
||||
// const float maxLoad = load_meter.GetMaxCpuLoad();
|
||||
// const float minLoad = load_meter.GetMinCpuLoad();
|
||||
// // print it to the serial connection (as percentages)
|
||||
// daisy_hw.PrintLine("Processing Load %:");
|
||||
// daisy_hw.PrintLine("Max: " FLT_FMT3, FLT_VAR3(maxLoad * 100.0f));
|
||||
// daisy_hw.PrintLine("Avg: " FLT_FMT3, FLT_VAR3(avgLoad * 100.0f));
|
||||
// daisy_hw.PrintLine("Min: " FLT_FMT3, FLT_VAR3(minLoad * 100.0f));
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,6 @@
|
|||
#define _SCOPE_HPP
|
||||
|
||||
#include "daisy_seed.h"
|
||||
|
||||
extern daisy::DaisySeed daisy_hw;
|
||||
|
||||
#define AUDIOC_LOG (daisy_hw.PrintLine)
|
||||
#include "audioc.hpp"
|
||||
|
||||
#endif /* _SCOPE_HPP */
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -157,8 +157,9 @@ struct tft_driver_ili9341 {
|
|||
enum class async_status {
|
||||
INIT,
|
||||
READY,
|
||||
TX,
|
||||
NO_TX,
|
||||
TX_NONE,
|
||||
TX_ACTIVE,
|
||||
TX_INACTIVE,
|
||||
DONE
|
||||
};
|
||||
|
||||
|
@ -176,8 +177,6 @@ struct tft_driver_ili9341 {
|
|||
SpiHandle spi;
|
||||
SpiHandle::Config spi_conf;
|
||||
|
||||
Logger<LOGGER_EXTERNAL> *lg;
|
||||
|
||||
Pin dcx_pin;
|
||||
GPIO dcx;
|
||||
|
||||
|
@ -186,6 +185,7 @@ struct tft_driver_ili9341 {
|
|||
volatile async_wr _async_wr;
|
||||
volatile async_on_finish_f _async_cb_fun;
|
||||
volatile void *_async_cb_ctx;
|
||||
int _async_id;
|
||||
|
||||
uint8_t *_async_dma_buf;
|
||||
size_t _async_dma_sz;
|
||||
|
@ -196,17 +196,11 @@ struct tft_driver_ili9341 {
|
|||
/* general */
|
||||
inline uint16_t width(void) { return (ILI9341_TFTWIDTH); }
|
||||
inline uint16_t height(void) { return (ILI9341_TFTHEIGHT); }
|
||||
inline size_t block_rows(void) {
|
||||
return (sizeof(tft_color) * height() /
|
||||
TFT_DRIVER_ILI9341_NBLOCKS);
|
||||
}
|
||||
inline size_t block_sz(void) {
|
||||
return (sizeof(tft_color) * width() * height() /
|
||||
TFT_DRIVER_ILI9341_NBLOCKS);
|
||||
}
|
||||
|
||||
tft_driver_ili9341(void) : _async_hint(async_hint::NONE),
|
||||
_async_stat(async_status::INIT), _async_wr(async_wr::END),
|
||||
_async_cb_fun(NULL), _async_cb_ctx(NULL),
|
||||
_async_id(-1),
|
||||
_async_dma_buf(NULL), _async_dma_sz(0),
|
||||
_async_curr_wr(NULL), _async_curr_rd(NULL) {};
|
||||
|
||||
|
@ -233,9 +227,19 @@ struct tft_driver_ili9341 {
|
|||
void async_flush(void);
|
||||
void async_tx(void);
|
||||
void async_tx_try(void);
|
||||
void async_finalize(void);
|
||||
|
||||
int async_ready(void);
|
||||
|
||||
inline int async_id(void) { return (_async_id); }
|
||||
inline int async_id_next(void) {
|
||||
_async_id++;
|
||||
_async_id &= 0xffff;
|
||||
return (_async_id);
|
||||
}
|
||||
|
||||
int async_cmd_hint(async_hint hint);
|
||||
int async_hline_row_bg_fill(tft_color *bg, tft_color *fg,
|
||||
int async_hline_row_bg_fill(int async_id, tft_color *bg, tft_color *fg,
|
||||
uint16_t hline_idx_st, uint16_t hline_idx_end, uint16_t row_idx);
|
||||
|
||||
static void async_tx_cmd_scb(void *ctx);
|
||||
|
@ -255,8 +259,10 @@ struct tft_driver_ili9341 {
|
|||
size_t dma_buf_sz_tx_pend(void);
|
||||
size_t dma_buf_sz_used(void);
|
||||
|
||||
int dma_buf_reset(void);
|
||||
|
||||
tft_dma_cmd *dma_buf_curr_wr(void);
|
||||
tft_dma_cmd *dma_buf_next_wr(void);
|
||||
tft_dma_cmd *dma_buf_next_wr(size_t curr_sz);
|
||||
|
||||
const tft_dma_cmd *dma_buf_curr_rd(void);
|
||||
const tft_dma_cmd *dma_buf_next_rd(void);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue