1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-20 06:45:16 +03:00

efactor MAX7456 driver code

This commit is contained in:
Marcin Baliniak 2016-09-25 11:42:53 +02:00
parent 0892c4786b
commit 171b03bfb7
4 changed files with 208 additions and 191 deletions

View file

@ -37,42 +37,44 @@
#include "max7456.h"
#include "max7456_symbols.h"
// On shared SPI bus we want to change clock for OSD chip and restore for other devices
//on shared SPI buss we want to change clock for OSD chip and restore for other devices
#ifdef MAX7456_SPI_CLK
#define ENABLE_MAX7456 {spiSetDivisor(MAX7456_SPI_INSTANCE, MAX7456_SPI_CLK);IOLo(max7456CsPin);}
#define ENABLE_MAX7456 {spiSetDivisor(MAX7456_SPI_INSTANCE, MAX7456_SPI_CLK);IOLo(max7456CsPin);}
#else
#define ENABLE_MAX7456 IOLo(max7456CsPin)
#define ENABLE_MAX7456 IOLo(max7456CsPin)
#endif
#ifdef MAX7456_RESTORE_CLK
#define DISABLE_MAX7456 {IOHi(max7456CsPin);spiSetDivisor(MAX7456_SPI_INSTANCE, MAX7456_RESTORE_CLK);}
#define DISABLE_MAX7456 {IOHi(max7456CsPin);spiSetDivisor(MAX7456_SPI_INSTANCE, MAX7456_RESTORE_CLK);}
#else
#define DISABLE_MAX7456 IOHi(max7456CsPin)
#define DISABLE_MAX7456 IOHi(max7456CsPin)
#endif
uint16_t maxScreenSize = VIDEO_BUFFER_CHARS_PAL;
// we write everything in SCREEN_BUFFER and then comapre
// SCREEN_BUFFER with SHADOW_BUFFER to upgrade only changed chars
// this solution is faster then redraw all screen
static uint8_t SCREEN_BUFFER[VIDEO_BUFFER_CHARS_PAL + 40]; //for faster writes we use memcpy so we need some space to don't overwrite buffer
static uint8_t SHADOW_BUFFER[VIDEO_BUFFER_CHARS_PAL];
// we write everything in screenBuffer and then comapre
// screenBuffer with shadowBuffer to upgrade only changed chars
// this solution is faster then redraw all screen
static uint8_t screenBuffer[VIDEO_BUFFER_CHARS_PAL+40]; //for faster writes we use memcpy so we need some space to don't overwrite buffer
static uint8_t shadowBuffer[VIDEO_BUFFER_CHARS_PAL];
//max chars to update in one idle
#define MAX_CHARS2UPDATE 100
#ifdef MAX7456_DMA_CHANNEL_TX
volatile bool dmaTxInProgress = false;
#endif // MAX7456_DMA_CHANNEL_TX
volatile bool dmaTransactionInProgress = false;
#endif
static uint8_t spiBuffer[MAX_CHARS2UPDATE * 6];
static uint8_t spiBuff[MAX_CHARS2UPDATE*6];
static uint8_t videoSignalCfg = 0;
static uint8_t videoSignalReg = VIDEO_MODE_PAL | OSD_ENABLE; //PAL by default
static bool max7456Lock = false;
static IO_t max7456CsPin = IO_NONE;
static bool fontIsLoading = false;
static uint8_t videoSignalCfg = 0;
static uint8_t videoSignalReg = VIDEO_MODE_PAL | OSD_ENABLE; //PAL by default
static bool max7456Lock = false;
static bool fontIsLoading = false;
static IO_t max7456CsPin = IO_NONE;
static uint8_t max7456_send(uint8_t add, uint8_t data) {
static uint8_t max7456_send(uint8_t add, uint8_t data)
{
spiTransferByte(MAX7456_SPI_INSTANCE, add);
return spiTransferByte(MAX7456_SPI_INSTANCE, data);
}
@ -82,15 +84,15 @@ static void max7456_send_dma(void* tx_buffer, void* rx_buffer, uint16_t buffer_s
DMA_InitTypeDef DMA_InitStructure;
#ifdef MAX7456_DMA_CHANNEL_RX
static uint16_t dummy[] = {0xffff};
#else // MAX7456_DMA_CHANNEL_RX
#else
UNUSED(rx_buffer);
#endif // MAX7456_DMA_CHANNEL_RX
while (dmaTxInProgress); // Wait for prev DMA transaction
#endif
while (dmaTransactionInProgress); // Wait for prev DMA transaction
DMA_DeInit(MAX7456_DMA_CHANNEL_TX);
#ifdef MAX7456_DMA_CHANNEL_RX
DMA_DeInit(MAX7456_DMA_CHANNEL_RX);
#endif // MAX7456_DMA_CHANNEL_RX
#endif
// Common to both channels
DMA_StructInit(&DMA_InitStructure);
@ -107,24 +109,24 @@ static void max7456_send_dma(void* tx_buffer, void* rx_buffer, uint16_t buffer_s
#ifdef STM32F4
DMA_InitStructure.DMA_Memory0BaseAddr = rx_buffer ? (uint32_t)rx_buffer : (uint32_t)(dummy);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
#else // STM32F4
#else
DMA_InitStructure.DMA_MemoryBaseAddr = rx_buffer ? (uint32_t)rx_buffer : (uint32_t)(dummy);
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
#endif // STM32F4
#endif
DMA_InitStructure.DMA_MemoryInc = rx_buffer ? DMA_MemoryInc_Enable : DMA_MemoryInc_Disable;
DMA_Init(MAX7456_DMA_CHANNEL_RX, &DMA_InitStructure);
DMA_Cmd(MAX7456_DMA_CHANNEL_RX, ENABLE);
#endif // MAX7456_DMA_CHANNEL_RX
#endif
// Tx channel
#ifdef STM32F4
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)tx_buffer; //max7456_screen;
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
#else // STM32F4
#else
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)tx_buffer; //max7456_screen;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
#endif // STM32F4
#endif
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_Init(MAX7456_DMA_CHANNEL_TX, &DMA_InitStructure);
@ -132,18 +134,18 @@ static void max7456_send_dma(void* tx_buffer, void* rx_buffer, uint16_t buffer_s
#ifdef MAX7456_DMA_CHANNEL_RX
DMA_ITConfig(MAX7456_DMA_CHANNEL_RX, DMA_IT_TC, ENABLE);
#else // MAX7456_DMA_CHANNEL_RX
#else
DMA_ITConfig(MAX7456_DMA_CHANNEL_TX, DMA_IT_TC, ENABLE);
#endif // MAX7456_DMA_CHANNEL_RX
#endif
// Enable SPI TX/RX request
ENABLE_MAX7456;
dmaTxInProgress = true;
dmaTransactionInProgress = true;
SPI_I2S_DMACmd(MAX7456_SPI_INSTANCE,
#ifdef MAX7456_DMA_CHANNEL_RX
SPI_I2S_DMAReq_Rx |
#endif // MAX7456_DMA_CHANNEL_RX
#endif
SPI_I2S_DMAReq_Tx, ENABLE);
}
@ -152,7 +154,7 @@ void max7456_dma_irq_handler(dmaChannelDescriptor_t* descriptor) {
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) {
#ifdef MAX7456_DMA_CHANNEL_RX
DMA_Cmd(MAX7456_DMA_CHANNEL_RX, DISABLE);
#endif // MAX7456_DMA_CHANNEL_RX
#endif
// make sure spi dmd transfer is complete
while (SPI_I2S_GetFlagStatus (MAX7456_SPI_INSTANCE, SPI_I2S_FLAG_TXE) == RESET) {};
while (SPI_I2S_GetFlagStatus (MAX7456_SPI_INSTANCE, SPI_I2S_FLAG_BSY) == SET) {};
@ -170,11 +172,11 @@ void max7456_dma_irq_handler(dmaChannelDescriptor_t* descriptor) {
SPI_I2S_DMACmd(MAX7456_SPI_INSTANCE,
#ifdef MAX7456_DMA_CHANNEL_RX
SPI_I2S_DMAReq_Rx |
#endif // MAX7456_DMA_CHANNEL_RX
#endif
SPI_I2S_DMAReq_Tx, DISABLE);
DISABLE_MAX7456;
dmaTxInProgress = false;
dmaTransactionInProgress = false;
}
if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_HTIF)) {
@ -184,9 +186,11 @@ void max7456_dma_irq_handler(dmaChannelDescriptor_t* descriptor) {
DMA_CLEAR_FLAG(descriptor, DMA_IT_TEIF);
}
}
#endif // MAX7456_DMA_CHANNEL_TX
uint8_t max7456_get_rows_count(void) {
#endif
uint8_t max7456GetRowsCount(void)
{
if (videoSignalReg & VIDEO_MODE_PAL)
return VIDEO_LINES_PAL;
@ -195,11 +199,12 @@ uint8_t max7456_get_rows_count(void) {
//because MAX7456 need some time to detect video system etc. we need to wait for a while to initialize it at startup
//and in case of restart we need to reinitialize chip
void max7456_init2(void) {
void max7456ReInit(void)
{
uint8_t maxScreenRows;
uint8_t srdata = 0;
uint16_t x;
static bool firstInit = true;
static uint8_t firstInit = 1;
//do not init MAX before camera power up correctly
if (millis() < 1500)
@ -239,18 +244,21 @@ void max7456_init2(void) {
DISABLE_MAX7456;
//clear shadow to force redraw all screen in non-dma mode
memset(SHADOW_BUFFER, 0, maxScreenSize);
if (firstInit) {
max7456_refresh_all();
firstInit = false;
memset(shadowBuffer, 0, maxScreenSize);
if (firstInit)
{
max7456RefreshAll();
firstInit = 0;
}
}
//here we init only CS and try to init MAX for first time
void max7456_init(uint8_t videoSystem) {
void max7456Init(uint8_t video_system)
{
#ifdef MAX7456_SPI_CS_PIN
max7456CsPin = IOGetByTag(IO_TAG(MAX7456_SPI_CS_PIN));
#endif // MAX7456_SPI_CS_PIN
#endif
IOInit(max7456CsPin, OWNER_OSD, RESOURCE_SPI_CS, 0);
IOConfigGPIO(max7456CsPin, SPI_IO_CS_CFG);
@ -259,44 +267,48 @@ void max7456_init(uint8_t videoSystem) {
ENABLE_MAX7456;
max7456_send(VM0_REG, MAX7456_RESET);
DISABLE_MAX7456;
videoSignalCfg = videoSystem;
videoSignalCfg = video_system;
#ifdef MAX7456_DMA_CHANNEL_TX
dmaSetHandler(MAX7456_DMA_IRQ_HANDLER_ID, max7456_dma_irq_handler, NVIC_PRIO_MAX7456_DMA, 0);
#endif // MAX7456_DMA_CHANNEL_TX
#endif
//real init will be made letter when driver idle detect
}
//just fill with spaces with some tricks
void max7456_clear_screen(void) {
uint16_t x;
uint32_t *p = (uint32_t*)&SCREEN_BUFFER[0];
for (x = 0; x < VIDEO_BUFFER_CHARS_PAL/4; x++)
p[x] = 0x20202020;
void max7456ClearScreen(void)
{
uint16_t x;
uint32_t *p = (uint32_t*)&screenBuffer[0];
for (x = 0; x < VIDEO_BUFFER_CHARS_PAL/4; x++)
p[x] = 0x20202020;
}
uint8_t* max7456_get_screen_buffer(void) {
return SCREEN_BUFFER;
uint8_t* max7456GetScreenBuffer(void) {
return screenBuffer;
}
void max7456_write_char(uint8_t x, uint8_t y, uint8_t c) {
SCREEN_BUFFER[y*30+x] = c;
void max7456WriteChar(uint8_t x, uint8_t y, uint8_t c)
{
screenBuffer[y*30+x] = c;
}
void max7456_write(uint8_t x, uint8_t y, char *buff) {
uint8_t i = 0;
for (i = 0; *(buff+i); i++)
if (x+i < 30) //do not write over screen
SCREEN_BUFFER[y*30+x+i] = *(buff+i);
void max7456Write(uint8_t x, uint8_t y, char *buff)
{
uint8_t i = 0;
for (i = 0; *(buff+i); i++)
if (x+i < 30) //do not write over screen
screenBuffer[y*30+x+i] = *(buff+i);
}
#ifdef MAX7456_DMA_CHANNEL_TX
uint8_t max7456_dma_in_progres(void) {
return dmaTxInProgress;
bool max7456DmaInProgres(void)
{
return dmaTransactionInProgress;
}
#endif // MAX7456_DMA_CHANNEL_TX
#endif
void max7456_draw_screen(void) {
void max7456DrawScreen(void) {
uint8_t check;
static uint16_t pos = 0;
int k = 0, buff_len=0;
@ -308,20 +320,22 @@ void max7456_draw_screen(void) {
check = max7456_send(VM0_REG | 0x80, 0x00);
DISABLE_MAX7456;
if ( check != videoSignalReg )
max7456_init2();
if ( check != videoSignalReg)
max7456ReInit();
//------------ end of (re)init-------------------------------------
for (k=0; k< MAX_CHARS2UPDATE; k++) {
if (SCREEN_BUFFER[pos] != SHADOW_BUFFER[pos]) {
spiBuffer[buff_len++] = MAX7456ADD_DMAH;
spiBuffer[buff_len++] = pos >> 8;
spiBuffer[buff_len++] = MAX7456ADD_DMAL;
spiBuffer[buff_len++] = pos & 0xff;
spiBuffer[buff_len++] = MAX7456ADD_DMDI;
spiBuffer[buff_len++] = SCREEN_BUFFER[pos];
SHADOW_BUFFER[pos] = SCREEN_BUFFER[pos];
for (k=0; k< MAX_CHARS2UPDATE; k++)
{
if (screenBuffer[pos] != shadowBuffer[pos])
{
spiBuff[buff_len++] = MAX7456ADD_DMAH;
spiBuff[buff_len++] = pos >> 8;
spiBuff[buff_len++] = MAX7456ADD_DMAL;
spiBuff[buff_len++] = pos & 0xff;
spiBuff[buff_len++] = MAX7456ADD_DMDI;
spiBuff[buff_len++] = screenBuffer[pos];
shadowBuffer[pos] = screenBuffer[pos];
k++;
}
@ -332,25 +346,26 @@ void max7456_draw_screen(void) {
}
if (buff_len) {
#ifdef MAX7456_DMA_CHANNEL_TX
#ifdef MAX7456_DMA_CHANNEL_TX
if (buff_len > 0)
max7456_send_dma(spiBuffer, NULL, buff_len);
#else
max7456_send_dma(spiBuff, NULL, buff_len);
#else
ENABLE_MAX7456;
for (k=0; k < buff_len; k++)
spiTransferByte(MAX7456_SPI_INSTANCE, spiBuffer[k]);
spiTransferByte(MAX7456_SPI_INSTANCE, spiBuff[k]);
DISABLE_MAX7456;
#endif // MAX7456_DMA_CHANNEL_TX
#endif // MAX7456_DMA_CHANNEL_TX
}
max7456Lock = 0;
max7456Lock = false;
}
}
// this funcktion refresh all and should not be used when copter is armed
void max7456_refresh_all(void) {
void max7456RefreshAll(void)
{
if (!max7456Lock) {
#ifdef MAX7456_DMA_CHANNEL_TX
while (dmaTxInProgress);
while (dmaTransactionInProgress);
#endif
uint16_t xx;
max7456Lock = true;
@ -359,23 +374,24 @@ void max7456_refresh_all(void) {
max7456_send(MAX7456ADD_DMAL, 0);
max7456_send(MAX7456ADD_DMM, 1);
for (xx = 0; xx < maxScreenSize; ++xx) {
max7456_send(MAX7456ADD_DMDI, SCREEN_BUFFER[xx]);
SHADOW_BUFFER[xx] = SCREEN_BUFFER[xx];
for (xx = 0; xx < maxScreenSize; ++xx)
{
max7456_send(MAX7456ADD_DMDI, screenBuffer[xx]);
shadowBuffer[xx] = screenBuffer[xx];
}
max7456_send(MAX7456ADD_DMDI, 0xFF);
max7456_send(MAX7456ADD_DMM, 0);
DISABLE_MAX7456;
max7456Lock = 0;
max7456Lock = false;
}
}
void max7456_write_nvm(uint8_t char_address, uint8_t *font_data) {
void max7456WriteNvm(uint8_t char_address, uint8_t *font_data) {
uint8_t x;
#ifdef MAX7456_DMA_CHANNEL_TX
while (dmaTxInProgress);
while (dmaTransactionInProgress);
#endif
while (max7456Lock);
max7456Lock = true;
@ -392,9 +408,9 @@ void max7456_write_nvm(uint8_t char_address, uint8_t *font_data) {
max7456_send(MAX7456ADD_CMDI, font_data[x]);
#ifdef LED0_TOGGLE
LED0_TOGGLE;
#else // LED0_TOGGLE
#else
LED1_TOGGLE;
#endif // LED0_TOGGLE
#endif
}
// transfer 54 bytes from shadow ram to NVM
@ -405,7 +421,8 @@ void max7456_write_nvm(uint8_t char_address, uint8_t *font_data) {
DISABLE_MAX7456;
max7456Lock = 0;
max7456Lock = false;
}
#endif // USE_MAX7456
#endif