AP_OSD: allow for loading fonts from sdcard

user can put fontN.bin on their sdcard and it will replace the font in
romfs. This makes for easy font development, and allows for multiple
languages

This replaces #15668
This commit is contained in:
Andrew Tridgell 2020-11-13 11:03:37 +11:00
parent 773517a473
commit a2d86eac6d
5 changed files with 52 additions and 33 deletions

View File

@ -51,3 +51,26 @@ void AP_OSD_Backend::write(uint8_t x, uint8_t y, bool blink, const char *fmt, ..
va_end(ap); va_end(ap);
#endif #endif
} }
/*
load a font from sdcard or ROMFS
*/
FileData *AP_OSD_Backend::load_font_data(uint8_t font_num)
{
FileData *fd;
// first try from microSD
char fontname[] = "font0.bin";
fontname[4] = font_num + '0';
fd = AP::FS().load_file(fontname);
if (fd == nullptr) {
char fontname_romfs[] = "@ROMFS/font0.bin";
fontname_romfs[7+4] = font_num + '0';
fd = AP::FS().load_file(fontname_romfs);
}
if (fd == nullptr) {
GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "OSD: Failed to load font %u", font_num);
}
return fd;
}

View File

@ -18,6 +18,7 @@
#include <AP_HAL/HAL.h> #include <AP_HAL/HAL.h>
#include <AP_OSD/AP_OSD.h> #include <AP_OSD/AP_OSD.h>
#include <AP_Filesystem/AP_Filesystem.h>
class AP_OSD_Backend class AP_OSD_Backend
@ -72,6 +73,9 @@ protected:
return (_osd.options & option) != 0; return (_osd.options & option) != 0;
} }
// load a font from sdcard or ROMFS
FileData *load_font_data(uint8_t font_num);
int8_t blink_phase; int8_t blink_phase;
enum vid_format { enum vid_format {

View File

@ -22,7 +22,8 @@
#include <AP_HAL/Util.h> #include <AP_HAL/Util.h>
#include <AP_HAL/Semaphores.h> #include <AP_HAL/Semaphores.h>
#include <AP_HAL/Scheduler.h> #include <AP_HAL/Scheduler.h>
#include <AP_ROMFS/AP_ROMFS.h> #include <AP_Filesystem/AP_Filesystem.h>
#include <GCS_MAVLink/GCS.h>
#include <utility> #include <utility>
@ -157,13 +158,19 @@ bool AP_OSD_MAX7456::init()
bool AP_OSD_MAX7456::update_font() bool AP_OSD_MAX7456::update_font()
{ {
uint32_t font_size;
uint8_t updated_chars = 0; uint8_t updated_chars = 0;
char fontname[] = "font0.bin";
last_font = get_font_num(); last_font = get_font_num();
fontname[4] = last_font + '0'; FileData *fd = load_font_data(last_font);
const uint8_t *font_data = AP_ROMFS::find_decompress(fontname, font_size);
if (font_data == nullptr || font_size != NVM_RAM_SIZE * 256) { if (fd == nullptr) {
return false;
}
const uint8_t *font_data = fd->data;
uint32_t font_size = fd->length;
if (font_size != NVM_RAM_SIZE * 256) {
GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "AP_OSD: bad font size %u\n", unsigned(font_size));
delete fd;
return false; return false;
} }
@ -173,18 +180,13 @@ bool AP_OSD_MAX7456::update_font()
if (!check_font_char(chr, chr_font_data)) { if (!check_font_char(chr, chr_font_data)) {
//update char inside max7456 NVM //update char inside max7456 NVM
if (!update_font_char(chr, chr_font_data)) { if (!update_font_char(chr, chr_font_data)) {
hal.console->printf("AP_OSD: error during font char update\n"); delete fd;
AP_ROMFS::free(font_data);
return false; return false;
} }
updated_chars++; updated_chars++;
} }
} }
if (updated_chars > 0) { delete fd;
hal.console->printf("AP_OSD: updated %d symbols.\n", updated_chars);
}
hal.console->printf("AP_OSD: osd font is up to date.\n");
AP_ROMFS::free(font_data);
return true; return true;
} }

View File

@ -43,21 +43,13 @@ extern const AP_HAL::HAL &hal;
*/ */
void AP_OSD_SITL::load_font(void) void AP_OSD_SITL::load_font(void)
{ {
uint32_t font_size;
char fontname[] = "font0.bin";
last_font = get_font_num(); last_font = get_font_num();
fontname[4] = last_font + '0'; FileData *fd = load_font_data(last_font);
const uint8_t *font_data = AP_ROMFS::find_decompress(fontname, font_size); if (fd == nullptr || fd->length != 54 * 256) {
if (font_data == nullptr && last_font != 0) {
last_font = 0;
fontname[4] = last_font + '0';
font_data = AP_ROMFS::find_decompress(fontname, font_size);
}
if (font_data == nullptr || font_size != 54 * 256) {
AP_HAL::panic("Bad font file"); AP_HAL::panic("Bad font file");
} }
for (uint16_t i=0; i<256; i++) { for (uint16_t i=0; i<256; i++) {
const uint8_t *c = &font_data[i*54]; const uint8_t *c = &fd->data[i*54];
// each pixel is 4 bytes, RGBA // each pixel is 4 bytes, RGBA
sf::Uint8 *pixels = new sf::Uint8[char_width * char_height * 4]; sf::Uint8 *pixels = new sf::Uint8[char_width * char_height * 4];
if (!font[i].create(char_width, char_height)) { if (!font[i].create(char_width, char_height)) {
@ -97,7 +89,7 @@ void AP_OSD_SITL::load_font(void)
} }
font[i].update(pixels); font[i].update(pixels);
} }
AP_ROMFS::free(font_data); delete fd;
} }
void AP_OSD_SITL::write(uint8_t x, uint8_t y, const char* text) void AP_OSD_SITL::write(uint8_t x, uint8_t y, const char* text)

View File

@ -1777,17 +1777,15 @@ void AP_OSD_Screen::draw_callsign(uint8_t x, uint8_t y)
#if HAVE_FILESYSTEM_SUPPORT #if HAVE_FILESYSTEM_SUPPORT
if (!callsign_data.load_attempted) { if (!callsign_data.load_attempted) {
callsign_data.load_attempted = true; callsign_data.load_attempted = true;
int fd = AP::FS().open("callsign.txt", O_RDONLY); FileData *fd = AP::FS().load_file("callsign.txt");
if (fd != -1) { if (fd != nullptr) {
char s[20] {}; uint32_t len = fd->length;
int32_t len = AP::FS().read(fd, s, sizeof(s)-1);
// trim off whitespace // trim off whitespace
while (len > 0 && isspace(s[len-1])) { while (len > 0 && isspace(fd->data[len-1])) {
s[len-1] = 0;
len--; len--;
} }
AP::FS().close(fd); callsign_data.str = strndup((const char *)fd->data, len);
callsign_data.str = strdup(s); delete fd;
} }
} }
if (callsign_data.str != nullptr) { if (callsign_data.str != nullptr) {