mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-25 17:25:20 +03:00
MAX7456 driver - add support for SPI DMA
This commit is contained in:
parent
5d385d0019
commit
224043be4e
6 changed files with 301 additions and 147 deletions
|
@ -359,3 +359,4 @@ void spiResetErrorCounter(SPI_TypeDef *instance)
|
|||
if (device != SPIINVALID)
|
||||
spiHardwareMap[device].errorCount = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "drivers/bus_spi.h"
|
||||
#include "drivers/light_led.h"
|
||||
#include "drivers/system.h"
|
||||
#include "drivers/nvic.h"
|
||||
|
||||
#include "max7456.h"
|
||||
#include "max7456_symbols.h"
|
||||
|
@ -36,30 +37,120 @@
|
|||
#define DISABLE_MAX7456 IOHi(max7456CsPin)
|
||||
#define ENABLE_MAX7456 IOLo(max7456CsPin)
|
||||
|
||||
/** Artificial Horizon limits **/
|
||||
#define AHIPITCHMAX 200 // Specify maximum AHI pitch value displayed. Default 200 = 20.0 degrees
|
||||
#define AHIROLLMAX 400 // Specify maximum AHI roll value displayed. Default 400 = 40.0 degrees
|
||||
#define AHISIDEBARWIDTHPOSITION 7
|
||||
#define AHISIDEBARHEIGHTPOSITION 3
|
||||
|
||||
uint16_t max_screen_size;
|
||||
char max7456_screen[VIDEO_BUFFER_CHARS_PAL];
|
||||
static MAX7456_CHAR_TYPE max7456_screen[VIDEO_BUFFER_CHARS_PAL + 5];
|
||||
#define SCREEN_BUFFER ((MAX7456_CHAR_TYPE*)&max7456_screen[3])
|
||||
|
||||
#ifdef MAX7456_DMA_CHANNEL_TX
|
||||
volatile uint8_t dma_transaction_in_progress = 0;
|
||||
#endif
|
||||
|
||||
static uint8_t video_signal_type = 0;
|
||||
static uint8_t max7456_lock = 0;
|
||||
static IO_t max7456CsPin = IO_NONE;
|
||||
|
||||
uint8_t max7456_send(uint8_t add, uint8_t data) {
|
||||
|
||||
MAX7456_CHAR_TYPE* max7456_get_screen_buffer(void) {
|
||||
return SCREEN_BUFFER;
|
||||
}
|
||||
|
||||
static uint8_t max7456_send(uint8_t add, uint8_t data) {
|
||||
spiTransferByte(MAX7456_SPI_INSTANCE, add);
|
||||
return spiTransferByte(MAX7456_SPI_INSTANCE, data);
|
||||
}
|
||||
|
||||
#ifdef MAX7456_DMA_CHANNEL_TX
|
||||
static void max7456_send_dma(void* tx_buffer, void* rx_buffer, uint16_t buffer_size) {
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
#ifdef MAX7456_DMA_CHANNEL_RX
|
||||
static uint16_t dummy[] = {0xffff};
|
||||
#else
|
||||
UNUSED(rx_buffer);
|
||||
#endif
|
||||
while (dma_transaction_in_progress); // Wait for prev DMA transaction
|
||||
|
||||
DMA_DeInit(MAX7456_DMA_CHANNEL_TX);
|
||||
#ifdef MAX7456_DMA_CHANNEL_RX
|
||||
DMA_DeInit(MAX7456_DMA_CHANNEL_RX);
|
||||
#endif
|
||||
|
||||
// Common to both channels
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(MAX7456_SPI_INSTANCE->DR));
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_BufferSize = buffer_size;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Low;
|
||||
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
||||
|
||||
#ifdef MAX7456_DMA_CHANNEL_RX
|
||||
// Rx Channel
|
||||
DMA_InitStructure.DMA_MemoryBaseAddr = rx_buffer ? (uint32_t)rx_buffer : (uint32_t)(dummy);
|
||||
DMA_InitStructure.DMA_MemoryInc = rx_buffer ? DMA_MemoryInc_Enable : DMA_MemoryInc_Disable;
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
|
||||
|
||||
DMA_Init(MAX7456_DMA_CHANNEL_RX, &DMA_InitStructure);
|
||||
DMA_Cmd(MAX7456_DMA_CHANNEL_RX, ENABLE);
|
||||
#endif
|
||||
// Tx channel
|
||||
|
||||
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)tx_buffer; //max7456_screen;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
|
||||
|
||||
DMA_Init(MAX7456_DMA_CHANNEL_TX, &DMA_InitStructure);
|
||||
DMA_Cmd(MAX7456_DMA_CHANNEL_TX, ENABLE);
|
||||
|
||||
#ifdef MAX7456_DMA_CHANNEL_RX
|
||||
DMA_ITConfig(MAX7456_DMA_CHANNEL_RX, DMA_IT_TC, ENABLE);
|
||||
#else
|
||||
DMA_ITConfig(MAX7456_DMA_CHANNEL_TX, DMA_IT_TC, ENABLE);
|
||||
#endif
|
||||
|
||||
// Enable SPI TX/RX request
|
||||
ENABLE_MAX7456;
|
||||
dma_transaction_in_progress = 1;
|
||||
|
||||
SPI_I2S_DMACmd(MAX7456_SPI_INSTANCE,
|
||||
#ifdef MAX7456_DMA_CHANNEL_RX
|
||||
SPI_I2S_DMAReq_Rx |
|
||||
#endif
|
||||
SPI_I2S_DMAReq_Tx, ENABLE);
|
||||
}
|
||||
|
||||
void MAX7456_DMA_IRQ_HANDLER_FUNCTION (void) {
|
||||
if (DMA_GetFlagStatus(MAX7456_DMA_TC_FLAG)) {
|
||||
#ifdef MAX7456_DMA_CHANNEL_RX
|
||||
DMA_Cmd(MAX7456_DMA_CHANNEL_RX, DISABLE);
|
||||
#else
|
||||
//Empty RX buffer. RX DMA takes care of it if enabled
|
||||
while (SPI_I2S_GetFlagStatus(MAX7456_SPI_INSTANCE, SPI_I2S_FLAG_RXNE) == SET) {
|
||||
MAX7456_SPI_INSTANCE->DR;
|
||||
}
|
||||
#endif
|
||||
DMA_Cmd(MAX7456_DMA_CHANNEL_TX, DISABLE);
|
||||
|
||||
DMA_ClearFlag(MAX7456_DMA_TC_FLAG);
|
||||
|
||||
SPI_I2S_DMACmd(MAX7456_SPI_INSTANCE,
|
||||
#ifdef MAX7456_DMA_CHANNEL_RX
|
||||
SPI_I2S_DMAReq_Rx |
|
||||
#endif
|
||||
SPI_I2S_DMAReq_Tx, DISABLE);
|
||||
|
||||
DISABLE_MAX7456;
|
||||
for (uint16_t x = 0; x < max_screen_size; x++)
|
||||
max7456_screen[x + 3] = MAX7456ADD_DMDI;
|
||||
dma_transaction_in_progress = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void max7456_init(uint8_t video_system) {
|
||||
uint8_t max_screen_rows;
|
||||
uint8_t srdata = 0;
|
||||
uint16_t x;
|
||||
char buf[LINE];
|
||||
|
||||
#ifdef MAX7456_SPI_CS_PIN
|
||||
max7456CsPin = IOGetByTag(IO_TAG(MAX7456_SPI_CS_PIN));
|
||||
|
@ -68,7 +159,7 @@ void max7456_init(uint8_t video_system) {
|
|||
IOConfigGPIO(max7456CsPin, SPI_IO_CS_CFG);
|
||||
|
||||
//Minimum spi clock period for max7456 is 100ns (10Mhz)
|
||||
spiSetDivisor(MAX7456_SPI_INSTANCE, SPI_9MHZ_CLOCK_DIVIDER);
|
||||
spiSetDivisor(MAX7456_SPI_INSTANCE, SPI_STANDARD_CLOCK);
|
||||
|
||||
delay(1000);
|
||||
// force soft reset on Max7456
|
||||
|
@ -112,94 +203,73 @@ void max7456_init(uint8_t video_system) {
|
|||
|
||||
DISABLE_MAX7456;
|
||||
delay(100);
|
||||
|
||||
for (x = 0; x < max_screen_size; x++)
|
||||
SCREEN_BUFFER[x] = MAX7456_CHAR(0);
|
||||
|
||||
#ifdef MAX7456_DMA_CHANNEL_TX
|
||||
max7456_screen[0] = (uint16_t)(MAX7456ADD_DMAH | (0 << 8));
|
||||
max7456_screen[1] = (uint16_t)(MAX7456ADD_DMAL | (0 << 8));
|
||||
max7456_screen[2] = (uint16_t)(MAX7456ADD_DMM | (1 << 8));
|
||||
max7456_screen[max_screen_size + 3] = (uint16_t)(MAX7456ADD_DMDI | (0xFF << 8));
|
||||
max7456_screen[max_screen_size + 4] = (uint16_t)(MAX7456ADD_DMM | (0 << 8));
|
||||
|
||||
RCC_AHBPeriphClockCmd(MAX7456_DMA_PERIPH_CLOCK, ENABLE);
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
|
||||
NVIC_InitStructure.NVIC_IRQChannel = MAX7456_DMA_IRQ_HANDLER_ID;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_PRIORITY_BASE(NVIC_PRIO_MAX7456_DMA);
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_PRIORITY_SUB(NVIC_PRIO_MAX7456_DMA);
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Copy string from ram into screen buffer
|
||||
void max7456_write_string(const char *string, int16_t address) {
|
||||
char *dest;
|
||||
MAX7456_CHAR_TYPE *dest;
|
||||
|
||||
if (address >= 0)
|
||||
dest = max7456_screen + address;
|
||||
dest = SCREEN_BUFFER + address;
|
||||
else
|
||||
dest = max7456_screen + (max_screen_size + address);
|
||||
dest = SCREEN_BUFFER + (max_screen_size + address);
|
||||
|
||||
while(*string && dest < (max7456_screen + max_screen_size))
|
||||
*dest++ = *string++;
|
||||
}
|
||||
|
||||
|
||||
// Write the artifical horizon to the screen buffer
|
||||
void max7456_artificial_horizon(int rollAngle, int pitchAngle, uint8_t show_sidebars) {
|
||||
uint16_t position = 194;
|
||||
|
||||
if(pitchAngle>AHIPITCHMAX) pitchAngle=AHIPITCHMAX;
|
||||
if(pitchAngle<-AHIPITCHMAX) pitchAngle=-AHIPITCHMAX;
|
||||
if(rollAngle>AHIROLLMAX) rollAngle=AHIROLLMAX;
|
||||
if(rollAngle<-AHIROLLMAX) rollAngle=-AHIROLLMAX;
|
||||
|
||||
for(uint8_t X=0; X<=8; X++) {
|
||||
if (X==4) X=5;
|
||||
int Y = (rollAngle * (4-X)) / 64;
|
||||
Y -= pitchAngle / 8;
|
||||
Y += 41;
|
||||
if(Y >= 0 && Y <= 81) {
|
||||
uint16_t pos = position -7 + LINE*(Y/9) + 3 - 4*LINE + X;
|
||||
max7456_screen[pos] = SYM_AH_BAR9_0+(Y%9);
|
||||
}
|
||||
}
|
||||
max7456_screen[position-1] = SYM_AH_CENTER_LINE;
|
||||
max7456_screen[position+1] = SYM_AH_CENTER_LINE_RIGHT;
|
||||
max7456_screen[position] = SYM_AH_CENTER;
|
||||
|
||||
if (show_sidebars) {
|
||||
// Draw AH sides
|
||||
int8_t hudwidth = AHISIDEBARWIDTHPOSITION;
|
||||
int8_t hudheight = AHISIDEBARHEIGHTPOSITION;
|
||||
for(int8_t X=-hudheight; X<=hudheight; X++) {
|
||||
max7456_screen[position-hudwidth+(X*LINE)] = SYM_AH_DECORATION;
|
||||
max7456_screen[position+hudwidth+(X*LINE)] = SYM_AH_DECORATION;
|
||||
}
|
||||
// AH level indicators
|
||||
max7456_screen[position-hudwidth+1] = SYM_AH_LEFT;
|
||||
max7456_screen[position+hudwidth-1] = SYM_AH_RIGHT;
|
||||
while(*string && dest < (SCREEN_BUFFER + max_screen_size)) {
|
||||
*dest++ = MAX7456_CHAR(*string++);
|
||||
}
|
||||
}
|
||||
|
||||
void max7456_draw_screen(void) {
|
||||
uint16_t xx;
|
||||
if (!max7456_lock) {
|
||||
ENABLE_MAX7456;
|
||||
for (xx = 0; xx < max_screen_size; ++xx) {
|
||||
max7456_send(MAX7456ADD_DMAH, xx>>8);
|
||||
max7456_send(MAX7456ADD_DMAL, xx);
|
||||
max7456_send(MAX7456ADD_DMDI, max7456_screen[xx]);
|
||||
max7456_screen[xx] = ' ';
|
||||
}
|
||||
DISABLE_MAX7456;
|
||||
}
|
||||
}
|
||||
#ifdef MAX7456_DMA_CHANNEL_TX
|
||||
max7456_send_dma(max7456_screen, NULL, max_screen_size * 2 + 10);
|
||||
#else
|
||||
uint16_t xx;
|
||||
max7456_lock = 1;
|
||||
|
||||
void max7456_draw_screen_fast(void) {
|
||||
uint16_t xx;
|
||||
if (!max7456_lock) {
|
||||
ENABLE_MAX7456;
|
||||
max7456_send(MAX7456ADD_DMAH, 0);
|
||||
max7456_send(MAX7456ADD_DMAL, 0);
|
||||
max7456_send(MAX7456ADD_DMM, 1);
|
||||
for (xx = 0; xx < max_screen_size; ++xx) {
|
||||
max7456_send(MAX7456ADD_DMDI, max7456_screen[xx]);
|
||||
max7456_screen[xx] = ' ';
|
||||
max7456_send(MAX7456ADD_DMDI, SCREEN_BUFFER[xx]);
|
||||
SCREEN_BUFFER[xx] = MAX7456_CHAR(0);
|
||||
}
|
||||
max7456_send(MAX7456ADD_DMDI, 0xFF);
|
||||
max7456_send(MAX7456ADD_DMM, 0);
|
||||
DISABLE_MAX7456;
|
||||
max7456_lock = 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void max7456_write_nvm(uint8_t char_address, uint8_t *font_data) {
|
||||
uint8_t x;
|
||||
|
||||
#ifdef MAX7456_DMA_CHANNEL_TX
|
||||
while (dma_transaction_in_progress);
|
||||
#endif
|
||||
while (max7456_lock);
|
||||
max7456_lock = 1;
|
||||
ENABLE_MAX7456;
|
||||
|
||||
|
|
|
@ -143,12 +143,18 @@
|
|||
enum VIDEO_TYPES { AUTO = 0, PAL, NTSC };
|
||||
|
||||
extern uint16_t max_screen_size;
|
||||
extern char max7456_screen[VIDEO_BUFFER_CHARS_PAL];
|
||||
|
||||
#ifdef MAX7456_DMA_CHANNEL_TX
|
||||
#define MAX7456_CHAR_TYPE uint16_t
|
||||
#define MAX7456_CHAR(X) (MAX7456ADD_DMDI | ((X) << 8))
|
||||
#else
|
||||
#define MAX7456_CHAR_TYPE char
|
||||
#define MAX7456_CHAR(X) (X)
|
||||
#endif
|
||||
|
||||
void max7456_init(uint8_t system);
|
||||
void max7456_draw_screen(void);
|
||||
void max7456_draw_screen_fast(void);
|
||||
void max7456_artificial_horizon(int rollAngle, int pitchAngle, uint8_t show_sidebars);
|
||||
void max7456_write_string(const char *string, int16_t address);
|
||||
void max7456_write_nvm(uint8_t char_address, uint8_t *font_data);
|
||||
MAX7456_CHAR_TYPE* max7456_get_screen_buffer(void);
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define NVIC_PRIO_MAG_DATA_READY NVIC_BUILD_PRIORITY(0x0f, 0x0f)
|
||||
#define NVIC_PRIO_CALLBACK NVIC_BUILD_PRIORITY(0x0f, 0x0f)
|
||||
#define NVIC_PRIO_BST_READ_DATA NVIC_BUILD_PRIORITY(1, 1)
|
||||
#define NVIC_PRIO_MAX7456_DMA NVIC_BUILD_PRIORITY(3, 0)
|
||||
|
||||
// utility macros to join/split priority
|
||||
#define NVIC_BUILD_PRIORITY(base,sub) (((((base)<<(4-(7-(NVIC_PRIORITY_GROUPING>>8))))|((sub)&(0x0f>>(7-(NVIC_PRIORITY_GROUPING>>8)))))<<4)&0xf0)
|
||||
|
|
|
@ -122,6 +122,11 @@
|
|||
#define STICKMIN 10
|
||||
#define STICKMAX 90
|
||||
|
||||
/** Artificial Horizon limits **/
|
||||
#define AHIPITCHMAX 200 // Specify maximum AHI pitch value displayed. Default 200 = 20.0 degrees
|
||||
#define AHIROLLMAX 400 // Specify maximum AHI roll value displayed. Default 400 = 40.0 degrees
|
||||
#define AHISIDEBARWIDTHPOSITION 7
|
||||
#define AHISIDEBARHEIGHTPOSITION 3
|
||||
|
||||
static uint32_t next_osd_update_at = 0;
|
||||
static uint32_t armed_seconds = 0;
|
||||
|
@ -194,6 +199,23 @@ void print_vtx_freq(uint16_t pos, uint8_t col) {
|
|||
sprintf(string_buffer, "%d M", vtx_freq[current_vtx_channel]);
|
||||
max7456_write_string(string_buffer, pos);
|
||||
}
|
||||
|
||||
void update_vtx_power(int value_change_direction, uint8_t col) {
|
||||
UNUSED(col);
|
||||
if (value_change_direction) {
|
||||
masterConfig.vtx_power = 0;
|
||||
} else {
|
||||
masterConfig.vtx_power = 1;
|
||||
}
|
||||
rtc6705_soft_spi_set_rf_power(masterConfig.vtx_power);
|
||||
}
|
||||
|
||||
void print_vtx_power(uint16_t pos, uint8_t col) {
|
||||
UNUSED(col);
|
||||
sprintf(string_buffer, "%s", masterConfig.vtx_power ? "25MW" : "200MW");
|
||||
max7456_write_string(string_buffer, pos);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void print_pid(uint16_t pos, uint8_t col, int pid_term) {
|
||||
|
@ -400,7 +422,7 @@ osd_page_t menu_pages[] = {
|
|||
{
|
||||
.title = "VTX SETTINGS",
|
||||
.cols_number = 1,
|
||||
.rows_number = 3,
|
||||
.rows_number = 4,
|
||||
.cols = {
|
||||
{
|
||||
.title = NULL,
|
||||
|
@ -422,6 +444,11 @@ osd_page_t menu_pages[] = {
|
|||
.title = "FREQUENCY",
|
||||
.update = NULL,
|
||||
.print = print_vtx_freq
|
||||
},
|
||||
{
|
||||
.title = "POWER",
|
||||
.update = update_vtx_power,
|
||||
.print = print_vtx_power
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -628,6 +655,49 @@ void show_menu(void) {
|
|||
max7456_write_string(">", cursor_x + cursor_y * OSD_LINE_LENGTH);
|
||||
}
|
||||
|
||||
// Write the artifical horizon to the screen buffer
|
||||
void osdDrawArtificialHorizon(int rollAngle, int pitchAngle, uint8_t show_sidebars) {
|
||||
uint16_t position = 194;
|
||||
MAX7456_CHAR_TYPE *screenBuffer = max7456_get_screen_buffer();
|
||||
|
||||
if (pitchAngle > AHIPITCHMAX)
|
||||
pitchAngle = AHIPITCHMAX;
|
||||
if (pitchAngle < -AHIPITCHMAX)
|
||||
pitchAngle = -AHIPITCHMAX;
|
||||
if (rollAngle > AHIROLLMAX)
|
||||
rollAngle = AHIROLLMAX;
|
||||
if (rollAngle < -AHIROLLMAX)
|
||||
rollAngle = -AHIROLLMAX;
|
||||
|
||||
for (uint8_t X = 0; X <= 8; X++) {
|
||||
if (X == 4)
|
||||
X = 5;
|
||||
int Y = (rollAngle * (4 - X)) / 64;
|
||||
Y -= pitchAngle / 8;
|
||||
Y += 41;
|
||||
if (Y >= 0 && Y <= 81) {
|
||||
uint16_t pos = position - 7 + LINE * (Y / 9) + 3 - 4 * LINE + X;
|
||||
screenBuffer[pos] = MAX7456_CHAR(SYM_AH_BAR9_0 + (Y % 9));
|
||||
}
|
||||
}
|
||||
screenBuffer[position - 1] = MAX7456_CHAR(SYM_AH_CENTER_LINE);
|
||||
screenBuffer[position + 1] = MAX7456_CHAR(SYM_AH_CENTER_LINE_RIGHT);
|
||||
screenBuffer[position] = MAX7456_CHAR(SYM_AH_CENTER);
|
||||
|
||||
if (show_sidebars) {
|
||||
// Draw AH sides
|
||||
int8_t hudwidth = AHISIDEBARWIDTHPOSITION;
|
||||
int8_t hudheight = AHISIDEBARHEIGHTPOSITION;
|
||||
for (int8_t X = -hudheight; X <= hudheight; X++) {
|
||||
screenBuffer[position - hudwidth + (X * LINE)] = MAX7456_CHAR(SYM_AH_DECORATION);
|
||||
screenBuffer[position + hudwidth + (X * LINE)] = MAX7456_CHAR(SYM_AH_DECORATION);
|
||||
}
|
||||
// AH level indicators
|
||||
screenBuffer[position-hudwidth+1] = MAX7456_CHAR(SYM_AH_LEFT);
|
||||
screenBuffer[position+hudwidth-1] = MAX7456_CHAR(SYM_AH_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
void updateOsd(void)
|
||||
{
|
||||
static uint8_t skip = 0;
|
||||
|
@ -645,86 +715,84 @@ void updateOsd(void)
|
|||
if ( !(skip % 2))
|
||||
blink = !blink;
|
||||
|
||||
if (skip++ & 1) {
|
||||
if (ARMING_FLAG(ARMED)) {
|
||||
if (!armed) {
|
||||
armed = true;
|
||||
armed_at = now;
|
||||
in_menu = false;
|
||||
arming = 5;
|
||||
}
|
||||
} else {
|
||||
if (armed) {
|
||||
armed = false;
|
||||
armed_seconds += ((now - armed_at) / 1000000);
|
||||
}
|
||||
for (uint8_t channelIndex = 0; channelIndex < 4; channelIndex++) {
|
||||
sticks[channelIndex] = (constrain(rcData[channelIndex], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN);
|
||||
}
|
||||
if (!in_menu && sticks[YAW] > STICKMAX && sticks[THROTTLE] > STICKMIN && sticks[THROTTLE] < STICKMAX && sticks[ROLL] > STICKMIN && sticks[ROLL] < STICKMAX && sticks[PITCH] > STICKMAX) {
|
||||
in_menu = true;
|
||||
cursor_row = 255;
|
||||
cursor_col = 2;
|
||||
activating_menu = true;
|
||||
}
|
||||
}
|
||||
if (in_menu) {
|
||||
show_menu();
|
||||
} else {
|
||||
if (batteryWarningVoltage > vbat && blink && masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING] != -1) {
|
||||
max7456_write_string("LOW VOLTAGE", masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING]);
|
||||
}
|
||||
if (arming && blink && masterConfig.osdProfile.item_pos[OSD_ARMED] != -1) {
|
||||
max7456_write_string("ARMED", masterConfig.osdProfile.item_pos[OSD_ARMED]);
|
||||
arming--;
|
||||
}
|
||||
if (!armed && masterConfig.osdProfile.item_pos[OSD_DISARMED] != -1) {
|
||||
max7456_write_string("DISARMED", masterConfig.osdProfile.item_pos[OSD_DISARMED]);
|
||||
}
|
||||
|
||||
if (masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE] != -1) {
|
||||
line[0] = SYM_VOLT;
|
||||
sprintf(line+1, "%d.%1d", vbat / 10, vbat % 10);
|
||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE]);
|
||||
}
|
||||
if (masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE] != -1) {
|
||||
line[0] = SYM_RSSI;
|
||||
sprintf(line+1, "%d", rssi / 10);
|
||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE]);
|
||||
}
|
||||
if (masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS] != -1) {
|
||||
line[0] = SYM_THR;
|
||||
line[1] = SYM_THR1;
|
||||
sprintf(line+2, "%3d", (constrain(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN));
|
||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS]);
|
||||
}
|
||||
if (masterConfig.osdProfile.item_pos[OSD_TIMER] != -1) {
|
||||
if (armed) {
|
||||
seconds = armed_seconds + ((now-armed_at) / 1000000);
|
||||
line[0] = SYM_FLY_M;
|
||||
sprintf(line+1, " %02d:%02d", seconds / 60, seconds % 60);
|
||||
} else {
|
||||
line[0] = SYM_ON_M;
|
||||
seconds = now / 1000000;
|
||||
sprintf(line+1, " %02d:%02d", seconds / 60, seconds % 60);
|
||||
}
|
||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_TIMER]);
|
||||
}
|
||||
if (masterConfig.osdProfile.item_pos[OSD_CPU_LOAD] != -1) {
|
||||
print_average_system_load(masterConfig.osdProfile.item_pos[OSD_CPU_LOAD], 0);
|
||||
}
|
||||
if (masterConfig.osdProfile.item_pos[OSD_ARTIFICIAL_HORIZON] != -1) {
|
||||
max7456_artificial_horizon(attitude.values.roll, attitude.values.pitch, masterConfig.osdProfile.item_pos[OSD_HORIZON_SIDEBARS] != -1);
|
||||
}
|
||||
if (ARMING_FLAG(ARMED)) {
|
||||
if (!armed) {
|
||||
armed = true;
|
||||
armed_at = now;
|
||||
in_menu = false;
|
||||
arming = 5;
|
||||
}
|
||||
} else {
|
||||
max7456_draw_screen_fast();
|
||||
if (armed) {
|
||||
armed = false;
|
||||
armed_seconds += ((now - armed_at) / 1000000);
|
||||
}
|
||||
for (uint8_t channelIndex = 0; channelIndex < 4; channelIndex++) {
|
||||
sticks[channelIndex] = (constrain(rcData[channelIndex], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN);
|
||||
}
|
||||
if (!in_menu && sticks[YAW] > STICKMAX && sticks[THROTTLE] > STICKMIN && sticks[THROTTLE] < STICKMAX && sticks[ROLL] > STICKMIN && sticks[ROLL] < STICKMAX && sticks[PITCH] > STICKMAX) {
|
||||
in_menu = true;
|
||||
cursor_row = 255;
|
||||
cursor_col = 2;
|
||||
activating_menu = true;
|
||||
}
|
||||
}
|
||||
if (in_menu) {
|
||||
show_menu();
|
||||
} else {
|
||||
if (batteryWarningVoltage > vbat && blink && masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING] != -1) {
|
||||
max7456_write_string("LOW VOLTAGE", masterConfig.osdProfile.item_pos[OSD_VOLTAGE_WARNING]);
|
||||
}
|
||||
if (arming && blink && masterConfig.osdProfile.item_pos[OSD_ARMED] != -1) {
|
||||
max7456_write_string("ARMED", masterConfig.osdProfile.item_pos[OSD_ARMED]);
|
||||
arming--;
|
||||
}
|
||||
if (!armed && masterConfig.osdProfile.item_pos[OSD_DISARMED] != -1) {
|
||||
max7456_write_string("DISARMED", masterConfig.osdProfile.item_pos[OSD_DISARMED]);
|
||||
}
|
||||
|
||||
if (masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE] != -1) {
|
||||
line[0] = SYM_VOLT;
|
||||
sprintf(line+1, "%d.%1d", vbat / 10, vbat % 10);
|
||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_MAIN_BATT_VOLTAGE]);
|
||||
}
|
||||
if (masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE] != -1) {
|
||||
line[0] = SYM_RSSI;
|
||||
sprintf(line+1, "%d", rssi / 10);
|
||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_RSSI_VALUE]);
|
||||
}
|
||||
if (masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS] != -1) {
|
||||
line[0] = SYM_THR;
|
||||
line[1] = SYM_THR1;
|
||||
sprintf(line+2, "%3d", (constrain(rcData[THROTTLE], PWM_RANGE_MIN, PWM_RANGE_MAX) - PWM_RANGE_MIN) * 100 / (PWM_RANGE_MAX - PWM_RANGE_MIN));
|
||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_THROTTLE_POS]);
|
||||
}
|
||||
if (masterConfig.osdProfile.item_pos[OSD_TIMER] != -1) {
|
||||
if (armed) {
|
||||
seconds = armed_seconds + ((now-armed_at) / 1000000);
|
||||
line[0] = SYM_FLY_M;
|
||||
sprintf(line+1, " %02d:%02d", seconds / 60, seconds % 60);
|
||||
} else {
|
||||
line[0] = SYM_ON_M;
|
||||
seconds = now / 1000000;
|
||||
sprintf(line+1, " %02d:%02d", seconds / 60, seconds % 60);
|
||||
}
|
||||
max7456_write_string(line, masterConfig.osdProfile.item_pos[OSD_TIMER]);
|
||||
}
|
||||
if (masterConfig.osdProfile.item_pos[OSD_CPU_LOAD] != -1) {
|
||||
print_average_system_load(masterConfig.osdProfile.item_pos[OSD_CPU_LOAD], 0);
|
||||
}
|
||||
if (masterConfig.osdProfile.item_pos[OSD_ARTIFICIAL_HORIZON] != -1) {
|
||||
osdDrawArtificialHorizon(attitude.values.roll, attitude.values.pitch, masterConfig.osdProfile.item_pos[OSD_HORIZON_SIDEBARS] != -1);
|
||||
}
|
||||
}
|
||||
max7456_draw_screen();
|
||||
}
|
||||
|
||||
void osdInit(void)
|
||||
{
|
||||
uint16_t x;
|
||||
MAX7456_CHAR_TYPE* screen_buffer = max7456_get_screen_buffer();
|
||||
|
||||
max7456_init(masterConfig.osdProfile.video_system);
|
||||
|
||||
|
@ -732,7 +800,8 @@ void osdInit(void)
|
|||
x = 160;
|
||||
for (int i = 1; i < 5; i++) {
|
||||
for (int j = 3; j < 27; j++)
|
||||
max7456_screen[i * LINE + j] = (char)x++;
|
||||
if (x != 255)
|
||||
screen_buffer[(i * LINE + j)] = MAX7456_CHAR(x++);
|
||||
}
|
||||
sprintf(string_buffer, "BF VERSION: %s", FC_VERSION_STRING);
|
||||
max7456_write_string(string_buffer, LINE06 + 5);
|
||||
|
|
|
@ -112,6 +112,13 @@
|
|||
#define MAX7456_SPI_INSTANCE SPI3
|
||||
#define MAX7456_SPI_CS_PIN PA15
|
||||
|
||||
#define MAX7456_DMA_CHANNEL_TX DMA2_Channel2
|
||||
#define MAX7456_DMA_CHANNEL_RX DMA2_Channel1
|
||||
#define MAX7456_DMA_TC_FLAG DMA2_FLAG_TC1
|
||||
#define MAX7456_DMA_PERIPH_CLOCK RCC_AHBPeriph_DMA2
|
||||
#define MAX7456_DMA_IRQ_HANDLER_FUNCTION DMA2_Channel1_IRQHandler
|
||||
#define MAX7456_DMA_IRQ_HANDLER_ID DMA2_Channel1_IRQn
|
||||
|
||||
#define USE_RTC6705
|
||||
#define RTC6705_SPIDATA_PIN PC15
|
||||
#define RTC6705_SPILE_PIN PC14
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue