21
21
#include "msp.h"
22
22
#include "msp_displayport.h"
23
23
24
- #define OSD_WIDTH 31
25
- #define OSD_HEIGHT 15
26
-
27
- #define X_OFFSET 180
28
- #define Y_OFFSET 0
29
-
30
24
#define PORT 7654
31
25
32
26
#define WIDTH 1440
33
27
#define HEIGHT 810
34
28
#define BYTES_PER_PIXEL 4
35
29
#define PLANE_ID 6
36
30
37
- #define FONT_WIDTH 36
38
- #define FONT_HEIGHT 54
31
+ #define NUM_CHARS 256
39
32
40
33
#define INPUT_FILENAME "/dev/input/event0"
41
34
#define SPLASH_STRING "MSP OSD WAITING FOR DATA..."
42
35
#define SHUTDOWN_STRING "MSP OSD SHUTTING DOWN..."
43
36
44
- #define FALLBACK_FONT_PATH "/blackbox/font.bin"
45
- #define ENTWARE_FONT_PATH "/opt/fonts/font.bin"
46
- #define SDCARD_FONT_PATH "/storage/sdcard0/font.bin"
47
- #define FONT_FILE_SIZE 1990656
37
+ #define FALLBACK_FONT_PATH "/blackbox/font"
38
+ #define ENTWARE_FONT_PATH "/opt/fonts/font"
39
+ #define SDCARD_FONT_PATH "/storage/sdcard0/font"
48
40
49
41
#define EV_CODE_BACK 0xc9
50
42
60
52
( (((data) >> 24) & 0x000000FF) | (((data) >> 8) & 0x0000FF00) | \
61
53
(((data) << 8) & 0x00FF0000) | (((data) << 24) & 0xFF000000) )
62
54
55
+ #define MAX_DISPLAY_X 50
56
+ #define MAX_DISPLAY_Y 18
57
+
58
+ typedef struct display_info_s {
59
+ uint8_t char_width ;
60
+ uint8_t char_height ;
61
+ uint8_t font_width ;
62
+ uint8_t font_height ;
63
+ uint16_t x_offset ;
64
+ uint16_t y_offset ;
65
+ } display_info_t ;
66
+
63
67
static volatile sig_atomic_t quit = 0 ;
64
- dji_display_state_t * dji_display ;
65
- uint8_t character_map [OSD_WIDTH ][OSD_HEIGHT ];
66
- displayport_vtable_t * display_driver ;
67
- void * font ;
68
- uint8_t which_fb = 0 ;
68
+ static dji_display_state_t * dji_display ;
69
+ static uint16_t character_map [MAX_DISPLAY_X ][MAX_DISPLAY_Y ];
70
+ static displayport_vtable_t * display_driver ;
71
+ static void * font_page_1 = NULL ;
72
+ static void * font_page_2 = NULL ;
73
+ static uint8_t which_fb = 0 ;
74
+
75
+ #define SD_DISPLAY_INFO {.char_width = 31, .char_height = 15, .font_width = 36, .font_height = 54, .x_offset = 180, .y_offset = 0}
76
+
77
+ static display_info_t sd_display_info = SD_DISPLAY_INFO ;
78
+
79
+ static display_info_t hd_display_info = {
80
+ .char_width = 50 ,
81
+ .char_height = 18 ,
82
+ .font_width = 24 ,
83
+ .font_height = 36 ,
84
+ .x_offset = 120 ,
85
+ .y_offset = 80
86
+ };
87
+
88
+ static display_info_t current_display_info = SD_DISPLAY_INFO ;
69
89
70
90
static void sig_handler (int _ )
71
91
{
72
92
quit = 1 ;
73
93
}
74
94
75
- static void draw_character (uint32_t x , uint32_t y , uint8_t c )
95
+ static void draw_character (uint32_t x , uint32_t y , uint16_t c )
76
96
{
77
- if ((x > (OSD_WIDTH - 1 )) || (y > (OSD_HEIGHT - 1 ))) {
97
+ if ((x > (current_display_info . char_width - 1 )) || (y > (current_display_info . char_height - 1 ))) {
78
98
return ;
79
99
}
80
100
character_map [x ][y ] = c ;
81
101
}
82
102
83
103
static void draw_screen () {
104
+ if (font_page_1 == NULL ) {
105
+ // give up if we don't have a font loaded
106
+ return ;
107
+ }
108
+ void * font ;
84
109
void * fb_addr = dji_display_get_fb_address (dji_display , which_fb );
85
110
// DJI has a backwards alpha channel - FF is transparent, 00 is opaque.
86
111
memset (fb_addr , 0x000000FF , WIDTH * HEIGHT * BYTES_PER_PIXEL );
87
- for (int y = 0 ; y < OSD_HEIGHT ; y ++ ) {
88
- for (int x = 0 ; x < OSD_WIDTH ; x ++ ) {
89
- uint8_t c = character_map [x ][y ];
112
+ for (int y = 0 ; y < current_display_info . char_height ; y ++ ) {
113
+ for (int x = 0 ; x < current_display_info . char_width ; x ++ ) {
114
+ uint16_t c = character_map [x ][y ];
90
115
if (c != 0 ) {
91
- uint32_t pixel_x = (x * FONT_WIDTH ) + X_OFFSET ;
92
- uint32_t pixel_y = (y * FONT_HEIGHT ) + Y_OFFSET ;
93
- uint32_t character_offset = (((FONT_HEIGHT * FONT_WIDTH ) * BYTES_PER_PIXEL ) * c );
94
- for (uint8_t gx = 0 ; gx < FONT_WIDTH ; gx ++ ) {
95
- for (uint8_t gy = 0 ; gy < FONT_HEIGHT ; gy ++ ) {
96
- uint32_t font_offset = character_offset + (gy * FONT_WIDTH * BYTES_PER_PIXEL ) + (gx * BYTES_PER_PIXEL );
116
+ font = font_page_1 ;
117
+ if (c > 255 ) {
118
+ c = c & 0xFF ;
119
+ if (font_page_2 != NULL ) {
120
+ // fall back to writing page 1 chars if we don't have a page 2 font
121
+ font = font_page_2 ;
122
+ }
123
+ }
124
+ uint32_t pixel_x = (x * current_display_info .font_width ) + current_display_info .x_offset ;
125
+ uint32_t pixel_y = (y * current_display_info .font_height ) + current_display_info .y_offset ;
126
+ uint32_t character_offset = (((current_display_info .font_height * current_display_info .font_width ) * BYTES_PER_PIXEL ) * c );
127
+ for (uint8_t gx = 0 ; gx < current_display_info .font_width ; gx ++ ) {
128
+ for (uint8_t gy = 0 ; gy < current_display_info .font_height ; gy ++ ) {
129
+ uint32_t font_offset = character_offset + (gy * current_display_info .font_width * BYTES_PER_PIXEL ) + (gx * BYTES_PER_PIXEL );
97
130
uint32_t target_offset = ((((pixel_x + gx ) * BYTES_PER_PIXEL ) + ((pixel_y + gy ) * WIDTH * BYTES_PER_PIXEL )));
98
131
* ((uint8_t * )fb_addr + target_offset ) = * (uint8_t * )((uint8_t * )font + font_offset + 2 );
99
132
* ((uint8_t * )fb_addr + target_offset + 1 ) = * (uint8_t * )((uint8_t * )font + font_offset + 1 );
@@ -126,33 +159,87 @@ static void msp_callback(msp_msg_t *msp_message)
126
159
displayport_process_message (display_driver , msp_message );
127
160
}
128
161
129
- static int open_font (const char * filename , void * * font ) {
130
- printf ("Opening font: %s\n" , filename );
162
+ static void get_font_path_with_prefix (char * font_path_dest , const char * font_path , uint8_t len , uint8_t is_hd , uint8_t page ) {
163
+ char name_buf [len ];
164
+ if (is_hd ) {
165
+ snprintf (name_buf , len , "%s_hd" , font_path );
166
+ } else {
167
+ snprintf (name_buf , len , "%s" , font_path );
168
+ }
169
+ if (page > 0 ) {
170
+ snprintf (font_path_dest , len , "%s_%d.bin" , name_buf , page + 1 );
171
+ } else {
172
+ snprintf (font_path_dest , len , "%s.bin" , name_buf );
173
+ }
174
+ }
175
+
176
+ static int open_font (const char * filename , void * * font , uint8_t page ) {
177
+ char file_path [255 ];
178
+ get_font_path_with_prefix (file_path , filename , 255 , (current_display_info .font_width < sd_display_info .font_width ), page );
179
+ printf ("Opening font: %s\n" , file_path );
131
180
struct stat st ;
132
- stat (filename , & st );
181
+ memset (& st , 0 , sizeof (st ));
182
+ stat (file_path , & st );
133
183
size_t filesize = st .st_size ;
134
- if (filesize != FONT_FILE_SIZE ) {
184
+ size_t desired_filesize = current_display_info .font_height * current_display_info .font_width * NUM_CHARS * BYTES_PER_PIXEL ;
185
+ if (filesize != desired_filesize ) {
186
+ if (filesize != 0 ) {
187
+ printf ("Font was wrong size: %s %d != %d\n" , file_path , filesize , desired_filesize );
188
+ }
135
189
return -1 ;
136
190
}
137
- int fd = open (filename , O_RDONLY , 0 );
191
+ int fd = open (file_path , O_RDONLY , 0 );
138
192
if (!fd ) {
193
+ printf ("Could not open file %s\n" , file_path );
139
194
return -1 ;
140
195
}
141
196
void * mmappedData = mmap (NULL , filesize , PROT_READ , MAP_PRIVATE , fd , 0 );
142
- assert (mmappedData != MAP_FAILED );
143
197
// there is no need to keep an FD open after mmap
144
198
close (fd );
145
- * font = mmappedData ;
199
+ if (mmappedData != MAP_FAILED ) {
200
+ * font = mmappedData ;
201
+ } else {
202
+ printf ("Could not map font %s\n" , file_path );
203
+ * font = 0 ;
204
+ }
146
205
return 0 ;
147
206
}
148
207
208
+ static void load_font () {
209
+ if (open_font (SDCARD_FONT_PATH , & font_page_1 , 0 ) < 0 ) {
210
+ if (open_font (ENTWARE_FONT_PATH , & font_page_1 , 0 ) < 0 ) {
211
+ open_font (FALLBACK_FONT_PATH , & font_page_1 , 0 );
212
+ }
213
+ }
214
+ if (open_font (SDCARD_FONT_PATH , & font_page_2 , 1 ) < 0 ) {
215
+ if (open_font (ENTWARE_FONT_PATH , & font_page_2 , 1 ) < 0 ) {
216
+ open_font (FALLBACK_FONT_PATH , & font_page_2 , 1 );
217
+ }
218
+ }
219
+ }
220
+
149
221
static void close_font (void * font ) {
150
- munmap (font , FONT_FILE_SIZE );
222
+ if (font != NULL )
223
+ {
224
+ munmap (font , current_display_info .font_height * current_display_info .font_width * NUM_CHARS * 4 );
225
+ }
226
+ }
227
+
228
+ static void set_options (uint8_t font_num , uint8_t is_hd ) {
229
+ clear_screen ();
230
+ close_font (font_page_1 );
231
+ close_font (font_page_2 );
232
+ if (is_hd ) {
233
+ current_display_info = hd_display_info ;
234
+ } else {
235
+ current_display_info = sd_display_info ;
236
+ }
237
+ load_font ();
151
238
}
152
239
153
240
static void display_print_string (const char * string , uint8_t len ) {
154
241
for (int x = 0 ; x < len ; x ++ ) {
155
- character_map [x ][OSD_HEIGHT - 2 ] = string [x ];
242
+ character_map [x ][current_display_info . char_height - 2 ] = string [x ];
156
243
}
157
244
draw_complete ();
158
245
}
@@ -170,14 +257,6 @@ static void stop_display() {
170
257
dji_display_state_free (dji_display );
171
258
}
172
259
173
- static void load_font () {
174
- if (open_font (SDCARD_FONT_PATH , & font ) < 0 ) {
175
- if (open_font (ENTWARE_FONT_PATH , & font ) < 0 ) {
176
- open_font (FALLBACK_FONT_PATH , & font );
177
- }
178
- }
179
- }
180
-
181
260
int main (int argc , char * argv [])
182
261
{
183
262
signal (SIGINT , sig_handler );
@@ -189,6 +268,7 @@ int main(int argc, char *argv[])
189
268
display_driver -> draw_character = & draw_character ;
190
269
display_driver -> clear_screen = & clear_screen ;
191
270
display_driver -> draw_complete = & draw_complete ;
271
+ display_driver -> set_options = & set_options ;
192
272
193
273
msp_state_t * msp_state = calloc (1 , sizeof (msp_state_t ));
194
274
msp_state -> cb = & msp_callback ;
@@ -238,7 +318,8 @@ int main(int argc, char *argv[])
238
318
printf ("Switching Enabled/Waiting -> Disabled!\n" );
239
319
if (display_mode == DISPLAY_RUNNING )
240
320
stop_display ();
241
- close_font (font );
321
+ close_font (font_page_1 );
322
+ close_font (font_page_2 );
242
323
display_mode = DISPLAY_DISABLED ;
243
324
dji_start_goggles (is_v2_goggles );
244
325
}
0 commit comments