@ -1,5 +1,5 @@
/*
* Copyright ( c ) 201 4- 2015 , TAKAHASHI Tomohiro ( TTRFTECH ) edy555 @ gmail . com
* Copyright ( c ) 201 9- 2020 , written by DiSlord dislordlive @ gmail . com
* All rights reserved .
*
* This is free software ; you can redistribute it and / or modify
@ -21,8 +21,23 @@
# include "hal.h"
# include "nanovna.h"
// Allow enable DMA for read display data (some problem vs use in ST7796 in fast mode)
# define __USE_DISPLAY_DMA_RX__
# include "spi.h"
// Allow enable DMA for read display data
//#define __USE_DISPLAY_DMA_RX__
// Pin macros for LCD
# define LCD_CS_LOW palClearPad(GPIOB, GPIOB_LCD_CS)
# define LCD_CS_HIGH palSetPad(GPIOB, GPIOB_LCD_CS)
# define LCD_RESET_ASSERT palClearPad(GPIOA, GPIOA_LCD_RESET)
# define LCD_RESET_NEGATE palSetPad(GPIOA, GPIOA_LCD_RESET)
# define LCD_DC_CMD palClearPad(GPIOB, GPIOB_LCD_CD)
# define LCD_DC_DATA palSetPad(GPIOB, GPIOB_LCD_CD)
# define LCD_SPI SPI1
// Set SPI bus speed for LCD
# define LCD_SPI_SPEED SPI_BR_DIV2
//Not define if need use some as Tx speed
//#define LCD_SPI_RX_SPEED SPI_BR_DIV4
uint16_t spi_buffer [ SPI_BUFFER_SIZE ] ;
// Default foreground & background colors
@ -135,85 +150,44 @@ uint16_t background_color = 0;
# define DISPLAY_ROTATION_180 (ILI9341_MADCTL_MX | ILI9341_MADCTL_MY \
| ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR )
//
// Pin macros
//
# define RESET_ASSERT palClearPad(GPIOA, 15)
# define RESET_NEGATE palSetPad(GPIOA, 15)
# define CS_LOW palClearPad(GPIOB, 6)
# define CS_HIGH palSetPad(GPIOB, 6)
# define DC_CMD palClearPad(GPIOB, 7)
# define DC_DATA palSetPad(GPIOB, 7)
//*****************************************************************************
//********************************** SPI bus **********************************
//*****************************************************************************
// STM32 SPI transfer mode:
// in 8 bit mode:
// if you write *(uint8_t*)(&SPI1->DR) = (uint8_t) data, then data send as << data
// if you write *(uint16_t*)(&SPI1->DR) =(uint16_t) data, then data send as << dataLoByte, after send dataHiByte
// in 16 bit mode
// if you write *(uint16_t*)(&SPI1->DR) =(uint16_t) data, then data send as << data
// SPI init in 8 bit mode
# define SPI_CR2_8BIT 0x0700
# define SPI_CR2_16BIT 0x0F00
// SPI bus activity macros
// The RXNE flag is set depending on the FRXTH bit value in the SPIx_CR2 register:
// • If FRXTH is set, RXNE goes high and stays high until the RXFIFO level is greater or equal to 1/4 (8-bit).
# define SPI_RX_IS_NOT_EMPTY (SPI1->SR&SPI_SR_RXNE)
# define SPI_RX_IS_EMPTY (((SPI1->SR&SPI_SR_RXNE) == 0))
// The TXE flag is set when transmission TXFIFO has enough space to store data to send.
// 0: Tx buffer not empty, bit is cleared automatically when the TXFIFO level becomes greater than 1/2
// 1: Tx buffer empty, flag goes high and stays high until the TXFIFO level is lower or equal to 1/2 of the FIFO depth
# define SPI_TX_IS_NOT_EMPTY (((SPI1->SR&(SPI_SR_TXE)) == 0))
# define SPI_TX_IS_EMPTY (SPI1->SR&SPI_SR_TXE)
// When BSY is set, it indicates that a data transfer is in progress on the SPI (the SPI bus is busy).
# define SPI_IS_BUSY (SPI1->SR & SPI_SR_BSY)
// SPI send data macros
# define SPI_WRITE_8BIT(data) *(__IO uint8_t*)(&SPI1->DR) = (uint8_t) data
# define SPI_WRITE_16BIT(data) SPI1->DR = data
// SPI read data macros
# define SPI_READ_DATA SPI1->DR
//*****************************************************
// SPI DMA settings and data
//*****************************************************
# ifdef __USE_DISPLAY_DMA__
static const stm32_dma_stream_t * dmatx =
STM32_DMA_STREAM ( STM32_SPI_SPI1_TX_DMA_STREAM ) ;
static uint32_t txdmamode =
static const uint32_t txdmamode =
STM32_DMA_CR_CHSEL ( SPI1_TX_DMA_CHANNEL ) // Select SPI1 Tx DMA
| STM32_DMA_CR_PL ( STM32_SPI_SPI1_DMA_PRIORITY ) // Set priority
| STM32_DMA_CR_DIR_M2P // Memory to Spi
| STM32_DMA_CR_DMEIE //
| STM32_DMA_CR_TEIE ;
| STM32_DMA_CR_DIR_M2P ; // Memory to Spi
// Not handle interrupt
#if 0
static void spi_lld_serve_tx_interrupt ( SPIDriver * spip , uint32_t flags )
{
( void ) spip ;
( void ) flags ;
}
# endif
# ifdef __USE_DISPLAY_DMA_RX__
static const stm32_dma_stream_t * dmarx = STM32_DMA_STREAM ( STM32_SPI_SPI1_RX_DMA_STREAM ) ;
static uint32_t rxdmamode = STM32_DMA_CR_CHSEL ( SPI1_RX_DMA_CHANNEL )
| STM32_DMA_CR_PL ( STM32_SPI_SPI1_DMA_PRIORITY )
| STM32_DMA_CR_DIR_P2M
| STM32_DMA_CR_TCIE
| STM32_DMA_CR_DMEIE
| STM32_DMA_CR_TEIE ;
static const uint32_t rxdmamode =
STM32_DMA_CR_CHSEL ( SPI1_RX_DMA_CHANNEL ) // Select SPI1 Rx DMA
| STM32_DMA_CR_PL ( STM32_SPI_SPI1_DMA_PRIORITY ) // Set priority
| STM32_DMA_CR_DIR_P2M ; // SPI to Memory
// Not handle interrupt
#if 0
static void spi_lld_serve_rx_interrupt ( SPIDriver * spip , uint32_t flags )
{
( void ) spip ;
( void ) flags ;
}
# endif
# endif
// Send prepared DMA data, and wait completion
static void dmaStreamFlush ( uint32_t len )
{
while ( len ) {
@ -227,53 +201,129 @@ static void dmaStreamFlush(uint32_t len)
}
# endif
// SPI transmit byte to SPI (no wait complete transmit)
void spi_TxByte ( uint8_t data ) {
SPI_WRITE_8BIT ( LCD_SPI , data ) ;
}
// Transmit word to SPI bus (if SPI in 8 bit mode LSB send first!!!!!)
void spi_TxWord ( uint16_t data ) {
SPI_WRITE_16BIT ( LCD_SPI , data ) ;
}
// Transmit buffer to SPI bus (len should be > 0)
void spi_TxBuffer ( uint8_t * buffer , uint16_t len ) {
do {
while ( SPI_TX_IS_NOT_EMPTY ( LCD_SPI ) ) ;
SPI_WRITE_8BIT ( LCD_SPI , * buffer + + ) ;
} while ( - - len ) ;
}
// Receive byte from SPI bus
uint8_t spi_RxByte ( void ) {
// Start RX clock (by sending data)
SPI_WRITE_8BIT ( LCD_SPI , 0xFF ) ;
while ( SPI_RX_IS_EMPTY ( LCD_SPI ) | | SPI_IS_BUSY ( LCD_SPI ) ) ;
return SPI_READ_8BIT ( LCD_SPI ) ;
}
// Receive buffer from SPI bus (len should be > 0)
void spi_RxBuffer ( uint8_t * buffer , uint16_t len ) {
do {
SPI_WRITE_8BIT ( LCD_SPI , 0xFF ) ;
while ( SPI_RX_IS_EMPTY ( LCD_SPI ) ) ;
* buffer + + = SPI_READ_8BIT ( LCD_SPI ) ;
} while ( - - len ) ;
}
void spi_DropRx ( void ) {
// Drop Rx buffer after tx and wait tx complete
while ( SPI_RX_IS_NOT_EMPTY ( LCD_SPI ) | | SPI_IS_BUSY ( LCD_SPI ) )
( void ) SPI_READ_8BIT ( LCD_SPI ) ;
}
# ifdef __USE_DISPLAY_DMA__
// SPI receive byte buffer use DMA
void spi_DMATxBuffer ( uint8_t * buffer , uint16_t len ) {
dmaStreamSetMemory0 ( dmatx , buffer ) ;
dmaStreamSetMode ( dmatx , txdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_MINC ) ;
dmaStreamFlush ( len ) ;
}
# ifdef __USE_DISPLAY_DMA_RX__
// SPI transmit byte buffer use DMA
static void spi_DMARxBuffer ( uint8_t * buffer , uint16_t len ) {
uint8_t dummy_tx = 0xFF ;
// Init Rx DMA buffer, size, mode (spi and mem data size is 8 bit)
dmaStreamSetMemory0 ( dmarx , buffer ) ;
dmaStreamSetTransactionSize ( dmarx , len ) ;
dmaStreamSetMode ( dmarx , rxdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_MINC ) ;
// Init dummy Tx DMA (for rx clock), size, mode (spi and mem data size is 8 bit)
dmaStreamSetMemory0 ( dmatx , & dummy_tx ) ;
dmaStreamSetTransactionSize ( dmatx , len ) ;
dmaStreamSetMode ( dmatx , txdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE ) ;
// Skip SPI rx buffer
spi_DropRx ( ) ;
// Start DMA exchange
dmaStreamEnable ( dmarx ) ;
dmaStreamEnable ( dmatx ) ;
// Wait DMA completion
dmaWaitCompletion ( dmatx ) ;
dmaWaitCompletion ( dmarx ) ;
}
# endif
# endif
static void spi_init ( void )
{
rccEnableSPI1 ( FALSE ) ;
SPI1 - > CR1 = 0 ;
SPI1 - > CR1 = SPI_CR1_MSTR // SPI is MASTER
| SPI_CR1_SSM // Software slave management (The external NSS pin is free for other application uses)
| SPI_CR1_SSI ; // Internal slave select (This bit has an effect only when the SSM bit is set. Allow use NSS pin as I/O)
// | SPI_CR1_BR_1; // Baud rate control
SPI1 - > CR2 = SPI_CR2_8BIT // SPI data size, set to 8 bit
| SPI_CR2_FRXTH ; // SPI_SR_RXNE generated every 8 bit data
// | SPI_CR2_SSOE; //
LCD_SPI - > CR1 = 0 ;
LCD_SPI - > CR1 = SPI_CR1_MSTR // SPI is MASTER
| SPI_CR1_SSM // Software slave management (The external NSS pin is free for other application uses)
| SPI_CR1_SSI // Internal slave select (This bit has an effect only when the SSM bit is set. Allow use NSS pin as I/O)
| LCD_SPI_SPEED // Baud rate control
// | SPI_CR1_CPHA // Clock Phase
// | SPI_CR1_CPOL // Clock Polarity
;
LCD_SPI - > CR2 = SPI_CR2_8BIT // SPI data size, set to 8 bit
| SPI_CR2_FRXTH ; // SPI_SR_RXNE generated every 8 bit data
// | SPI_CR2_SSOE; //
# ifdef __USE_DISPLAY_DMA__
// Tx DMA init
dmaStreamAllocate ( dmatx , STM32_SPI_SPI1_IRQ_PRIORITY , ( stm32_dmaisr_t ) spi_lld_serve_tx_interrupt , NULL ) ;
dmaStreamSetPeripheral ( dmatx , & SPI1 - > DR ) ;
SPI1 - > CR2 | = SPI_CR2_TXDMAEN ; // Tx DMA enable
dmaStreamAllocate ( dmatx , STM32_SPI_SPI1_IRQ_PRIORITY , NULL , NULL ) ;
dmaStreamSetPeripheral ( dmatx , & LCD_ SPI- > DR ) ;
LCD_ SPI- > CR2 | = SPI_CR2_TXDMAEN ; // Tx DMA enable
# ifdef __USE_DISPLAY_DMA_RX__
// Rx DMA init
dmaStreamAllocate ( dmarx , STM32_SPI_SPI1_IRQ_PRIORITY , ( stm32_dmaisr_t ) spi_lld_serve_rx_interrupt , NULL ) ;
dmaStreamSetPeripheral ( dmarx , & SPI1 - > DR ) ;
dmaStreamAllocate ( dmarx , STM32_SPI_SPI1_IRQ_PRIORITY , NULL , NULL ) ;
dmaStreamSetPeripheral ( dmarx , & LCD_ SPI- > DR ) ;
// Enable DMA on SPI
SPI1 - > CR2 | = SPI_CR2_RXDMAEN ; // Rx DMA enable
LCD_ SPI- > CR2 | = SPI_CR2_RXDMAEN ; // Rx DMA enable
# endif
# endif
SPI1 - > CR1 | = SPI_CR1_SPE ; //SPI enable
LCD_ SPI- > CR1 | = SPI_CR1_SPE ; //SPI enable
}
// Disable inline for this function
static void __attribute__ ( ( noinline ) ) send_command ( uint8_t cmd , uint8_t len , const uint8_t * data )
static void send_command( uint8_t cmd , uint8_t len , const uint8_t * data )
{
CS_LOW ;
//while (SPI_TX_IS_NOT_EMPTY);
DC_CMD ;
SPI_WRITE_8BIT ( cmd ) ;
// Uncomment on low speed SPI (possible get here before previous tx complete)
// while (SPI_IN_TX_RX);
LCD_CS_LOW ;
LCD_DC_CMD ;
SPI_WRITE_8BIT ( LCD_SPI , cmd ) ;
// Need wait transfer complete and set data bit
while ( SPI_IS_BUSY )
while ( SPI_IN_TX_RX ( LCD_SPI ) )
;
// Send command data (if need)
DC_DATA ;
LCD_ DC_DATA;
while ( len - - > 0 ) {
while ( SPI_TX_IS_NOT_EMPTY )
while ( SPI_TX_IS_NOT_EMPTY ( LCD_SPI ) )
;
SPI_WRITE_8BIT ( * data + + ) ;
SPI_WRITE_8BIT ( LCD_SPI , * data + + ) ;
}
//CS_HIGH;
// LCD_ CS_HIGH;
}
static const uint8_t ili9341_init_seq [ ] = {
@ -337,10 +387,10 @@ static const uint8_t ili9341_init_seq[] = {
void ili9341_init ( void )
{
spi_init ( ) ;
DC_DATA;
RESET_ASSERT;
LCD_ DC_DATA;
LCD_ RESET_ASSERT;
chThdSleepMilliseconds ( 10 ) ;
RESET_NEGATE;
LCD_ RESET_NEGATE;
const uint8_t * p ;
for ( p = ili9341_init_seq ; * p ; ) {
send_command ( p [ 0 ] , p [ 1 ] , & p [ 2 ] ) ;
@ -351,6 +401,8 @@ void ili9341_init(void)
void ili9341_bulk_8bit ( int x , int y , int w , int h , uint16_t * palette )
{
//uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
//uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
uint32_t xx = __REV16 ( x | ( ( x + w - 1 ) < < 16 ) ) ;
uint32_t yy = __REV16 ( y | ( ( y + h - 1 ) < < 16 ) ) ;
send_command ( ILI9341_COLUMN_ADDRESS_SET , 4 , ( uint8_t * ) & xx ) ;
@ -359,12 +411,8 @@ void ili9341_bulk_8bit(int x, int y, int w, int h, uint16_t *palette)
uint8_t * buf = ( uint8_t * ) spi_buffer ;
int32_t len = w * h ;
while ( len - - > 0 ) {
uint16_t color = palette [ * buf + + ] ;
while ( SPI_TX_IS_NOT_EMPTY )
;
SPI_WRITE_16BIT ( color ) ;
}
while ( len - - > 0 )
spi_TxWord ( palette [ * buf + + ] ) ;
}
# ifndef __USE_DISPLAY_DMA__
@ -378,17 +426,14 @@ void ili9341_fill(int x, int y, int w, int h, uint16_t color)
send_command ( ILI9341_PAGE_ADDRESS_SET , 4 , ( uint8_t * ) & yy ) ;
send_command ( ILI9341_MEMORY_WRITE , 0 , NULL ) ;
int32_t len = w * h ;
while ( len - - > 0 ) {
while ( SPI_TX_IS_NOT_EMPTY )
;
SPI_WRITE_16BIT ( color ) ;
}
while ( len - - > 0 )
spi_TxWord ( color ) ;
}
void ili9341_bulk ( int x , int y , int w , int h )
{
// uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
// uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
// uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
// uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
uint16_t * buf = spi_buffer ;
uint32_t xx = __REV16 ( x | ( ( x + w - 1 ) < < 16 ) ) ;
uint32_t yy = __REV16 ( y | ( ( y + h - 1 ) < < 16 ) ) ;
@ -396,11 +441,8 @@ void ili9341_bulk(int x, int y, int w, int h)
send_command ( ILI9341_PAGE_ADDRESS_SET , 4 , ( uint8_t * ) & yy ) ;
send_command ( ILI9341_MEMORY_WRITE , 0 , NULL ) ;
int32_t len = w * h ;
while ( len - - > 0 ) {
while ( SPI_TX_IS_NOT_EMPTY )
;
SPI_WRITE_16BIT ( * buf + + ) ;
}
while ( len - - > 0 )
spi_TxWord ( * buf + + ) ;
}
# else
//
@ -409,6 +451,8 @@ void ili9341_bulk(int x, int y, int w, int h)
// Fill region by some color
void ili9341_fill ( int x , int y , int w , int h , uint16_t color )
{
//uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
//uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
uint32_t xx = __REV16 ( x | ( ( x + w - 1 ) < < 16 ) ) ;
uint32_t yy = __REV16 ( y | ( ( y + h - 1 ) < < 16 ) ) ;
send_command ( ILI9341_COLUMN_ADDRESS_SET , 4 , ( uint8_t * ) & xx ) ;
@ -438,75 +482,83 @@ void ili9341_bulk(int x, int y, int w, int h)
# endif
# ifndef __USE_DISPLAY_DMA_RX__
static uint8_t ssp_sendrecvdata ( void )
{
// Start RX clock (by sending data)
SPI_WRITE_8BIT ( 0 ) ;
while ( SPI_RX_IS_EMPTY & & SPI_IS_BUSY )
;
return SPI_READ_DATA ;
}
void ili9341_read_memory ( int x , int y , int w , int h , int len , uint16_t * out )
{
// uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
// uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
//uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
//uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
uint32_t xx = __REV16 ( x | ( ( x + w - 1 ) < < 16 ) ) ;
uint32_t yy = __REV16 ( y | ( ( y + h - 1 ) < < 16 ) ) ;
send_command ( ILI9341_COLUMN_ADDRESS_SET , 4 , ( uint8_t * ) & xx ) ;
send_command ( ILI9341_PAGE_ADDRESS_SET , 4 , ( uint8_t * ) & yy ) ;
send_command ( ILI9341_MEMORY_READ , 0 , NULL ) ;
// Skip data from rx buffer
while ( SPI_RX_IS_NOT_EMPTY )
( void ) SPI_READ_DATA ;
spi_DropRx ( ) ;
// Set read speed (if need different)
# ifdef LCD_SPI_RX_SPEED
SPI_BR_SET ( LCD_SPI , LCD_SPI_RX_SPEED ) ;
# endif
// require 8bit dummy clock
ssp_sendrecvdata ( ) ;
s pi_RxByte ( ) ;
while ( len - - > 0 ) {
uint8_t r , g , b ;
// read data is always 18bit
uint8_t r = ssp_sendrecvdata ( ) ;
uint8_t g = ssp_sendrecvdata ( ) ;
uint8_t b = ssp_sendrecvdata ( ) ;
r = spi_RxByte ( ) ;
g = spi_RxByte ( ) ;
b = spi_RxByte ( ) ;
* out + + = RGB565 ( r , g , b ) ;
}
CS_HIGH ;
// restore speed if need
# ifdef LCD_SPI_RX_SPEED
SPI_BR_SET ( LCD_SPI , LCD_SPI_SPEED ) ;
# endif
LCD_CS_HIGH ;
}
# else
// Copy screen data to buffer
// Warning!!! buffer size must be greater then 3*len + 1 bytes
void ili9341_read_memory ( int x , int y , int w , int h , int len , uint16_t * out )
{
uint 8 _t dummy_tx = 0 ;
uint 16 _t dummy_tx = 0 ;
uint8_t * rgbbuf = ( uint8_t * ) out ;
uint16_t data_size = len * 3 + 1 ;
uint16_t data_size = len * 3 ;
//uint8_t xx[4] = { x >> 8, x, (x+w-1) >> 8, (x+w-1) };
//uint8_t yy[4] = { y >> 8, y, (y+h-1) >> 8, (y+h-1) };
uint32_t xx = __REV16 ( x | ( ( x + w - 1 ) < < 16 ) ) ;
uint32_t yy = __REV16 ( y | ( ( y + h - 1 ) < < 16 ) ) ;
send_command ( ILI9341_COLUMN_ADDRESS_SET , 4 , ( uint8_t * ) & xx ) ;
send_command ( ILI9341_PAGE_ADDRESS_SET , 4 , ( uint8_t * ) & yy ) ;
send_command ( ILI9341_MEMORY_READ , 0 , NULL ) ;
// Skip SPI rx buffer
while ( SPI_RX_IS_NOT_EMPTY ) ( void ) SPI_READ_DATA ;
// Init Rx DMA buffer, size, mode (spi and mem data size is 8 bit)
dmaStreamSetMemory0 ( dmarx , rgbbuf ) ;
dmaStreamSetTransactionSize ( dmarx , data_size ) ;
dmaStreamSetMode ( dmarx , rxdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE |
STM32_DMA_CR_MINC ) ;
dmaStreamSetMode ( dmarx , rxdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_MINC ) ;
// Init dummy Tx DMA (for rx clock), size, mode (spi and mem data size is 8 bit)
dmaStreamSetMemory0 ( dmatx , & dummy_tx ) ;
dmaStreamSetTransactionSize ( dmatx , data_size ) ;
dmaStreamSetMode ( dmatx , txdmamode | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE ) ;
// Skip SPI rx buffer
spi_DropRx ( ) ;
// Set read speed (if need different)
# ifdef LCD_SPI_RX_SPEED
SPI_BR_SET ( LCD_SPI , LCD_SPI_RX_SPEED ) ;
# endif
// require 8bit dummy clock
spi_RxByte ( ) ;
// Start DMA exchange
dmaStreamEnable ( dmarx ) ;
dmaStreamEnable ( dmatx ) ;
// Wait DMA completion
dmaWaitCompletion ( dmatx ) ;
dmaWaitCompletion ( dmarx ) ;
CS_HIGH ;
// restore speed if need
# ifdef LCD_SPI_RX_SPEED
SPI_BR_SET ( LCD_SPI , LCD_SPI_SPEED ) ;
# endif
LCD_CS_HIGH ;
// Parce recived data
// Skip dummy 8-bit read
rgbbuf + + ;
while ( len - - > 0 ) {
uint8_t r , g , b ;
// read data is always 18bit
@ -573,12 +625,6 @@ void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t heigh
ili9341_bulk ( x , y , width , height ) ;
}
int ili9341_size = 1 ;
void ili9341_charsize ( int s )
{
ili9341_size = s ;
}
void ili9341_drawchar ( uint8_t ch , int x , int y )
{
blit8BitWidthBitmap ( x , y , FONT_GET_WIDTH ( ch ) , FONT_GET_HEIGHT , FONT_GET_DATA ( ch ) ) ;