Skip to content

Commit

Permalink
Added support for multiple lines and background color for the custom …
Browse files Browse the repository at this point in the history
…message
  • Loading branch information
tipoman9 committed Feb 22, 2025
1 parent 2607aa1 commit 2ff523f
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 26 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"stdint-uintn.h": "c",
"interface.h": "c",
"valarray": "c",
"complex": "c"
"complex": "c",
"source_location": "c"
}
}
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ AHI (Artificial Horizon Indicator) ladder - Graphical AHI , that is drawn over t

**Show custom mesage and diagnostics** on screen when text is written to file /tmp/MSPOSD.msg
```
echo "Custom Message... &L04 &F22 CPU:&C &B temp:&T" >/tmp/MSPOSD.msg
echo "Custom Message... &L04 &F22 CPU:&C &B temp:&T\n Line 2 with more data" >/tmp/MSPOSD.msg
```
Extra params withing the message to be shown:
- &T - Board temperature
Expand All @@ -104,13 +104,14 @@ Extra params withing the message to be shown:
- &C - CPU Usage percent
- &t - Time
- &Fxx - Set text font size (10 to 99)
- &Lxx - Set text colour (first digit 0- white, 1 - black, 2- red, 3 - green, 4 - blue, 5 - yellow, 6 - magenta, 7 - cyan) and postion on the screen(second digit) 0-TopLeft, 1-TopCenter, 2-TopRight, 3-TopMoving,4-BottomLeft, 5-BottomCenter, 6-BottomRight, 7-BottomMoving
- &Lxx - Set text colour (first digit 0- white, 1 - black, 2- blue, 3 - green, 4 - red, 5 - yellow, 6 - magenta, 7 - cyan) and postion on the screen(second digit) 0-TopLeft, 1-TopCenter, 2-TopRight, 3-TopMoving,4-BottomLeft, 5-BottomCenter, 6-BottomRight, 7-BottomMoving
- &Gx - Set text backGround color (0- white, 1 - black, 2- blue, 3 - green, 4 - red, 5 - yellow, 6 - magenta, 7 - cyan, 8 - dark gray, 9 - transparent)
-&p - Dropped packet injections by wfb-ng

### Custom OSD elements
Custom elements can be added via the standard inav/bf/ardu OSD Configurator. A keyword needs to be added on the screen, that will be replaced by the corresponding widget.
This keywords can be added using the PilotName/CraftName fields(INAV/BF/Ardu), or custom Text Elements(INAV only).
- ```!TWM!``` Camera board temp
- ```!TWP!``` Camera board temp
- ```!TMW!``` WiFi module tem(only 8812EU2 chipsets supported)
- ```!RC!``` Sticks Position widget (Ground Side only)

Expand Down
8 changes: 6 additions & 2 deletions bmp/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1117,12 +1117,14 @@ int getRowStride(int width, int BitsPerPixel) {
}

