Merge branch 'master' of github.com:btx000/Kenduino-core

This commit is contained in:
Neucrack
2019-04-01 18:41:45 +08:00
10 changed files with 13 additions and 488 deletions

399
cores/arduino/SPI.cpp Normal file
View File

@@ -0,0 +1,399 @@
#include "SPI.h"
#include "stdio.h"
#include "utils.h"
#include "fpioa.h"
#include "stdint.h"
#include "stdbool.h"
#include "./kendryte-standalone-sdk/lib/drivers/include/spi.h"
#include "SPI_hal.h"
#include "sysctl.h"
SPIClass SPI;
extern volatile spi_t *const spi[4];
static spi_transfer_width_t sipeed_spi_get_frame_size(size_t data_bit_length)
{
if (data_bit_length < 8)
return SPI_TRANS_CHAR;
else if (data_bit_length < 16)
return SPI_TRANS_SHORT;
return SPI_TRANS_INT;
}
static void sipeed_spi_set_tmod(uint8_t spi_num, uint32_t tmod)
{
configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2);
volatile spi_t *spi_handle = spi[spi_num];
uint8_t tmod_offset = 0;
switch(spi_num)
{
case 0:
case 1:
tmod_offset = 8;
break;
case 2:
configASSERT(!"Spi Bus 2 Not Support!");
break;
case 3:
default:
tmod_offset = 10;
break;
}
set_bit(&spi_handle->ctrlr0, 3 << tmod_offset, tmod << tmod_offset);
}
/**
*
* @param chip_select -1: not use cs
*/
void sipeed_spi_transfer_data_standard(spi_device_num_t spi_num, int8_t chip_select, const uint8_t *tx_buff,uint8_t *rx_buff, size_t len)
{
configASSERT(spi_num < SPI_DEVICE_MAX && spi_num != 2);
configASSERT(len > 0);
size_t index, fifo_len;
size_t rx_len = len;
size_t tx_len = rx_len;
sipeed_spi_set_tmod(spi_num, SPI_TMOD_TRANS_RECV);
volatile spi_t *spi_handle = spi[spi_num];
uint8_t dfs_offset;
switch(spi_num){
case 0:
case 1:
dfs_offset = 16;
break;
case 2:
configASSERT(!"Spi Bus 2 Not Support!");
break;
case 3:
default:
dfs_offset = 0;
break;
}
uint32_t data_bit_length = (spi_handle->ctrlr0 >> dfs_offset) & 0x1F;
spi_transfer_width_t frame_width = sipeed_spi_get_frame_size(data_bit_length);
spi_handle->ctrlr1 = (uint32_t)(tx_len/frame_width - 1);
spi_handle->ssienr = 0x01;
spi_handle->ser = 1U << chip_select;
uint32_t i = 0;
while (tx_len)
{
fifo_len = 32 - spi_handle->txflr;
fifo_len = fifo_len < tx_len ? fifo_len : tx_len;
switch(frame_width)
{
case SPI_TRANS_INT:
fifo_len = fifo_len / 4 * 4;
for (index = 0; index < fifo_len / 4; index++)
spi_handle->dr[0] = ((uint32_t *)tx_buff)[i++];
break;
case SPI_TRANS_SHORT:
fifo_len = fifo_len / 2 * 2;
for (index = 0; index < fifo_len / 2; index++)
spi_handle->dr[0] = ((uint16_t *)tx_buff)[i++];
break;
default:
for (index = 0; index < fifo_len; index++)
spi_handle->dr[0] = tx_buff[i++];
break;
}
tx_len -= fifo_len;
}
while ((spi_handle->sr & 0x05) != 0x04)
;
if(rx_buff)
{
i = 0;
while (rx_len)
{
fifo_len = spi_handle->rxflr;
fifo_len = fifo_len < rx_len ? fifo_len : rx_len;
switch(frame_width)
{
case SPI_TRANS_INT:
fifo_len = fifo_len / 4 * 4;
for (index = 0; index < fifo_len / 4; index++)
((uint32_t *)rx_buff)[i++] = spi_handle->dr[0];
break;
case SPI_TRANS_SHORT:
fifo_len = fifo_len / 2 * 2;
for (index = 0; index < fifo_len / 2; index++)
((uint16_t *)rx_buff)[i++] = (uint16_t)spi_handle->dr[0];
break;
default:
for (index = 0; index < fifo_len; index++)
rx_buff[i++] = (uint8_t)spi_handle->dr[0];
break;
}
rx_len -= fifo_len;
}
}
spi_handle->ser = 0x00;
spi_handle->ssienr = 0x00;
}
void sipeed_spi_deinit(spi_device_num_t spi_num)
{
volatile spi_t *spi_handle = spi[spi_num];
spi_handle->ssienr = 0x00;
sysctl_clock_disable( sysctl_clock_t(SYSCTL_CLOCK_SPI0 + spi_num));
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef struct{
int8_t pin;
bool used;
} spi_ss_t;
static spi_ss_t g_ss_table[2][4]={
{//SPI0
{.pin = -1, .used = false},
{.pin = -1, .used = false},
{.pin = -1, .used = false},
{.pin = -1, .used = false}
},
{//SPI1
{.pin = -1, .used = false},
{.pin = -1, .used = false},
{.pin = -1, .used = false},
{.pin = -1, .used = false}
}
};
int8_t getSsByPin(uint8_t spi, int8_t pin)
{
uint8_t i;
if(pin<0)
return -1;
for(i=0; i<4; ++i)
{
if(g_ss_table[spi][i].used && g_ss_table[spi][i].pin == pin)
return i;
}
return -1;
}
int8_t getSsNumLast(uint8_t spi)
{
uint8_t i=0, count=0;
for(i=0; i<4; ++i)
{
if(!g_ss_table[spi][i].used)
++count;
}
return count;
}
bool checkSs(uint8_t spi, int8_t ss)
{
int8_t ssPeriph;
if( ss < 0) // not use ss
return true;
ssPeriph = getSsByPin(spi, ss);
if(ssPeriph >= 0)
return true;
if(getSsNumLast(spi) > 0)
return true;
return false;
}
int8_t setSs(uint8_t spi, int8_t pin)
{
uint8_t i=0;
for(i=0; i<4; ++i)
{
if(!g_ss_table[spi][i].used)
{
g_ss_table[spi][i].used = true;
g_ss_table[spi][i].pin = pin;
return i;
}
}
return -1;
}
/**
* @param miso -1: not use miso
* @param mosi must >= 0
* @param ss -1: not use hardware ss
*/
bool checkPinParam(uint8_t spi, int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
{
if(!checkSs(spi, ss))
return false;
//TODO:
return true;
}
bool checkFreq(uint32_t freq)
{
return true;
}
bool checkBitOder(uint8_t bitOrder)
{
//TODO: support LSB
if(bitOrder!=SPI_MSBFIRST)
return false;
return true;
}
bool checkDataMode(uint8_t dataMode)
{
if(dataMode > SPI_MODE3)
return false;
return true;
}
SPIClass::SPIClass(spi_id_t spi_bus)
:_spiNum(spi_bus), _freq(1000000),
_sck(-1), _miso(-1), _mosi(-1), _ss(-1),
_inTransaction(false),
_initPinsInConstruct(false)
{
configASSERT(_spiNum==SPI_SOFT || _spiNum==SPI0 || _spiNum==SPI1);
}
SPIClass::SPIClass(spi_id_t spi_bus, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint32_t freq)
:_spiNum(spi_bus), _freq(freq),
_sck(sck), _miso(miso), _mosi(mosi), _ss(ss),
_inTransaction(false),
_initPinsInConstruct(true)
{
}
/**
*
* @param ss -1: not use
*/
void SPIClass::begin(int8_t sck, int8_t miso, int8_t mosi, int8_t ss)
{
if(_initPinsInConstruct)
{
sck = _sck;
miso = _miso;
mosi = _mosi;
ss = _ss;
}
configASSERT(checkPinParam(_spiNum, sck, miso, mosi, ss));
if(_spiNum == SPI_SOFT)
{
configASSERT(!"Soft SPI Not Support Yet!");
return ;
}
//hardware SPI
if(_spiNum == SPI0)
{
fpioa_set_function(sck, FUNC_SPI0_SCLK);
if( ss >= 0)
{
fpioa_function_t a = (fpioa_function_t)(FUNC_SPI0_SS0+setSs(_spiNum, ss));
fpioa_set_function(ss, a);
}
fpioa_set_function(mosi, FUNC_SPI0_D0);
if(miso>=0)
fpioa_set_function(miso, FUNC_SPI0_D1);
}
else if(_spiNum == SPI1)
{
fpioa_set_function(sck, FUNC_SPI1_SCLK);
if( ss >= 0)
{
fpioa_set_function(ss, (fpioa_function_t)(FUNC_SPI1_SS0+setSs(_spiNum, ss)));
}
fpioa_set_function(mosi, FUNC_SPI1_D0);
if(miso>=0)
fpioa_set_function(miso, FUNC_SPI1_D1);
}
_mosi = mosi;
_miso = miso;
_sck = sck;
_ss = ss;
_ssPeriph = getSsByPin(_spiNum, ss);
if(_ssPeriph<0)
_ssPeriph = 0; // default to cs0 TODO: optimize?
spi_init(spi_device_num_t(_spiNum), spi_work_mode_t(_dataMode), SPI_FF_STANDARD, 8, 0);
spi_set_clk_rate(spi_device_num_t(_spiNum), _freq);
}
void SPIClass::end()
{
sipeed_spi_deinit(spi_device_num_t(_spiNum));
}
void SPIClass::setBitOrder(uint8_t bitOrder)
{
//TODO: support LSB
configASSERT(bitOrder==SPI_MSBFIRST);
}
void SPIClass::setDataMode(uint8_t dataMode)
{
_dataMode = dataMode;
spi_init(spi_device_num_t(_spiNum), spi_work_mode_t(_dataMode), SPI_FF_STANDARD, 8, 0);
}
void SPIClass::setFrequency(uint32_t freq)
{
_freq = freq;
spi_set_clk_rate(spi_device_num_t(_spiNum), _freq);
}
void SPIClass::beginTransaction(SPISettings settings)
{
SPI_MUTEX_LOCK();
_inTransaction = true;
if( settings._freq!=_freq || settings._dataMode!=_dataMode || settings._bitOrder!=_bitOrder)
{
_dataMode = settings._dataMode;
_bitOrder = settings._bitOrder; //TODO: bit order
_freq = settings._freq;
spi_init(spi_device_num_t(_spiNum), spi_work_mode_t(_dataMode), SPI_FF_STANDARD, 8, 0);
spi_set_clk_rate(spi_device_num_t(_spiNum), _freq);
}
}
void SPIClass::endTransaction(void)
{
_inTransaction = false;
SPI_MUTEX_UNLOCK();
}
void SPIClass::transfer(uint8_t * data, uint32_t size)
{
sipeed_spi_transfer_data_standard(spi_device_num_t(_spiNum), _ssPeriph, data, NULL, size);
}
uint8_t SPIClass::transfer(uint8_t data)
{
uint8_t temp;
sipeed_spi_transfer_data_standard(spi_device_num_t(_spiNum), _ssPeriph, &data, &temp, 1);
return temp;
}
void SPIClass::transferBytes(uint8_t * data, uint8_t * out, uint32_t size)
{
sipeed_spi_transfer_data_standard(spi_device_num_t(_spiNum), _ssPeriph, data, out, size);
}
SPISettings::SPISettings(uint32_t freq, uint8_t bitOrder, uint8_t dataMode)
:_freq(freq), _bitOrder(bitOrder), _dataMode(dataMode)
{
configASSERT(checkFreq(freq));
configASSERT(checkBitOder(bitOrder));
configASSERT(checkDataMode(dataMode));
}

78
cores/arduino/SPI.h Normal file
View File

@@ -0,0 +1,78 @@
#ifndef __SPI_H
#define __SPI_H
#include "stdint.h"
typedef enum{
SPI_SOFT = -1,
SPI0 = 0,
SPI1,
SPI2,
SPI3,
SPI_MAX
} spi_id_t;
#define SPI_LSBFIRST 0
#define SPI_MSBFIRST 1
#define SPI_MODE0 0
#define SPI_MODE1 1
#define SPI_MODE2 2
#define SPI_MODE3 3
class SPISettings
{
public:
SPISettings() :_freq(1000000), _bitOrder(SPI_MSBFIRST), _dataMode(SPI_MODE0) {}
SPISettings(uint32_t freq, uint8_t bitOrder, uint8_t dataMode);
uint32_t _freq;
uint8_t _bitOrder;
uint8_t _dataMode;
};
class SPIClass
{
private:
spi_id_t _spiNum;
uint32_t _freq;
int8_t _sck;
int8_t _miso;
int8_t _mosi;
int8_t _ss; //pin
int8_t _ssPeriph; //peripheral
uint8_t _dataMode;
uint8_t _bitOrder;
bool _inTransaction;
bool _initPinsInConstruct;
public:
SPIClass(spi_id_t spi_bus = SPI1);
/*
* API just for k210
*/
SPIClass(spi_id_t spi_bus, int8_t sck, int8_t miso, int8_t mosi, int8_t ss, uint32_t freq = 1000000);
void begin(int8_t sck=27, int8_t miso=26, int8_t mosi=28, int8_t ss=-1);
void end();
void setBitOrder(uint8_t bitOrder);
void setDataMode(uint8_t dataMode);
void setFrequency(uint32_t freq);
void beginTransaction(SPISettings settings);
void endTransaction(void);
void transfer(uint8_t * data, uint32_t size);
uint8_t transfer(uint8_t data);
void transferBytes(uint8_t * data, uint8_t * out, uint32_t size);
// special
spi_id_t busId(){ return _spiNum; }
};
extern SPIClass SPI;
#endif //__SPI_H

107
cores/arduino/st7789.c Normal file
View File

@@ -0,0 +1,107 @@
#include "st7789.h"
static uint8_t g_gpio_dcx;
static int8_t g_gpio_rst;
static spi_device_num_t g_spi_num;
static dmac_channel_number_t g_dma_ch;
static uint8_t g_ss;
static void init_dcx(uint8_t dcx, int8_t dcx_pin)
{
fpioa_set_function(dcx_pin , FUNC_GPIO0 + dcx);
g_gpio_dcx = dcx;
gpio_set_drive_mode(g_gpio_dcx, GPIO_DM_OUTPUT);
gpio_set_pin(g_gpio_dcx, GPIO_PV_HIGH);
}
static void set_dcx_control(void)
{
gpio_set_pin(g_gpio_dcx, GPIO_PV_LOW);
}
static void set_dcx_data(void)
{
gpio_set_pin(g_gpio_dcx, GPIO_PV_HIGH);
}
static void init_rst(uint8_t rst, int8_t rst_pin)
{
g_gpio_rst = rst;
if( rst_pin < 0)
return ;
fpioa_set_function(rst_pin , FUNC_GPIO0 + rst);
gpio_set_drive_mode(g_gpio_rst, GPIO_DM_OUTPUT);
gpio_set_pin(g_gpio_rst, GPIO_PV_HIGH);
}
static void set_rst(uint8_t val)
{
if(g_gpio_rst < 0)
return ;
gpio_set_pin(g_gpio_rst, val);
}
void tft_set_clk_freq(uint32_t freq)
{
spi_set_clk_rate(g_spi_num, freq);
}
void 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)
{
g_spi_num = spi;
g_dma_ch = dma_ch;
g_ss = ss;
init_dcx(dcx, dcx_pin);
init_rst(rst, rst_pin);
set_rst(0);
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
tft_set_clk_freq(freq);
set_rst(1);
}
void tft_write_command(uint8_t cmd)
{
set_dcx_control();
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
spi_init_non_standard(g_spi_num, 8 /*instrction length*/, 0 /*address length*/, 0 /*wait cycles*/,
SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
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)
{
set_dcx_data();
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 8, 0);
spi_init_non_standard(g_spi_num, 8 /*instrction length*/, 0 /*address length*/, 0 /*wait cycles*/,
SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
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)
{
set_dcx_data();
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 16, 0);
spi_init_non_standard(g_spi_num, 16 /*instrction length*/, 0 /*address length*/, 0 /*wait cycles*/,
SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
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)
{
set_dcx_data();
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0);
spi_init_non_standard(g_spi_num, 0 /*instrction length*/, 32 /*address length*/, 0 /*wait cycles*/,
SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
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)
{
set_dcx_data();
spi_init(g_spi_num, SPI_WORK_MODE_0, SPI_FF_OCTAL, 32, 0);
spi_init_non_standard(g_spi_num, 0 /*instrction length*/, 32 /*address length*/, 0 /*wait cycles*/,
SPI_AITM_AS_FRAME_FORMAT /*spi address trans mode*/);
spi_fill_data_dma(g_dma_ch, g_spi_num, g_ss, data_buf, length);
}

107
cores/arduino/st7789.h Normal file
View File

@@ -0,0 +1,107 @@
#ifndef _ST7789_H_
#define _ST7789_H_
#include <stdint.h>
#include "gpio.h"
#include "fpioa.h"
#include "./kendryte-standalone-sdk/lib/drivers/include/spi.h"
#ifdef __cplusplus
extern "C" {
#endif
/* clang-format off */
#define NO_OPERATION 0x00
#define SOFTWARE_RESET 0x01
#define READ_ID 0x04
#define READ_STATUS 0x09
#define READ_POWER_MODE 0x0A
#define READ_MADCTL 0x0B
#define READ_PIXEL_FORMAT 0x0C
#define READ_IMAGE_FORMAT 0x0D
#define READ_SIGNAL_MODE 0x0E
#define READ_SELT_DIAG_RESULT 0x0F
#define SLEEP_ON 0x10
#define SLEEP_OFF 0x11
#define PARTIAL_DISPALY_ON 0x12
#define NORMAL_DISPALY_ON 0x13
#define INVERSION_DISPALY_OFF 0x20
#define INVERSION_DISPALY_ON 0x21
#define GAMMA_SET 0x26
#define DISPALY_OFF 0x28
#define DISPALY_ON 0x29
#define HORIZONTAL_ADDRESS_SET 0x2A
#define VERTICAL_ADDRESS_SET 0x2B
#define MEMORY_WRITE 0x2C
#define COLOR_SET 0x2D
#define MEMORY_READ 0x2E
#define PARTIAL_AREA 0x30
#define VERTICAL_SCROL_DEFINE 0x33
#define TEAR_EFFECT_LINE_OFF 0x34
#define TEAR_EFFECT_LINE_ON 0x35
#define MEMORY_ACCESS_CTL 0x36
#define VERTICAL_SCROL_S_ADD 0x37
#define IDLE_MODE_OFF 0x38
#define IDLE_MODE_ON 0x39
#define PIXEL_FORMAT_SET 0x3A
#define WRITE_MEMORY_CONTINUE 0x3C
#define READ_MEMORY_CONTINUE 0x3E
#define SET_TEAR_SCANLINE 0x44
#define GET_SCANLINE 0x45
#define WRITE_BRIGHTNESS 0x51
#define READ_BRIGHTNESS 0x52
#define WRITE_CTRL_DISPALY 0x53
#define READ_CTRL_DISPALY 0x54
#define WRITE_BRIGHTNESS_CTL 0x55
#define READ_BRIGHTNESS_CTL 0x56
#define WRITE_MIN_BRIGHTNESS 0x5E
#define READ_MIN_BRIGHTNESS 0x5F
#define READ_ID1 0xDA
#define READ_ID2 0xDB
#define READ_ID3 0xDC
#define RGB_IF_SIGNAL_CTL 0xB0
#define NORMAL_FRAME_CTL 0xB1
#define IDLE_FRAME_CTL 0xB2
#define PARTIAL_FRAME_CTL 0xB3
#define INVERSION_CTL 0xB4
#define BLANK_PORCH_CTL 0xB5
#define DISPALY_FUNCTION_CTL 0xB6
#define ENTRY_MODE_SET 0xB7
#define BACKLIGHT_CTL1 0xB8
#define BACKLIGHT_CTL2 0xB9
#define BACKLIGHT_CTL3 0xBA
#define BACKLIGHT_CTL4 0xBB
#define BACKLIGHT_CTL5 0xBC
#define BACKLIGHT_CTL7 0xBE
#define BACKLIGHT_CTL8 0xBF
#define POWER_CTL1 0xC0
#define POWER_CTL2 0xC1
#define VCOM_CTL1 0xC5
#define VCOM_CTL2 0xC7
#define NV_MEMORY_WRITE 0xD0
#define NV_MEMORY_PROTECT_KEY 0xD1
#define NV_MEMORY_STATUS_READ 0xD2
#define READ_ID4 0xD3
#define POSITIVE_GAMMA_CORRECT 0xE0
#define NEGATIVE_GAMMA_CORRECT 0xE1
#define DIGITAL_GAMMA_CTL1 0xE2
#define DIGITAL_GAMMA_CTL2 0xE3
#define INTERFACE_CTL 0xF6
/* clang-format on */
void 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);
void tft_set_clk_freq(uint32_t freq);
void tft_write_command(uint8_t cmd);
void tft_write_byte(uint8_t *data_buf, uint32_t length);
void tft_write_half(uint16_t *data_buf, uint32_t length);
void tft_write_word(uint32_t *data_buf, uint32_t length);
void tft_fill_data(uint32_t *data_buf, uint32_t length);
#ifdef __cplusplus
}
#endif
#endif