Remove test #defines
[inav.git] / src / main / io / displayport_hdzero_osd.c
blob6483610b2e2471bc89fddfb6d2ce08f4d6382373
1 /*
2 * This file is part of INAV Project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
6 * You can obtain one at http://mozilla.org/MPL/2.0/.
8 * Alternatively, the contents of this file may be used under the terms
9 * of the GNU General Public License Version 3, as described below:
11 * This file is free software: you may copy, redistribute and/or modify
12 * it under the terms of the GNU General Public License as published by the
13 * Free Software Foundation, either version 3 of the License, or (at your
14 * option) any later version.
16 * This file is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
19 * Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see http://www.gnu.org/licenses/.
25 #include <stdbool.h>
26 #include <stdint.h>
27 #include <string.h>
29 #include "platform.h"
31 #if defined(USE_OSD) && defined(USE_HDZERO_OSD)
33 #include "common/utils.h"
34 #include "common/printf.h"
35 #include "common/time.h"
37 #include "drivers/display.h"
38 #include "drivers/display_font_metadata.h"
39 #include "drivers/osd_symbols.h"
41 #include "msp/msp_protocol.h"
42 #include "msp/msp_serial.h"
44 #include "displayport_hdzero_osd.h"
46 #define MSP_HEARTBEAT 0
47 #define MSP_RELEASE 1
48 #define MSP_CLEAR_SCREEN 2
49 #define MSP_WRITE_STRING 3
50 #define MSP_DRAW_SCREEN 4
51 #define MSP_SET_HD 5
53 #define FONT_PAGE_ATTRIBUTE 0x01
55 static mspPort_t hdzeroMspPort;
56 static displayPort_t hdzeroOsdDisplayPort;
57 static bool hdzeroVtxReady;
59 // HD screen size
60 #define ROWS 18
61 #define COLS 50
62 #define SCREENSIZE (ROWS*COLS)
63 static uint8_t screen[SCREENSIZE];
64 static uint8_t fontPage[SCREENSIZE / 8 + 1]; // page bits for each character (to address 512 char font)
66 extern uint8_t cliMode;
68 static int output(displayPort_t *displayPort, uint8_t cmd, uint8_t *subcmd, int len)
70 UNUSED(displayPort);
72 if (cliMode)
73 return 0;
75 return mspSerialPushPort(cmd, subcmd, len, &hdzeroMspPort, MSP_V1);
78 static int heartbeat(displayPort_t *displayPort)
80 uint8_t subcmd[] = { MSP_HEARTBEAT };
81 return output(displayPort, MSP_DISPLAYPORT, subcmd, sizeof(subcmd));
84 static int release(displayPort_t *displayPort)
86 uint8_t subcmd[] = { MSP_RELEASE };
87 return output(displayPort, MSP_DISPLAYPORT, subcmd, sizeof(subcmd));
90 static int clearScreen(displayPort_t *displayPort)
92 UNUSED(displayPort);
94 memset(screen, SYM_BLANK, sizeof(screen));
95 memset(fontPage, 0, sizeof(fontPage));
96 return 1;
100 * Write up to three populated rows at a time, skipping blank lines.
101 * This gives a refresh rate to the VTX of approximately 10 to 62Hz
102 * depending on how much data is displayed.
104 static int drawScreen(displayPort_t *displayPort) // 62.5hz
106 static uint8_t row = 0, clearSent = 0;
107 uint8_t subcmd[COLS + 4], len, col, page, aPage, rowsToPrint;
108 uint16_t lineIdx, idx, end;
109 int charsOut = 0;
111 rowsToPrint = 3;
112 do {
113 // Find a row with something to print
114 do {
115 // Strip leading and trailing spaces for the selected row
116 lineIdx = row * COLS;
117 idx = lineIdx;
118 end = idx + COLS - 1;
120 while ((screen[idx] == SYM_BLANK || screen[end] == SYM_BLANK) && idx <= end) {
121 if (screen[idx] == SYM_BLANK)
122 idx++;
123 if (screen[end] == SYM_BLANK)
124 end--;
126 } while (idx > end && ++row < ROWS);
128 while (idx <= end) {
129 if (!clearSent) {
130 // Start the transaction
131 subcmd[0] = MSP_CLEAR_SCREEN;
132 charsOut += output(displayPort, MSP_DISPLAYPORT, subcmd, 1);
133 clearSent = 1;
136 // Split the line up into strings from the same font page and output them.
137 // (note spaces are printed to save overhead on small elements)
138 len = 4;
139 col = idx - lineIdx;
140 page = (fontPage[idx >> 3] >> (idx & 0x07)) & FONT_PAGE_ATTRIBUTE;
142 do {
143 subcmd[len++] = screen[idx++];
144 aPage = (fontPage[idx >> 3] >> (idx & 0x07)) & FONT_PAGE_ATTRIBUTE;
145 } while (idx <= end && (aPage == page || screen[idx] == SYM_BLANK));
147 subcmd[0] = MSP_WRITE_STRING;
148 subcmd[1] = row;
149 subcmd[2] = col;
150 subcmd[3] = page;
151 charsOut += output(displayPort, MSP_DISPLAYPORT, subcmd, len);
153 } while (++row < ROWS && --rowsToPrint);
155 if (row >= ROWS) {
156 // End the transaction if required and reset the counters
157 if (clearSent > 0) {
158 subcmd[0] = MSP_DRAW_SCREEN;
159 charsOut += output(displayPort, MSP_DISPLAYPORT, subcmd, 1);
161 row = clearSent = 0;
164 return charsOut;
167 static int setHdMode(displayPort_t *displayPort)
169 uint8_t subcmd[3];
170 subcmd[0] = MSP_SET_HD;
171 subcmd[1] = 0; // future font index
172 subcmd[2] = 1; // 0 SD 1 HD
174 return output(displayPort, MSP_DISPLAYPORT, subcmd, sizeof(subcmd));
177 static int grab(displayPort_t *displayPort)
179 return heartbeat(displayPort);
182 static int screenSize(const displayPort_t *displayPort)
184 UNUSED(displayPort);
186 return SCREENSIZE;
189 // Intercept writeString and write to a buffer instead (1st page of font file only)
190 static int writeString(displayPort_t *displayPort, uint8_t col, uint8_t row, const char *string, textAttributes_t attr)
192 UNUSED(displayPort);
193 UNUSED(attr);
195 uint16_t i, pos, len, end, idx;
197 pos = (row * COLS) + col;
198 if (pos >= SCREENSIZE)
199 return 0;
201 len = strlen(string);
203 // Allow word wrap and truncate of past the screen end
204 end = pos + len - 1;
205 if (end >= SCREENSIZE)
206 len = end - SCREENSIZE;
208 // Copy the string into the screen buffer
209 memcpy(screen + pos, string, len);
211 // Clear the page bits for all the characters in the string
212 for (i = 0; i < len; i++) {
213 idx = pos + i;
214 fontPage[idx >> 3] &= ~(1 << (idx & 0x07));
217 return (int) len;
220 // Write character to screen and page buffers (supports 512 char fonts)
221 static int writeChar(displayPort_t *displayPort, uint8_t col, uint8_t row, uint16_t c, textAttributes_t attr)
223 UNUSED(displayPort);
224 UNUSED(attr);
226 uint16_t pos, idx;
227 uint8_t bitmask;
229 pos = (row * COLS) + col;
230 if (pos >= SCREENSIZE)
231 return 0;
233 // Copy character into screen buffer
234 screen[pos] = c;
236 idx = pos >> 3;
237 bitmask = 1 << (pos & 0x07);
239 // Save index of the character's font page
240 if (c & 0x0100)
241 fontPage[idx] |= bitmask;
242 else
243 fontPage[idx] &= ~bitmask;
245 return (int) 1;
248 static bool readChar(displayPort_t *displayPort, uint8_t col, uint8_t row, uint16_t *c, textAttributes_t *attr)
250 UNUSED(displayPort);
252 uint16_t pos, chr;
254 pos = (row * COLS) + col;
255 if (pos >= SCREENSIZE)
256 *c = SYM_BLANK;
257 else {
258 chr = (fontPage[pos >> 3] >> (pos & 0x07)) & FONT_PAGE_ATTRIBUTE;
259 *c = (chr << 8) | screen[pos];
262 if (attr)
263 *attr = TEXT_ATTRIBUTES_NONE;
265 return true;
268 static bool isTransferInProgress(const displayPort_t *displayPort)
270 UNUSED(displayPort);
272 return false;
275 static void resync(displayPort_t *displayPort)
277 displayPort->rows = ROWS;
278 displayPort->cols = COLS;
279 setHdMode(displayPort);
282 static uint32_t txBytesFree(const displayPort_t *displayPort)
284 UNUSED(displayPort);
286 return mspSerialTxBytesFree();
289 static textAttributes_t supportedTextAttributes(const displayPort_t *displayPort)
291 UNUSED(displayPort);
293 textAttributes_t attr = TEXT_ATTRIBUTES_NONE;
294 //TEXT_ATTRIBUTES_ADD_INVERTED(attr);
295 //TEXT_ATTRIBUTES_ADD_SOLID_BG(attr);
296 return attr;
299 static bool getFontMetadata(displayFontMetadata_t *metadata, const displayPort_t *displayPort)
301 UNUSED(displayPort);
303 metadata->charCount = 512;
304 metadata->version = 3;
306 return true;
309 static bool isReady(displayPort_t *displayPort)
311 UNUSED(displayPort);
313 return hdzeroVtxReady;
316 static const displayPortVTable_t hdzeroOsdVTable = {
317 .grab = grab,
318 .release = release,
319 .clearScreen = clearScreen,
320 .drawScreen = drawScreen,
321 .screenSize = screenSize,
322 .writeString = writeString,
323 .writeChar = writeChar,
324 .readChar = readChar,
325 .isTransferInProgress = isTransferInProgress,
326 .heartbeat = heartbeat,
327 .resync = resync,
328 .txBytesFree = txBytesFree,
329 .supportedTextAttributes = supportedTextAttributes,
330 .getFontMetadata = getFontMetadata,
331 .isReady = isReady,
334 void hdzeroOsdSerialInit(void)
336 memset(&hdzeroMspPort, 0, sizeof(mspPort_t));
338 serialPortConfig_t *portConfig = findSerialPortConfig(FUNCTION_HDZERO_OSD);
340 if (portConfig) {
341 serialPort_t *port = openSerialPort(portConfig->identifier, FUNCTION_HDZERO_OSD, NULL, NULL,
342 baudRates[portConfig->msp_baudrateIndex], MODE_RXTX, SERIAL_NOT_INVERTED);
343 if (port)
344 resetMspPort(&hdzeroMspPort, port);
348 displayPort_t* hdzeroOsdDisplayPortInit(void)
350 memset(screen, SYM_BLANK, sizeof(screen));
351 memset(fontPage, 0, sizeof(fontPage));
352 displayInit(&hdzeroOsdDisplayPort, &hdzeroOsdVTable);
353 return &hdzeroOsdDisplayPort;
356 void hdzeroOsdSerialProcess(mspEvaluateNonMspData_e evaluateNonMspData, mspProcessCommandFnPtr mspProcessCommandFn)
358 if (hdzeroMspPort.port) {
359 // Process normal MSP command
360 mspSerialProcessOnePort(&hdzeroMspPort, evaluateNonMspData, mspProcessCommandFn);
361 hdzeroVtxReady = true;
365 #endif // USE_HDZERO_OSD