void convertBitmap1555ToI4(
uint16_t *srcBitmap, uint32_t width, uint32_t height, uint8_t *destBitmap, int singleColor) {
uint16_t *srcBitmap, uint32_t width, uint32_t height, uint8_t *destBitmap, int singleColor, int colourBackground) {
MI_RGN_PaletteTable_t *paletteTable = &g_stPaletteTable;
// Calculate the number of bytes required per line without padding

if (singleColor == -1) // The color that we assume as transparent
singleColor = 15;


unsigned char u8Value = 0;
uint32_t u32Stride = (width + 1) / 2;

Expand Down Expand Up @@ -1154,6 +1156,8 @@ void convertBitmap1555ToI4(
if (paletteIndex != 15 & paletteIndex >= 0) {
paletteIndex = singleColor;
}
if (colourBackground>=0 && paletteIndex==15)
paletteIndex=colourBackground;

// No Fucking idea why this is different for x86 and Sigmastar, BUT
// !!! SigmaStar I4 format needs it reversit 4bit pairs. 0x0A,
Expand Down
2 changes: 1 addition & 1 deletion bmp/bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ void convertBitmap1555ToI8(uint16_t *srcBitmap, uint32_t width, uint32_t height,
void Convert1555ToRGBA(
unsigned short *bitmap1555, unsigned char *rgbaData, unsigned int width, unsigned int height);
void convertBitmap1555ToI4(
uint16_t *srcBitmap, uint32_t width, uint32_t height, uint8_t *destBitmap, int singleColor);
uint16_t *srcBitmap, uint32_t width, uint32_t height, uint8_t *destBitmap, int singleColor, int colourBackground);

void convertRGBAToI4(uint8_t *srcBitmap, uint32_t width, uint32_t height, uint8_t *destBitmap,
MI_RGN_PaletteTable_t *paletteTable);
Expand Down
2 changes: 1 addition & 1 deletion bmp/text.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ static void copyimage(SFT_Image *dest, const SFT_Image *source, int x0, int y0,
*/
unsigned char pixel = s[x];
// If the pixel is not zero (assuming non-zero means black)
if (pixel > 64) // 128 makes them too thin...
if (pixel > 96) // 128 makes them too thin... 64 is best
d[x] = 0x8000; // Set pixel to opaque black (ARGB1555: 1000 0000
// 0000 0000)
else
Expand Down
2 changes: 1 addition & 1 deletion develepment_notes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ make osd-x86 VERBOSE=1
cc msposd.c -I ./include -L/usr/lib/x86_64-linux-gnu/ -lcsfml-graphics -lcsfml-window -lcsfml-system -O1 -g -fsanitize=address -fno-omit-frame-pointer -Wall -Wextra -D_x86 -g -fsanitize=address -levent_core -o msposd

#copy on cam
scp -O ./release/star6e/msposd [email protected]:/usr/bin/msposd

scp -O ./msposd_star6e [email protected]:/usr/bin/msposd

on the camera
Expand Down
98 changes: 81 additions & 17 deletions osd.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ enum { MAX_DISPLAY_X = 60, MAX_DISPLAY_Y = 22 };
// supported.
#define MSP_DISPLAY_SIZE_VERSION 45

#define MIN(a, b) ((a) < (b) ? (a) : (b))

extern FrequencyChannel fc_list[MAX_ENTRIES]; // Array to store frequency-channel pairs

typedef struct msp_cache_entry_s {
Expand Down Expand Up @@ -676,6 +678,8 @@ int msg_layout = 0;
/// white font
int msg_colour = 0;

int msg_colour_background=-1;

static unsigned long long LastCleared = 0;
static bool osd_msg_enabled = false;

Expand Down Expand Up @@ -1105,15 +1109,16 @@ static void draw_Ladder() {

static int droppedTTL = 0;
static bool first_wfb_read = true;
#define MAX_STATUS_MSG_LEN 500

void fill(char *str) {
unsigned int rxb_l, txb_l, cpu_l[7];
char out[280] = "";
char out[MAX_STATUS_MSG_LEN+100] = "";
char param = 0;
int ipos = 0, opos = 0;

while (str[ipos] != 0) {
if (str[ipos] == '\r' || str[ipos] == '\n')
if (str[ipos] == '\r' /* || str[ipos] == '\n'*/)
str[ipos] = ' ';
if (str[ipos] != '&') {
strncat(out, str + ipos, 1);
Expand Down Expand Up @@ -1306,15 +1311,37 @@ void fill(char *str) {
msg_colour--;

ipos += 3;
}
} else if (str[ipos + 1] == 'G' && isdigit(str[ipos + 2]) ) {
if (!DrawOSD) {// we need to keep &Cx
strncat(out, str + ipos, 1);
opos++;
} else {
// Extract the one digit after $C as an integer

msg_colour_background = str[ipos + 2]-'0';
if (msg_colour_background == 0)
msg_colour_background = COLOR_WHITE;
else if (msg_colour_background == 1)
msg_colour_background = COLOR_BLACK;
else if (msg_colour_background == 8)
msg_colour_background = 10;//dark_gray
else if (msg_colour_background == 9)//remove it, i.e. make it transparent
msg_colour_background = -1;
else
msg_colour_background--;

ipos += 2;
}
} else if (str[ipos + 1] == '&') {
}
else if (str[ipos + 1] == '&') {
ipos++;
strcat(out, "&");
opos++;
}
ipos++;
}
strncpy(str, out, 180);
strncpy(str, out, MAX_STATUS_MSG_LEN);
}

#ifdef _x86
Expand Down Expand Up @@ -1371,7 +1398,24 @@ void remove_carriage_returns(char *out) {
out[j] = '\0'; // Null-terminate the modified string
}

char osdmsg[180];

#define MAX_LINES 100 // Maximum number of lines we expect to handle
void split_lines(char *str, char *lines[MAX_LINES], int *line_count) {
*line_count = 0; // Initialize the line count
lines[(*line_count)++] = str; // Store the pointer to the first line

while (*str) {
if (*str == '\n') {//'@'
*str = '\0'; // Replace the carriage return with a null terminator
if (*(str + 1) != '\0') { // Check if it's not the end of the string
lines[(*line_count)++] = str + 1; // Store the pointer to the next line
}
}
str++;
}
}

char osdmsg[MAX_STATUS_MSG_LEN];

bool DrawTextOnOSDBitmap(char *msg) {
char *font;
Expand All @@ -1392,14 +1436,14 @@ bool DrawTextOnOSDBitmap(char *msg) {

bool res = false;
int result;
char out[180];
char out[MAX_STATUS_MSG_LEN];
size_t bytesRead = 0;

FILE *file = NULL;
if (msg == NULL || strlen(msg) == 0) {
file = fopen(FECFile, "rb");
if (file != NULL) { // New file, will have to render the font
bytesRead = fread(osdmsg, 1, 179 /*max buffer*/, file); // with files
bytesRead = fread(osdmsg, 1, MAX_STATUS_MSG_LEN /*max buffer*/, file); // with files
fclose(file);
remove(FECFile);
osdmsg[bytesRead] = 0; // end of string
Expand Down Expand Up @@ -1431,7 +1475,7 @@ bool DrawTextOnOSDBitmap(char *msg) {
if (!DrawOSD && out_sock > 0) { // send the line to the ground
static uint8_t msg_buffer[256];
static uint8_t payload_buffer[256];
out[79] = 0; // just in case
//out[79] = 0; // just in case
int msglen = strlen(&out[0]);

payload_buffer[0] = MSP_DISPLAYPORT_INFO_MSG;
Expand All @@ -1451,18 +1495,38 @@ bool DrawTextOnOSDBitmap(char *msg) {
if ((osds[FULL_OVERLAY_ID].size < 5.0) || (osds[FULL_OVERLAY_ID].size > 99.0))
osds[FULL_OVERLAY_ID].size = 20.0;

// print_string_as_hex(out);
// remove_carriage_returns(out);

RECT rect = measure_text(font, osds[FULL_OVERLAY_ID].size, out);
RECT rect;// = measure_text(font, osds[FULL_OVERLAY_ID].size, out);

if (bitmapText.pData != NULL) {
bitmapText.pData = NULL;
free(bitmapText.pData);
free(bitmapText.pData);
}
char *lines[MAX_LINES]; // Array to hold pointers to each line
int line_count = 0;

split_lines(out, lines, &line_count);//Here we will modify the message
int maxwidth=0;

for (int i = 0; i < line_count; i++) {
//printf("OSD Statistics Line %d: %s\n", i + 1, lines[i]);
rect = measure_text(font, osds[FULL_OVERLAY_ID].size, lines[i]);
maxwidth=(rect.width>maxwidth)?rect.width:maxwidth;
}

bitmapText.u32Height = line_count * rect.height ;// preview_height;//rows *
bitmapText.u32Width = MIN( (maxwidth + 15) & ~15, bmpBuff.u32Width-16) ;// should be multiple of 16 OVERLAY_WIDTH-16
bitmapText.pData = (unsigned char *) malloc(bitmapText.u32Height * getRowStride(bitmapText.u32Width, 16));
memset(bitmapText.pData, 0, bitmapText.u32Height * getRowStride(bitmapText.u32Width, 16));

for(int i=0;i<line_count;i++){
BITMAP bitmapTextLine = raster_text(font, osds[FULL_OVERLAY_ID].size, lines[i]); // allocates new bitmap, Bus error on goke ?!
//raster_text always return argb1555
copyRectARGB1555(bitmapTextLine.pData, bitmapTextLine.u32Width, bitmapTextLine.u32Height,
bitmapText.pData, bitmapText.u32Width, bitmapText.u32Height,
0, 0, MIN(bitmapTextLine.u32Width,bitmapText.u32Width) , MIN(bitmapTextLine.u32Height, bitmapText.u32Height),
0, i*rect.height);
}

bitmapText = raster_text(font, osds[FULL_OVERLAY_ID].size,
out); // allocates new bitmap, Bus error on goke ?!

if (PIXEL_FORMAT_DEFAULT ==
PIXEL_FORMAT_I4) { // convert to I4 and copy over the main overlay
Expand All @@ -1472,7 +1536,7 @@ bool DrawTextOnOSDBitmap(char *msg) {
getRowStride(bitmapText.u32Width, PIXEL_FORMAT_BitsPerPixel));

convertBitmap1555ToI4(bitmapText.pData, bitmapText.u32Width, bitmapText.u32Height,
destBitmap, msg_colour);
destBitmap, msg_colour,msg_colour_background);

free(bitmapText.pData); // free ARGB1555 bitmap
// This is inefficient, we use 4 times more memory, but the buffer
Expand Down Expand Up @@ -1509,7 +1573,7 @@ bool DrawTextOnOSDBitmap(char *msg) {
if (msg_layout % 4 == 2) // upper right
posX = (bmpBuff.u32Width - bitmapText.u32Width) - 2;
if (msg_layout % 4 == 3) // moving
posX = 20 + ((timems / 16) % (bmpBuff.u32Width - bitmapText.u32Width - 40)) & ~1;
posX = 2 + ((timems / 16) % (bmpBuff.u32Width - bitmapText.u32Width - 8)) & ~1;
posY = (msg_layout / 4) == 0 ? 0 : (bmpBuff.u32Height - bitmapText.u32Height) - 2;

if (bitmapText.pData != NULL && bitmapText.enPixelFormat == PIXEL_FORMAT_I4) {
Expand Down

0 comments on commit 2ff523f

Please sign in to comment.