From 174bbaa7d1e0abee35f6be0c3948a14ac1c4e94a Mon Sep 17 00:00:00 2001 From: DiSlord Date: Sun, 12 Jul 2020 17:28:15 +0300 Subject: [PATCH] Move SPI definition to spi.h Update to last ili driver ( --- ili9341.c | 336 +++++++++++++++++++++++++++++++----------------------- spi.h | 80 +++++++++++++ 2 files changed, 271 insertions(+), 145 deletions(-) create mode 100644 spi.h diff --git a/ili9341.c b/ili9341.c index f3ff1e8..dd581ea 100644 --- a/ili9341.c +++ b/ili9341.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, TAKAHASHI Tomohiro (TTRFTECH) edy555@gmail.com + * Copyright (c) 2019-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(); + spi_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) { - uint8_t dummy_tx = 0; + uint16_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 @@ -519,7 +571,7 @@ void ili9341_read_memory(int x, int y, int w, int h, int len, uint16_t *out) } #endif -void ili9341_clear_screen(void) +void ili9341_clear_screen(void) { ili9341_fill(0, 0, ILI9341_WIDTH, ILI9341_HEIGHT, background_color); } @@ -546,7 +598,7 @@ void ili9341_set_rotation(uint8_t r) } void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, - const uint8_t *bitmap) + const uint8_t *bitmap) { uint16_t *buf = spi_buffer; for (uint16_t c = 0; c < height; c++) { @@ -560,7 +612,7 @@ void blit8BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height } void blit16BitWidthBitmap(uint16_t x, uint16_t y, uint16_t width, uint16_t height, - const uint16_t *bitmap) + const uint16_t *bitmap) { uint16_t *buf = spi_buffer; for (uint16_t c = 0; c < height; c++) { @@ -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)); diff --git a/spi.h b/spi.h new file mode 100644 index 0000000..04238c9 --- /dev/null +++ b/spi.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019-2020, Dmitry Slepynin (DiSlord) dislordlive@gmail.com + * All rights reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * The software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +//***************************************************************************** +//********************************** SPI1 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 baud rate (PPL/BR_DIV) +//***************************************************** +#define SPI_BR_DIV2 (0x00000000U) +#define SPI_BR_DIV4 (SPI_CR1_BR_0) +#define SPI_BR_DIV8 (SPI_CR1_BR_1) +#define SPI_BR_DIV16 (SPI_CR1_BR_1|SPI_CR1_BR_0) +#define SPI_BR_DIV32 (SPI_CR1_BR_2) +#define SPI_BR_DIV64 (SPI_CR1_BR_2|SPI_CR1_BR_0) +#define SPI_BR_DIV128 (SPI_CR1_BR_2|SPI_CR1_BR_1) +#define SPI_BR_DIV256 (SPI_CR1_BR_2|SPI_CR1_BR_1|SPI_CR1_BR_0) + +#define SPI_BR_SET(spi, br) (spi->CR1 = (spi->CR1& ~(SPI_CR1_BR))|br) + +//***************************************************** +// 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(spi) (spi->SR&SPI_SR_RXNE) +#define SPI_RX_IS_EMPTY(spi) (((spi->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(spi) (((spi->SR&(SPI_SR_TXE)) == 0)) +#define SPI_TX_IS_EMPTY(spi) (spi->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(spi) (spi->SR & SPI_SR_BSY) + +// Tx or Rx in process +#define SPI_IN_TX_RX(spi) ((spi->SR & (SPI_SR_TXE | SPI_SR_RXNE)) == 0 || SPI_IS_BUSY(spi)) + +//***************************************************** +// SPI send data macros +//***************************************************** +#define SPI_WRITE_8BIT(spi, data) *(__IO uint8_t*)(&spi->DR) = (uint8_t) data +#define SPI_WRITE_16BIT(spi, data) *(__IO uint16_t*)(&spi->DR) = (uint16_t) data + +//***************************************************** +// SPI read data macros +//***************************************************** +#define SPI_READ_8BIT(spi) *(__IO uint8_t*)(&spi->DR) +#define SPI_READ_16BIT(spi) *(__IO uint16_t*)(&spi->DR) +