1
0
Fork 0
mirror of https://github.com/iNavFlight/inav.git synced 2025-07-24 16:55:29 +03:00

[OSD] Remove FrSky OSD dependency on MAX7456

Move local character grid buffer to drivers/osd.c and use it
from both the FrSky OSD and the MAX7456 drivers.
This commit is contained in:
Alberto García Hierro 2019-10-24 21:54:35 +01:00
parent 51da88d26c
commit a4187a58d4
6 changed files with 85 additions and 35 deletions

View file

@ -44,6 +44,7 @@ COMMON_SRC = \
drivers/io.c \
drivers/io_pca9685.c \
drivers/light_led.c \
drivers/osd.c \
drivers/resource.c \
drivers/rx_nrf24l01.c \
drivers/rx_spi.c \

View file

@ -176,10 +176,9 @@
#define CHAR_MODE_EXT (1 << 2)
#define CHAR_MODE_IS_EXT(m) ((m) & CHAR_MODE_EXT)
// we write everything in max7456ScreenBuffer and set a dirty bit
// in screenIsDirty to upgrade only changed chars this solution
// is faster than redrawing the whole screen on each frame
uint16_t max7456ScreenBuffer[MAX7456_BUFFER_CHARS_PAL] ALIGNED(4);
// we write everything in osdCharacterGridBuffer and set a dirty bit
// in screenIsDirty to update only changed chars. This solution
// is faster than redrawing the whole screen on each frame.
static BITARRAY_DECLARE(screenIsDirty, MAX7456_BUFFER_CHARS_PAL);
//max chars to update in one idle
@ -307,7 +306,7 @@ uint8_t max7456GetRowsCount(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. Note that we can't touch max7456ScreenBuffer here, since
//and in case of restart we need to reinitialize chip. Note that we can't touch osdCharacterGridBuffer here, since
//it might already have some data by the first time this function is called.
static void max7456ReInit(void)
{
@ -382,9 +381,9 @@ void max7456Init(const videoSystem_e videoSystem)
state.registers.dmm = 0;
state.videoSystem = videoSystem;
// Set max7456ScreenBuffer to all blanks
for (uint_fast16_t ii = 0; ii < ARRAYLEN(max7456ScreenBuffer); ii++) {
max7456ScreenBuffer[ii] = CHAR_BLANK;
// Set screen buffer to all blanks
for (uint_fast16_t ii = 0; ii < ARRAYLEN(osdCharacterGridBuffer); ii++) {
osdCharacterGridBuffer[ii] = CHAR_BLANK;
}
// Wait for software reset to finish
@ -409,9 +408,9 @@ void max7456Init(const videoSystem_e videoSystem)
void max7456ClearScreen(void)
{
for (uint_fast16_t ii = 0; ii < ARRAYLEN(max7456ScreenBuffer); ii++) {
if (max7456ScreenBuffer[ii] != CHAR_BLANK) {
max7456ScreenBuffer[ii] = CHAR_BLANK;
for (uint_fast16_t ii = 0; ii < ARRAYLEN(osdCharacterGridBuffer); ii++) {
if (osdCharacterGridBuffer[ii] != CHAR_BLANK) {
osdCharacterGridBuffer[ii] = CHAR_BLANK;
bitArraySet(screenIsDirty, ii);
}
}
@ -421,8 +420,8 @@ void max7456WriteChar(uint8_t x, uint8_t y, uint16_t c, uint8_t mode)
{
unsigned pos = y * MAX7456_CHARS_PER_LINE + x;
uint16_t val = MAKE_CHAR_MODE(c, mode);
if (max7456ScreenBuffer[pos] != val) {
max7456ScreenBuffer[pos] = val;
if (osdCharacterGridBuffer[pos] != val) {
osdCharacterGridBuffer[pos] = val;
bitArraySet(screenIsDirty, pos);
}
}
@ -430,8 +429,8 @@ void max7456WriteChar(uint8_t x, uint8_t y, uint16_t c, uint8_t mode)
bool max7456ReadChar(uint8_t x, uint8_t y, uint16_t *c, uint8_t *mode)
{
unsigned pos = y * MAX7456_CHARS_PER_LINE + x;
if (pos < ARRAYLEN(max7456ScreenBuffer)) {
uint16_t val = max7456ScreenBuffer[pos];
if (pos < ARRAYLEN(osdCharacterGridBuffer)) {
uint16_t val = osdCharacterGridBuffer[pos];
*c = CHAR_BYTE(val);
*mode = MODE_BYTE(val);
if (CHAR_MODE_IS_EXT(*mode)) {
@ -454,8 +453,8 @@ void max7456Write(uint8_t x, uint8_t y, const char *buff, uint8_t mode)
break;
}
c = MAKE_CHAR_MODE_U8(*buff, mode);
if (max7456ScreenBuffer[pos] != c) {
max7456ScreenBuffer[pos] = c;
if (osdCharacterGridBuffer[pos] != c) {
osdCharacterGridBuffer[pos] = c;
bitArraySet(screenIsDirty, pos);
}
}
@ -482,8 +481,8 @@ static bool max7456DrawScreenPartial(void)
uint8_t ph = pos >> 8;
uint8_t pl = pos & 0xff;
charMode = MODE_BYTE(max7456ScreenBuffer[pos]);
uint8_t chr = CHAR_BYTE(max7456ScreenBuffer[pos]);
charMode = MODE_BYTE(osdCharacterGridBuffer[pos]);
uint8_t chr = CHAR_BYTE(osdCharacterGridBuffer[pos]);
if (CHAR_MODE_IS_EXT(charMode)) {
if (!DMM_IS_8BIT_MODE(state.registers.dmm)) {
state.registers.dmm |= DMM_8BIT_MODE;
@ -621,8 +620,8 @@ void max7456RefreshAll(void)
// Mark non-blank characters as dirty
BITARRAY_CLR_ALL(screenIsDirty);
for (unsigned ii = 0; ii < ARRAYLEN(max7456ScreenBuffer); ii++) {
if (!CHAR_IS_BLANK(max7456ScreenBuffer[ii])) {
for (unsigned ii = 0; ii < ARRAYLEN(osdCharacterGridBuffer); ii++) {
if (!CHAR_IS_BLANK(osdCharacterGridBuffer[ii])) {
bitArraySet(screenIsDirty, ii);
}
}

View file

@ -44,8 +44,6 @@ enum VIDEO_TYPES { AUTO = 0, PAL, NTSC };
#define MAX7456_MODE_BLINK (1 << 4)
#define MAX7456_MODE_SOLID_BG (1 << 5)
extern uint16_t max7456ScreenBuffer[MAX7456_BUFFER_CHARS_PAL] ALIGNED(4);
void max7456Init(const videoSystem_e videoSystem);
void max7456Update(void);
void max7456ReadNvm(uint16_t char_address, osdCharacter_t *chr);

43
src/main/drivers/osd.c Normal file
View file

@ -0,0 +1,43 @@
/*
* This file is part of INAV.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Alternatively, the contents of this file may be used under the terms
* of the GNU General Public License Version 3, as described below:
*
* This file is free software: you may copy, redistribute and/or modify
* it under the terms of the GNU General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This file 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 this program. If not, see http://www.gnu.org/licenses/.
*
*/
#include "drivers/osd.h"
uint16_t osdCharacterGridBuffer[OSD_CHARACTER_GRID_BUFFER_SIZE] ALIGNED(4);
void osdCharacterGridBufferClear(void)
{
uint32_t *ptr = (uint32_t *)osdCharacterGridBuffer;
uint32_t *end = (uint32_t *)(ARRAYEND(osdCharacterGridBuffer));
for (; ptr < end; ptr++) {
*ptr = 0;
}
}
uint16_t *osdCharacterGridBufferGetEntryPtr(unsigned x, unsigned y)
{
unsigned pos = y * OSD_CHARACTER_GRID_MAX_WIDTH + x;
return &osdCharacterGridBuffer[pos];
}

View file

@ -22,6 +22,8 @@
#include <stdint.h>
#include "common/utils.h"
#define OSD_CHAR_WIDTH 12
#define OSD_CHAR_HEIGHT 18
#define OSD_CHAR_BITS_PER_PIXEL 2
@ -57,3 +59,13 @@ typedef enum {
typedef struct osdCharacter_s {
uint8_t data[OSD_CHAR_BYTES];
} osdCharacter_t;
#define OSD_CHARACTER_GRID_MAX_WIDTH 30
#define OSD_CHARACTER_GRID_MAX_HEIGHT 16
#define OSD_CHARACTER_GRID_BUFFER_SIZE (OSD_CHARACTER_GRID_MAX_WIDTH * OSD_CHARACTER_GRID_MAX_HEIGHT)
extern uint16_t osdCharacterGridBuffer[OSD_CHARACTER_GRID_BUFFER_SIZE] ALIGNED(4);
// Sets all buffer entries to 0
void osdCharacterGridBufferClear(void);
uint16_t *osdCharacterGridBufferGetEntryPtr(unsigned x, unsigned y);

View file

@ -13,7 +13,6 @@
#include "common/utils.h"
#include "common/uvarint.h"
#include "drivers/max7456.h"
#include "drivers/time.h"
#include "io/frsky_osd.h"
@ -25,7 +24,6 @@
#define FRSKY_OSD_PREAMBLE_BYTE_0 '$'
#define FRSKY_OSD_PREAMBLE_BYTE_1 'A'
#define FRSKY_OSD_GRID_BUFFER_POS(x, y) (y * MAX7456_CHARS_PER_LINE + x)
#define FRSKY_OSD_GRID_BUFFER_CHAR_BITS 9
#define FRSKY_OSD_GRID_BUFFER_CHAR_MASK ((1 << FRSKY_OSD_GRID_BUFFER_CHAR_BITS) - 1)
#define FRSKY_OSD_GRID_BUFFER_ENCODE(chr, attr) ((chr & FRSKY_OSD_GRID_BUFFER_CHAR_MASK) | (attr << FRSKY_OSD_GRID_BUFFER_CHAR_BITS))
@ -694,18 +692,18 @@ void frskyOSDDrawStringInGrid(unsigned x, unsigned y, const char *buff, textAttr
{
unsigned charsUpdated = 0;
const char *updatedCharAt = NULL;
unsigned pos = FRSKY_OSD_GRID_BUFFER_POS(x, y);
uint16_t *entry = osdCharacterGridBufferGetEntryPtr(x, y);
const char *p;
unsigned xx;
for (p = buff, xx = x; *p && xx < state.info.grid.columns; p++, pos++, xx++) {
for (p = buff, xx = x; *p && xx < state.info.grid.columns; p++, entry++, xx++) {
unsigned val = FRSKY_OSD_GRID_BUFFER_ENCODE(*p, attr);
if (max7456ScreenBuffer[pos] != val) {
if (*entry != val) {
if (++charsUpdated == 1) {
// First character that needs to be updated, save it
// in case we can issue a single update.
updatedCharAt = p;
}
max7456ScreenBuffer[pos] = val;
*entry = val;
}
}
@ -728,22 +726,21 @@ void frskyOSDDrawStringInGrid(unsigned x, unsigned y, const char *buff, textAttr
void frskyOSDDrawCharInGrid(unsigned x, unsigned y, uint16_t chr, textAttributes_t attr)
{
unsigned pos = FRSKY_OSD_GRID_BUFFER_POS(x, y);
uint16_t *entry = osdCharacterGridBufferGetEntryPtr(x, y);
unsigned val = FRSKY_OSD_GRID_BUFFER_ENCODE(chr, attr);
if (max7456ScreenBuffer[pos] == val) {
if (*entry == val) {
return;
}
frskyOSDSendCharInGrid(x, y, chr, attr);
max7456ScreenBuffer[pos] = val;
*entry = val;
}
bool frskyOSDReadCharInGrid(unsigned x, unsigned y, uint16_t *c, textAttributes_t *attr)
{
unsigned pos = FRSKY_OSD_GRID_BUFFER_POS(x, y);
uint16_t val = max7456ScreenBuffer[pos];
uint16_t val = *osdCharacterGridBufferGetEntryPtr(x, y);
// We use the lower 10 bits for characters
*c = val & FRSKY_OSD_GRID_BUFFER_CHAR_MASK;
*attr = val >> FRSKY_OSD_GRID_BUFFER_CHAR_BITS;
@ -752,7 +749,7 @@ bool frskyOSDReadCharInGrid(unsigned x, unsigned y, uint16_t *c, textAttributes_
void frskyOSDClearScreen(void)
{
memset(max7456ScreenBuffer, 0, sizeof(max7456ScreenBuffer));
osdCharacterGridBufferClear();
frskyOSDSendAsyncCommand(OSD_CMD_DRAWING_CLEAR_SCREEN, NULL, 0);
}