288 lines
8.4 KiB
C++
288 lines
8.4 KiB
C++
#ifndef _TFT_HPP
|
|
#define _TFT_HPP
|
|
|
|
#include "daisy.h"
|
|
|
|
#include "scope.hpp"
|
|
#include "audioc.hpp"
|
|
|
|
using namespace daisy;
|
|
|
|
#define ILI9341_TFTWIDTH 240 ///< ILI9341 max TFT width
|
|
#define ILI9341_TFTHEIGHT 320 ///< ILI9341 max TFT height
|
|
|
|
#define ILI9341_NOP 0x00 ///< No-op register
|
|
#define ILI9341_SWRESET 0x01 ///< Software reset register
|
|
#define ILI9341_RDDID 0x04 ///< Read display identification information
|
|
#define ILI9341_RDDST 0x09 ///< Read Display Status
|
|
|
|
#define ILI9341_SLPIN 0x10 ///< Enter Sleep Mode
|
|
#define ILI9341_SLPOUT 0x11 ///< Sleep Out
|
|
#define ILI9341_PTLON 0x12 ///< Partial Mode ON
|
|
#define ILI9341_NORON 0x13 ///< Normal Display Mode ON
|
|
|
|
#define ILI9341_RDMODE 0x0A ///< Read Display Power Mode
|
|
#define ILI9341_RDMADCTL 0x0B ///< Read Display MADCTL
|
|
#define ILI9341_RDPIXFMT 0x0C ///< Read Display Pixel Format
|
|
#define ILI9341_RDIMGFMT 0x0D ///< Read Display Image Format
|
|
#define ILI9341_RDSELFDIAG 0x0F ///< Read Display Self-Diagnostic Result
|
|
|
|
#define ILI9341_INVOFF 0x20 ///< Display Inversion OFF
|
|
#define ILI9341_INVON 0x21 ///< Display Inversion ON
|
|
#define ILI9341_GAMMASET 0x26 ///< Gamma Set
|
|
#define ILI9341_DISPOFF 0x28 ///< Display OFF
|
|
#define ILI9341_DISPON 0x29 ///< Display ON
|
|
|
|
#define ILI9341_CASET 0x2A ///< Column Address Set
|
|
#define ILI9341_PASET 0x2B ///< Page Address Set
|
|
#define ILI9341_RAMWR 0x2C ///< Memory Write
|
|
#define ILI9341_RAMRD 0x2E ///< Memory Read
|
|
|
|
#define ILI9341_PTLAR 0x30 ///< Partial Area
|
|
#define ILI9341_VSCRDEF 0x33 ///< Vertical Scrolling Definition
|
|
#define ILI9341_MADCTL 0x36 ///< Memory Access Control
|
|
#define ILI9341_VSCRSADD 0x37 ///< Vertical Scrolling Start Address
|
|
#define ILI9341_PIXFMT 0x3A ///< COLMOD: Pixel Format Set
|
|
#define ILI9341_WRCONT 0x3C ///< Continue Memory Write
|
|
|
|
#define ILI9341_DBRIGHT 0x51
|
|
|
|
#define ILI9341_FRMCTR1 \
|
|
0xB1 ///< Frame Rate Control (In Normal Mode/Full Colors)
|
|
#define ILI9341_FRMCTR2 0xB2 ///< Frame Rate Control (In Idle Mode/8 colors)
|
|
#define ILI9341_FRMCTR3 \
|
|
0xB3 ///< Frame Rate control (In Partial Mode/Full Colors)
|
|
#define ILI9341_INVCTR 0xB4 ///< Display Inversion Control
|
|
#define ILI9341_DFUNCTR 0xB6 ///< Display Function Control
|
|
|
|
#define ILI9341_PWCTR1 0xC0 ///< Power Control 1
|
|
#define ILI9341_PWCTR2 0xC1 ///< Power Control 2
|
|
#define ILI9341_PWCTR3 0xC2 ///< Power Control 3
|
|
#define ILI9341_PWCTR4 0xC3 ///< Power Control 4
|
|
#define ILI9341_PWCTR5 0xC4 ///< Power Control 5
|
|
#define ILI9341_VMCTR1 0xC5 ///< VCOM Control 1
|
|
#define ILI9341_VMCTR2 0xC7 ///< VCOM Control 2
|
|
|
|
#define ILI9341_RDID1 0xDA ///< Read ID 1
|
|
#define ILI9341_RDID2 0xDB ///< Read ID 2
|
|
#define ILI9341_RDID3 0xDC ///< Read ID 3
|
|
#define ILI9341_RDID4 0xDD ///< Read ID 4
|
|
|
|
#define ILI9341_GMCTRP1 0xE0 ///< Positive Gamma Correction
|
|
#define ILI9341_GMCTRN1 0xE1 ///< Negative Gamma Correction
|
|
//#define ILI9341_PWCTR6 0xFC
|
|
|
|
// Color definitions
|
|
#define ILI9341_BLACK 0x0000 ///< 0, 0, 0
|
|
#define ILI9341_NAVY 0x000F ///< 0, 0, 123
|
|
#define ILI9341_DARKGREEN 0x03E0 ///< 0, 125, 0
|
|
#define ILI9341_DARKCYAN 0x03EF ///< 0, 125, 123
|
|
#define ILI9341_MAROON 0x7800 ///< 123, 0, 0
|
|
#define ILI9341_PURPLE 0x780F ///< 123, 0, 123
|
|
#define ILI9341_OLIVE 0x7BE0 ///< 123, 125, 0
|
|
#define ILI9341_LIGHTGREY 0xC618 ///< 198, 195, 198
|
|
#define ILI9341_DARKGREY 0x7BEF ///< 123, 125, 123
|
|
#define ILI9341_BLUE 0x001F ///< 0, 0, 255
|
|
#define ILI9341_GREEN 0x07E0 ///< 0, 255, 0
|
|
#define ILI9341_CYAN 0x07FF ///< 0, 255, 255
|
|
#define ILI9341_RED 0xF800 ///< 255, 0, 0
|
|
#define ILI9341_MAGENTA 0xF81F ///< 255, 0, 255
|
|
#define ILI9341_YELLOW 0xFFE0 ///< 255, 255, 0
|
|
#define ILI9341_WHITE 0xFFFF ///< 255, 255, 255
|
|
#define ILI9341_ORANGE 0xFD20 ///< 255, 165, 0
|
|
#define ILI9341_GREENYELLOW 0xAFE5 ///< 173, 255, 41
|
|
#define ILI9341_PINK 0xFC18 ///< 255, 130, 198
|
|
|
|
|
|
struct __attribute__((packed)) tft_color {
|
|
uint8_t red;
|
|
uint8_t green;
|
|
uint8_t blue;
|
|
// uint16_t c16;
|
|
|
|
tft_color() : red(0x00), green(0), blue(0x00) {};
|
|
tft_color(uint8_t r, uint8_t g, uint8_t b) :
|
|
red(r), green(g), blue(b) {};
|
|
|
|
inline uint16_t u16(void) const
|
|
{
|
|
uint16_t ret = 0;
|
|
ret |= ((uint16_t)(red & 0xf8) << 8);
|
|
ret |= ((uint16_t)(green & 0xfc)) << 5;
|
|
ret |= ((uint16_t)blue) >> 3;
|
|
return (ret);
|
|
}
|
|
};
|
|
|
|
struct tft_dma_cmd {
|
|
size_t size;
|
|
uint8_t buf[];
|
|
};
|
|
|
|
#define TFT_CMD_PARAMS_MAXLEN 16
|
|
struct tft_cmd {
|
|
uint8_t cmd;
|
|
uint8_t _param_bytes[TFT_CMD_PARAMS_MAXLEN];
|
|
size_t param_len;
|
|
uint8_t *param_bytes_ext;
|
|
int post_delay;
|
|
|
|
tft_cmd(uint8_t c, std::initializer_list<uint8_t> params,
|
|
int dly = -1)
|
|
: cmd(c), param_len(params.size()), post_delay(dly)
|
|
{
|
|
size_t i;
|
|
|
|
AUDIOC_ASSERT(param_len <= sizeof(_param_bytes));
|
|
|
|
i = 0;
|
|
for (auto par : params) {
|
|
_param_bytes[i++] = par;
|
|
}
|
|
}
|
|
tft_cmd(uint8_t c, int dly = -1)
|
|
: cmd(c), param_len(0), post_delay(dly) {};
|
|
|
|
inline const uint8_t *param_bytes(void) const
|
|
{
|
|
return (_param_bytes);
|
|
}
|
|
};
|
|
|
|
#define TFT_DRIVER_ILI9341_NBLOCKS 8
|
|
|
|
struct tft_driver_ili9341 {
|
|
typedef void (*async_on_finish_f)(void *);
|
|
|
|
enum class async_status {
|
|
INIT,
|
|
READY,
|
|
TX,
|
|
NO_TX,
|
|
DONE
|
|
};
|
|
|
|
enum class async_wr {
|
|
START,
|
|
END
|
|
};
|
|
|
|
enum class async_hint {
|
|
NONE,
|
|
FULL_UPDATE_RENDER,
|
|
PARTIAL_UPDATE_RENDER
|
|
};
|
|
|
|
SpiHandle spi;
|
|
SpiHandle::Config spi_conf;
|
|
|
|
Logger<LOGGER_EXTERNAL> *lg;
|
|
|
|
Pin dcx_pin;
|
|
GPIO dcx;
|
|
|
|
async_hint _async_hint;
|
|
volatile async_status _async_stat;
|
|
volatile async_wr _async_wr;
|
|
volatile async_on_finish_f _async_cb_fun;
|
|
volatile void *_async_cb_ctx;
|
|
|
|
uint8_t *_async_dma_buf;
|
|
size_t _async_dma_sz;
|
|
|
|
volatile tft_dma_cmd *_async_curr_wr;
|
|
volatile const tft_dma_cmd *_async_curr_rd;
|
|
|
|
/* 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_dma_buf(NULL), _async_dma_sz(0),
|
|
_async_curr_wr(NULL), _async_curr_rd(NULL) {};
|
|
|
|
int init(uint8_t *dma_buf, size_t dma_sz);
|
|
|
|
/* syncronous */
|
|
int fill_screen(const tft_color *c);
|
|
void set_addr_window(uint16_t col_st, uint16_t width, uint16_t row_st,
|
|
uint16_t height);
|
|
|
|
int send_sync(const tft_cmd *cmd);
|
|
int send_sync(uint8_t cmd, const uint8_t *buf, size_t len);
|
|
int send_raw_sync(const uint8_t *buf, size_t len);
|
|
ssize_t recv_raw_sync(const uint8_t *buf, size_t len);
|
|
|
|
/* asyncronous */
|
|
void async_on_finish(async_on_finish_f cb, void *ctx);
|
|
|
|
int async_start(void);
|
|
int async_end(void);
|
|
|
|
async_status async_stat(void);
|
|
|
|
void async_flush(void);
|
|
void async_tx(void);
|
|
void async_tx_try(void);
|
|
|
|
int async_cmd_hint(async_hint hint);
|
|
int 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);
|
|
|
|
static void async_tx_cmd_scb(void *ctx);
|
|
static void async_tx_cmd_ecb(void *ctx, SpiHandle::Result res);
|
|
static void async_tx_param_scb(void *ctx);
|
|
static void async_tx_param_ecb(void *ctx, SpiHandle::Result res);
|
|
|
|
inline int
|
|
async_send_raw(const uint8_t *dma_buf, size_t dma_bufsz,
|
|
SpiHandle::StartCallbackFunctionPtr scb,
|
|
SpiHandle::EndCallbackFunctionPtr cb,
|
|
void *ctx) {
|
|
return (spi.DmaTransmit((uint8_t *)dma_buf, dma_bufsz, scb,
|
|
cb, ctx) == SpiHandle::Result::OK ? 0 : -1);
|
|
}
|
|
|
|
size_t dma_buf_sz_tx_pend(void);
|
|
size_t dma_buf_sz_used(void);
|
|
|
|
tft_dma_cmd *dma_buf_curr_wr(void);
|
|
tft_dma_cmd *dma_buf_next_wr(void);
|
|
|
|
const tft_dma_cmd *dma_buf_curr_rd(void);
|
|
const tft_dma_cmd *dma_buf_next_rd(void);
|
|
|
|
/* rendering */
|
|
int render_dma_buf_hline(const tft_color *c, uint16_t col_s,
|
|
uint16_t col_e, uint16_t row);
|
|
int render_dma_buf_memwr(const tft_color *col, size_t num);
|
|
int render_dma_buf_memwr_cont(const tft_color *col, size_t num);
|
|
int render_dma_buf_set_addr_window(uint16_t col_st,
|
|
uint16_t col_end, uint16_t row_st, uint16_t row_end);
|
|
int 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);
|
|
|
|
/* gpio control */
|
|
inline void
|
|
dcx_low(void)
|
|
{
|
|
dcx.Write(0);
|
|
}
|
|
|
|
inline void
|
|
dcx_high(void)
|
|
{
|
|
dcx.Write(1);
|
|
}
|
|
};
|
|
|
|
#endif
|