TFT_eSPI/Processors/TFT_eSPI_K210.h

379 lines
14 KiB
C

////////////////////////////////////////////////////
// TFT_eSPI driver functions for K210 processor //
// based on https://github.com/fukuen/TFT_eSPI //
////////////////////////////////////////////////////
#ifndef _TFT_eSPI_K210H_
#define _TFT_eSPI_K210H_
// Processor ID reported by getSetup()
#define PROCESSOR_ID 0x0210
// Include processor specific header
#include <stdint.h>
#include "gpio.h"
#include "fpioa.h"
#include "kendryte-standalone-sdk/lib/drivers/include/spi.h"
#include "kendryte-standalone-sdk/lib/drivers/include/sysctl.h"
#include "dmac.h"
#include "sleep.h"
#include <User_Setups/Setup210_Maixduino.h>
#if defined(MAIX_AMIGO) || defined(MAIX_CUBE)
#include <Wire.h>
#include <AXP173.h>
#elif defined(M5STICK_V)
#include <Wire.h>
#include <AXP192.h>
#endif
#define RST_PIN 6
#define DCX_PIN 7
#define SPI_NUM SPI_DEVICE_0
#define SS_PIN SPI_CHIP_SELECT_3
#define DMA_CH DMAC_CHANNEL3
static int8_t g_gpio_rst;
static uint8_t g_gpio_dcx;
static spi_chip_select_t g_ss;
static dmac_channel_number_t g_dma_ch;
static spi_device_num_t g_spi_num;
void tft_io_init(void)
{
#if defined(MAIX_AMIGO) || defined(MAIX_CUBE)
AXP173 Axp = AXP173();
Wire.begin((uint8_t) SDA, (uint8_t) SCL, 400000);
Axp.begin(true); //Wire is already enabled
#elif defined(M5STICK_V)
sysctl_set_power_mode(SYSCTL_POWER_BANK3,SYSCTL_POWER_V33);
AXP192 Axp = AXP192();
Wire.begin((uint8_t) SDA, (uint8_t) SCL, 400000);
Axp.begin(true); //Wire is already enabled
#endif
g_spi_num = SPI_NUM;
g_dma_ch = DMA_CH;
g_ss = SS_PIN;
/* Init SPI IO map and function settings */
fpioa_set_function(TFT_CS, (fpioa_function_t)(FUNC_SPI0_SS0 + SS_PIN));
#if defined (M5STICK_V)
fpioa_set_function(TFT_SCLK, FUNC_SPI0_SCLK);
#else
fpioa_set_function(TFT_WR, FUNC_SPI0_SCLK);
#endif
sysctl_set_spi0_dvp_data(1);
//tft_hard_init(uint8_t spi, uint8_t ss, uint8_t rst, uint8_t dcx, uint32_t freq, int8_t rst_pin, int8_t dcx_pin, uint8_t dma_ch){
fpioa_set_function(TFT_DC, (fpioa_function_t)(FUNC_GPIO0 + DCX_PIN));
g_gpio_dcx = DCX_PIN;
gpio_set_drive_mode(g_gpio_dcx, GPIO_DM_OUTPUT);
gpio_set_pin(g_gpio_dcx, GPIO_PV_HIGH);
fpioa_set_function(TFT_RST, (fpioa_function_t)(FUNC_GPIO0 + RST_PIN));
g_gpio_rst = RST_PIN;
gpio_set_drive_mode(g_gpio_rst, GPIO_DM_OUTPUT);
gpio_set_pin(g_gpio_rst, GPIO_PV_HIGH);
gpio_set_pin(g_gpio_rst, GPIO_PV_LOW);
#if defined (M5STICK_V)
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_STANDARD, 8, 0);
#else
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
#endif
spi_set_clk_rate(g_spi_num, SPI_FREQUENCY);
gpio_set_pin(g_gpio_rst, GPIO_PV_HIGH);
}
void tft_write_command(uint8_t cmd)
{
gpio_set_pin(g_gpio_dcx, GPIO_PV_LOW);
#if defined (M5STICK_V)
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_STANDARD, 8, 0);
#else
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
spi_init_non_standard(g_spi_num, 8, 0, 0, SPI_AITM_AS_FRAME_FORMAT);
#endif
spi_send_data_normal_dma(g_dma_ch, g_spi_num, g_ss, (uint8_t *)(&cmd), 1, SPI_TRANS_CHAR);
}
void tft_write_byte(uint8_t *data_buf, uint32_t length)
{
gpio_set_pin(g_gpio_dcx, GPIO_PV_HIGH);
#if defined (M5STICK_V)
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_STANDARD, 8, 0);
#else
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
spi_init_non_standard(g_spi_num, 8, 0, 0, SPI_AITM_AS_FRAME_FORMAT);
#endif
spi_send_data_normal_dma(g_dma_ch, g_spi_num, g_ss, data_buf, length, SPI_TRANS_CHAR);
}
void tft_write_half(uint16_t *data_buf, uint32_t length)
{
gpio_set_pin(g_gpio_dcx, GPIO_PV_HIGH);
#if defined (M5STICK_V)
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_STANDARD, 16, 0);
#else
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 16, 0);
spi_init_non_standard(g_spi_num, 16, 0, 0, SPI_AITM_AS_FRAME_FORMAT);
#endif
spi_send_data_normal_dma(g_dma_ch, g_spi_num, g_ss, data_buf, length, SPI_TRANS_SHORT);
}
void tft_write_word(uint32_t *data_buf, uint32_t length)
{
gpio_set_pin(g_gpio_dcx, GPIO_PV_HIGH);
#if defined (M5STICK_V)
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_STANDARD, 32, 0);
#else
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0);
spi_init_non_standard(g_spi_num, 0, 32, 0, SPI_AITM_AS_FRAME_FORMAT);
#endif
spi_send_data_normal_dma(g_dma_ch, g_spi_num, g_ss, data_buf, length, SPI_TRANS_INT);
}
void tft_fill_data(uint32_t *data_buf, uint32_t length)
{
gpio_set_pin(g_gpio_dcx, GPIO_PV_HIGH);
#if defined (M5STICK_V)
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_STANDARD, 32, 0);
#else
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0);
spi_init_non_standard(g_spi_num, 0, 32, 0, SPI_AITM_AS_FRAME_FORMAT);
#endif
spi_fill_data_dma(g_dma_ch, g_spi_num, g_ss, data_buf, length);
}
void tft_write_cs()
{
#if defined (M5STICK_V)
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_STANDARD, 8, 0);
#else
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
spi_init_non_standard(g_spi_num, 8, 0, 0, SPI_AITM_AS_FRAME_FORMAT);
#endif
}
void tft_write_a_byte(uint8_t data)
{
// dmac_wait_done(g_dma_ch);
// spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
// spi_init_non_standard(g_spi_num, 8, 0, 0, SPI_AITM_AS_FRAME_FORMAT);
spi_send_data_normal_dma(g_dma_ch, g_spi_num, g_ss, (uint8_t *)(&data), 1, SPI_TRANS_CHAR);
}
void tft_write_a_half(uint16_t data)
{
// dmac_wait_done(g_dma_ch);
#if defined (M5STICK_V)
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_STANDARD, 16, 0);
#else
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 16, 0);
spi_init_non_standard(g_spi_num, 16, 0, 0, SPI_AITM_AS_FRAME_FORMAT);
#endif
spi_send_data_normal_dma(g_dma_ch, g_spi_num, g_ss, (uint16_t *)(&data), 1, SPI_TRANS_SHORT);
}
void tft_write_a_word(uint32_t data)
{
uint8_t tmp[4] = { static_cast<uint8_t>((data >> 24) & 0xff), static_cast<uint8_t>((data >> 16) & 0xff), static_cast<uint8_t>((data >> 8) & 0xff), static_cast<uint8_t>(data & 0xff) };
dmac_wait_done(g_dma_ch);
#if defined (M5STICK_V)
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_STANDARD, 8, 0);
#else
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
spi_init_non_standard(g_spi_num, 8, 0, 0, SPI_AITM_AS_FRAME_FORMAT);
#endif
spi_send_data_normal_dma(g_dma_ch, g_spi_num, g_ss, (uint8_t *)tmp, 4, SPI_TRANS_CHAR);
}
uint8_t tft_read_a_byte(void)
{
uint8_t tmp;
#if defined (M5STICK_V)
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_STANDARD, 8, 0);
#else
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
spi_init_non_standard(g_spi_num, 8, 0, 0, SPI_AITM_AS_FRAME_FORMAT);
#endif
spi_receive_data_standard_dma(g_dma_ch, g_dma_ch, g_spi_num, g_ss, NULL, 0, (uint8_t *)(&tmp), 1);
return tmp;
}
// Processor specific code used by SPI bus transaction startWrite and endWrite functions
#define SET_BUS_WRITE_MODE // Not used
#define SET_BUS_READ_MODE // Not used
// Code to check if DMA is busy, used by SPI bus transaction startWrite and endWrite functions
#define DMA_BUSY_CHECK // Not used so leave blank
// SUPPORT_TRANSACTIONS is mandatory for K210
#if !defined (SUPPORT_TRANSACTIONS)
#define SUPPORT_TRANSACTIONS
#endif
// Initialise processor specific SPI functions, used by init()
#define INIT_TFT_DATA_BUS // Not used
// If smooth font is used then it is likely SPIFFS will be needed
#ifdef SMOOTH_FONT
// Call up the SPIFFS (SPI FLASH Filing System) for the anti-aliased fonts
// #define FS_NO_GLOBALS
// #include <FS.h>
// #include "Maixduino_SPIFFS.h"
// #define FONT_FS_AVAILABLE
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Define the DC (TFT Data/Command or Register Select (RS))pin drive code
////////////////////////////////////////////////////////////////////////////////////////
#if (TFT_DC >= 0)
#if defined (RPI_DISPLAY_TYPE)
#if defined (ILI9486_DRIVER)
// RPi ILI9486 display needs a slower DC change
#define DC_C gpio_set_pin(g_gpio_dcx, GPIO_PV_LOW); \
gpio_set_pin(g_gpio_dcx, GPIO_PV_LOW)
#define DC_D gpio_set_pin(g_gpio_dcx, GPIO_PV_LOW); \
gpio_set_pin(g_gpio_dcx, GPIO_PV_HIGH)
#else
// Other RPi displays need a slower C->D change
#define DC_C gpio_set_pin(g_gpio_dcx, GPIO_PV_LOW)
#define DC_D gpio_set_pin(g_gpio_dcx, GPIO_PV_LOW); \
gpio_set_pin(g_gpio_dcx, GPIO_PV_HIGH)
#endif
#else
#define DC_C gpio_set_pin(g_gpio_dcx, GPIO_PV_LOW)
#define DC_D gpio_set_pin(g_gpio_dcx, GPIO_PV_HIGH)
#endif
#else
#define DC_C // No macro allocated so it generates no code
#define DC_D // No macro allocated so it generates no code
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Define the CS (TFT chip select) pin drive code
////////////////////////////////////////////////////////////////////////////////////////
#if (TFT_CS >= 0)
#ifdef RPI_DISPLAY_TYPE // RPi display needs a slower CS change
#define CS_L digitalWrite(TFT_CS, HIGH); tft_write_cs()
#define CS_H tft_write_cs(); digitalWrite(TFT_CS, HIGH)
#else
#define CS_L tft_write_cs()
#define CS_H digitalWrite(TFT_CS, HIGH)
#endif
#else
#define CS_L // No macro allocated so it generates no code
#define CS_H // No macro allocated so it generates no code
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Define the WR (TFT Write) pin drive code
////////////////////////////////////////////////////////////////////////////////////////
#if !defined TFT_WR || (TFT_WR < 0)
#define WR_L // No macro allocated so it generates no code
#define WR_H // No macro allocated so it generates no code
#else
#define WR_L digitalWrite(TFT_WR, LOW)
#define WR_H digitalWrite(TFT_WR, HIGH)
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Define the touch screen chip select pin drive code
////////////////////////////////////////////////////////////////////////////////////////
#if !defined TOUCH_CS || (TOUCH_CS < 0)
#define T_CS_L // No macro allocated so it generates no code
#define T_CS_H // No macro allocated so it generates no code
#else
#define T_CS_L digitalWrite(TOUCH_CS, LOW)
#define T_CS_H digitalWrite(TOUCH_CS, HIGH)
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Make sure SPI default pins are assigned if not specified by user or set to -1
////////////////////////////////////////////////////////////////////////////////////////
#ifndef TFT_MISO
#define TFT_MISO -1
#endif
#ifndef TFT_MOSI
#define TFT_MOSI -1
#endif
#ifndef TFT_SCLK
#define TFT_SCLK -1
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Macros to write commands/pixel colour data to an ILI9488 TFT
////////////////////////////////////////////////////////////////////////////////////////
#if defined (ILI9488_DRIVER) // 16 bit colour converted to 3 bytes for 18 bit RGB
// Write 8 bits to TFT
#define tft_Write_8(C) spi_.transfer(C)
// Convert 16 bit colour to 18 bit and write in 3 bytes
#define tft_Write_16(C) spi_.transfer(((C) & 0xF800)>>8); \
spi_.transfer(((C) & 0x07E0)>>3); \
spi_.transfer(((C) & 0x001F)<<3)
// Convert swapped byte 16 bit colour to 18 bit and write in 3 bytes
#define tft_Write_16S(C) spi_.transfer((C) & 0xF8); \
spi_.transfer(((C) & 0xE000)>>11 | ((C) & 0x07)<<5); \
spi_.transfer(((C) & 0x1F00)>>5)
// Write 32 bits to TFT
#define tft_Write_32(C) spi_.transfer16((C)>>16); spi_.transfer16((uint16_t)(C))
// Write two address coordinates
#define tft_Write_32C(C,D) spi_.transfer16(C); spi_.transfer16(D)
// Write same value twice
#define tft_Write_32D(C) spi_.transfer16(C); spi_.transfer16(C)
#else
////////////////////////////////////////////////////////////////////////////////////////
// Macros to write commands/pixel colour data to an Raspberry Pi TFT
////////////////////////////////////////////////////////////////////////////////////////
#if defined (RPI_DISPLAY_TYPE)
// RPi TFT type always needs 16 bit transfers
#define tft_Write_8(C) spi_.transfer(0); spi_.transfer(C)
////////////////////////////////////////////////////////////////////////////////////////
// Macros for all other SPI displays
////////////////////////////////////////////////////////////////////////////////////////
#else
// K210 low level SPI writes for 8, 16 and 32 bit values
// Write 8 bits
#define tft_Write_8(C) tft_write_a_byte(C)
// Write 16 bits with corrected endianess for 16 bit colours
#define tft_Write_16(C) tft_write_a_half(C)
// Write 16 bits
#define tft_Write_16S(C) tft_write_a_half(((C)>>8 & 0xFF) | ((C)<<8))
// Write 32 bits
#define tft_Write_32(C) tft_write_a_word(C)
// Write two address coordinates
#define tft_Write_32C(C,D) tft_write_a_word((C)<<16 | (D))
// Write same value twice
#define tft_Write_32D(C) tft_write_a_word((C)<<16 | (C))
#endif
#endif
////////////////////////////////////////////////////////////////////////////////////////
// Macros to read from display using SPI or software SPI
////////////////////////////////////////////////////////////////////////////////////////
#if defined (TFT_SDA_READ)
// Macros to support a bit banged function call for K210 and bi-directional SDA pin
#define TFT_eSPI_ENABLE_8_BIT_READ // Enable tft_Read_8();
#define SCLK_L digitalWrite(TFT_SCLK, LOW)
#define SCLK_H digitalWrite(TFT_SCLK, LOW)
#else
// Use a SPI read transfer
#define tft_Read_8() tft_read_a_byte()
#endif
#endif // Header end