From 9e785090414f3855b20280d9ee3c0028983f8d13 Mon Sep 17 00:00:00 2001 From: Curtis Bangert Date: Sat, 19 May 2018 18:11:05 -0400 Subject: [PATCH] Linear Buffer for CRSF CMS display port --- src/main/interface/crsf_protocol.h | 17 +++++--- src/main/interface/settings.c | 6 --- src/main/io/displayport_crsf.c | 64 +++++++++++++----------------- src/main/io/displayport_crsf.h | 19 ++++----- src/main/pg/pg_ids.h | 2 +- src/main/rx/crsf.c | 10 +++-- src/main/telemetry/crsf.c | 29 ++++++++------ src/main/telemetry/crsf.h | 2 +- 8 files changed, 71 insertions(+), 78 deletions(-) diff --git a/src/main/interface/crsf_protocol.h b/src/main/interface/crsf_protocol.h index 89d0f6bdc..547044df5 100644 --- a/src/main/interface/crsf_protocol.h +++ b/src/main/interface/crsf_protocol.h @@ -52,15 +52,20 @@ typedef enum { CRSF_FRAMETYPE_MSP_REQ = 0x7A, // response request using msp sequence as command CRSF_FRAMETYPE_MSP_RESP = 0x7B, // reply with 58 byte chunked binary CRSF_FRAMETYPE_MSP_WRITE = 0x7C, // write with 8 byte chunked binary (OpenTX outbound telemetry buffer limit) - CRSF_FRAMETYPE_DISPLAYPORT_UPDATE = 0x7D, // transmit displayport buffer to remote - CRSF_FRAMETYPE_DISPLAYPORT_CLEAR = 0x7E, // clear remote - CRSF_FRAMETYPE_DISPLAYPORT_CMD = 0x7F, // client request + CRSF_FRAMETYPE_DISPLAYPORT_CMD = 0x7D, // displayport control command } crsfFrameType_e; enum { - CRSF_DISPLAYPORT_SUBCMD_OPEN = 0x01, // client request to open cms menu - CRSF_DISPLAYPORT_SUBCMD_CLOSE = 0x02, // client request to close cms menu - CRSF_DISPLAYPORT_SUBCMD_POLL = 0x03, // client request to poll/refresh cms menu + CRSF_DISPLAYPORT_SUBCMD_UPDATE = 0x01, // transmit displayport buffer to remote + CRSF_DISPLAYPORT_SUBCMD_CLEAR = 0X02, // clear client screen + CRSF_DISPLAYPORT_SUBCMD_OPEN = 0x03, // client request to open cms menu + CRSF_DISPLAYPORT_SUBCMD_CLOSE = 0x04, // client request to close cms menu + CRSF_DISPLAYPORT_SUBCMD_POLL = 0x05, // client request to poll/refresh cms menu +}; + +enum { + CRSF_DISPLAYPORT_OPEN_ROWS_OFFSET = 1, + CRSF_DISPLAYPORT_OPEN_COLS_OFFSET = 2, }; enum { diff --git a/src/main/interface/settings.c b/src/main/interface/settings.c index a872320b7..edc046abb 100644 --- a/src/main/interface/settings.c +++ b/src/main/interface/settings.c @@ -949,12 +949,6 @@ const clivalue_t valueTable[] = { { "displayport_msp_row_adjust", VAR_INT8 | MASTER_VALUE, .config.minmax = { -3, 0 }, PG_DISPLAY_PORT_MSP_CONFIG, offsetof(displayPortProfile_t, rowAdjust) }, #endif -// PG_DISPLAY_PORT_CRSF_CONFIG -#if defined(USE_CRSF_CMS_TELEMETRY) - { "displayport_crsf_col_adjust", VAR_INT8 | MASTER_VALUE, .config.minmax = { -8, 0 }, PG_DISPLAY_PORT_CRSF_CONFIG, offsetof(displayPortProfile_t, colAdjust) }, - { "displayport_crsf_row_adjust", VAR_INT8 | MASTER_VALUE, .config.minmax = { -3, 0 }, PG_DISPLAY_PORT_CRSF_CONFIG, offsetof(displayPortProfile_t, rowAdjust) }, -#endif - // PG_DISPLAY_PORT_MSP_CONFIG #ifdef USE_MAX7456 { "displayport_max7456_col_adjust", VAR_INT8| MASTER_VALUE, .config.minmax = { -6, 0 }, PG_DISPLAY_PORT_MAX7456_CONFIG, offsetof(displayPortProfile_t, colAdjust) }, diff --git a/src/main/io/displayport_crsf.c b/src/main/io/displayport_crsf.c index 74a1ed993..11c3a716a 100644 --- a/src/main/io/displayport_crsf.c +++ b/src/main/io/displayport_crsf.c @@ -32,16 +32,13 @@ #include "drivers/display.h" #include "drivers/time.h" #include "io/displayport_crsf.h" -#include "pg/pg_ids.h" #define CRSF_DISPLAY_PORT_OPEN_DELAY_MS 400 -#define CRSF_DISPLAY_PORT_CLEAR_DELAY_MS 38 +#define CRSF_DISPLAY_PORT_CLEAR_DELAY_MS 45 static crsfDisplayPortScreen_t crsfScreen; static timeMs_t delayTransportUntilMs = 0; -PG_REGISTER(displayPortProfile_t, displayPortProfileCrsf, PG_DISPLAY_PORT_CRSF_CONFIG, 0); - displayPort_t crsfDisplayPort; static int crsfGrab(displayPort_t *displayPort) @@ -52,14 +49,8 @@ static int crsfGrab(displayPort_t *displayPort) static int crsfClearScreen(displayPort_t *displayPort) { UNUSED(displayPort); - crsfDisplayPortRow_t *screenRow; - for (int row=0; rowpendingTransport = false; - for (int col=0; coldata[col]=' '; - } - } + memset(crsfScreen.buffer, ' ', sizeof(crsfScreen.buffer)); + memset(crsfScreen.pendingTransport, 0, sizeof(crsfScreen.pendingTransport)); crsfScreen.reset = true; delayTransportUntilMs = millis() + CRSF_DISPLAY_PORT_CLEAR_DELAY_MS; return 0; @@ -86,14 +77,14 @@ static int crsfScreenSize(const displayPort_t *displayPort) static int crsfWriteString(displayPort_t *displayPort, uint8_t col, uint8_t row, const char *s) { UNUSED(displayPort); - if (row >= CRSF_DISPLAY_PORT_ROWS_MAX || col >= CRSF_DISPLAY_PORT_COLS_MAX) { + if (row >= crsfScreen.rows || col >= crsfScreen.cols) { return 0; } - const size_t truncLen = MIN((int)strlen(s), CRSF_DISPLAY_PORT_COLS_MAX-col); // truncate at CRSF_DISPLAY_PORT_COLS_MAX - crsfDisplayPortRow_t *screenRow = &crsfScreen.rows[row]; - screenRow->pendingTransport = memcmp(&screenRow->data[col], s, truncLen); - if (screenRow->pendingTransport) { - memcpy(&screenRow->data[col], s, truncLen); + const size_t truncLen = MIN((int)strlen(s), crsfScreen.cols-col); // truncate at colCount + char *rowStart = &crsfScreen.buffer[row * crsfScreen.cols + col]; + crsfScreen.pendingTransport[row] = memcmp(rowStart, s, truncLen); + if (crsfScreen.pendingTransport[row]) { + memcpy(rowStart, s, truncLen); } return 0; } @@ -125,9 +116,8 @@ static int crsfHeartbeat(displayPort_t *displayPort) static void crsfResync(displayPort_t *displayPort) { - displayPort->rows = CRSF_DISPLAY_PORT_ROWS_MAX + displayPortProfileCrsf()->rowAdjust; - displayPort->cols = CRSF_DISPLAY_PORT_COLS_MAX + displayPortProfileCrsf()->colAdjust; - crsfClearScreen(displayPort); + displayPort->rows = crsfScreen.rows; + displayPort->cols = crsfScreen.cols; } static uint32_t crsfTxBytesFree(const displayPort_t *displayPort) @@ -151,13 +141,6 @@ static const displayPortVTable_t crsfDisplayPortVTable = { .txBytesFree = crsfTxBytesFree }; -displayPort_t *displayPortCrsfInit() -{ - displayInit(&crsfDisplayPort, &crsfDisplayPortVTable); - crsfResync(&crsfDisplayPort); - return &crsfDisplayPort; -} - crsfDisplayPortScreen_t *crsfDisplayPortScreen(void) { return &crsfScreen; @@ -183,6 +166,12 @@ void crsfDisplayPortMenuExit(void) cmsMenuExit(&crsfDisplayPort, &exitMenu); } +void crsfDisplayPortSetDimensions(uint8_t rows, uint8_t cols) +{ + crsfScreen.rows = MIN(rows, CRSF_DISPLAY_PORT_ROWS_MAX); + crsfScreen.cols = MIN(cols, CRSF_DISPLAY_PORT_COLS_MAX); + crsfResync(&crsfDisplayPort); +} void crsfDisplayPortRefresh(void) { @@ -190,12 +179,9 @@ void crsfDisplayPortRefresh(void) crsfDisplayPortMenuOpen(); return; } - crsfDisplayPortRow_t *screenRow; - for (int row=0; rowpendingTransport = true; - } + memset(crsfScreen.pendingTransport, 1, crsfScreen.rows); crsfScreen.reset = true; + delayTransportUntilMs = millis() + CRSF_DISPLAY_PORT_CLEAR_DELAY_MS; } int crsfDisplayPortNextRow(void) @@ -204,14 +190,18 @@ int crsfDisplayPortNextRow(void) if (currentTimeMs < delayTransportUntilMs) { return -1; } - crsfDisplayPortRow_t *screenRow; - for(int i=0; ipendingTransport) { + for(unsigned int i=0; icolAdjust; - const uint8_t frameLength = CRSF_FRAME_LENGTH_EXT_TYPE_CRC + bufLen; + uint8_t buflen = crsfDisplayPortScreen()->cols; + char *rowStart = &crsfDisplayPortScreen()->buffer[row * buflen]; + const uint8_t frameLength = CRSF_FRAME_LENGTH_EXT_TYPE_CRC + buflen; sbufWriteU8(dst, frameLength); - sbufWriteU8(dst, CRSF_FRAMETYPE_DISPLAYPORT_UPDATE); + sbufWriteU8(dst, CRSF_FRAMETYPE_DISPLAYPORT_CMD); sbufWriteU8(dst, CRSF_ADDRESS_RADIO_TRANSMITTER); sbufWriteU8(dst, CRSF_ADDRESS_FLIGHT_CONTROLLER); + sbufWriteU8(dst, CRSF_DISPLAYPORT_SUBCMD_UPDATE); sbufWriteU8(dst, row); - sbufWriteData(dst, str, bufLen); + sbufWriteData(dst, rowStart, buflen); *lengthPtr = sbufPtr(dst) - lengthPtr; } @@ -329,9 +331,10 @@ static void crsfFrameDisplayPortClear(sbuf_t *dst) { uint8_t *lengthPtr = sbufPtr(dst); sbufWriteU8(dst, CRSF_DISPLAY_PORT_COLS_MAX + CRSF_FRAME_LENGTH_EXT_TYPE_CRC); - sbufWriteU8(dst, CRSF_FRAMETYPE_DISPLAYPORT_CLEAR); + sbufWriteU8(dst, CRSF_FRAMETYPE_DISPLAYPORT_CMD); sbufWriteU8(dst, CRSF_ADDRESS_RADIO_TRANSMITTER); sbufWriteU8(dst, CRSF_ADDRESS_FLIGHT_CONTROLLER); + sbufWriteU8(dst, CRSF_DISPLAYPORT_SUBCMD_CLEAR); *lengthPtr = sbufPtr(dst) - lengthPtr; } @@ -449,10 +452,14 @@ bool checkCrsfTelemetryState(void) } #if defined(USE_CRSF_CMS_TELEMETRY) -void crsfProcessDisplayPortCmd(uint8_t cmd) +void crsfProcessDisplayPortCmd(uint8_t *frameStart) { + uint8_t cmd = *frameStart; switch (cmd) { - case CRSF_DISPLAYPORT_SUBCMD_OPEN: + case CRSF_DISPLAYPORT_SUBCMD_OPEN: ; + const uint8_t rows = *(frameStart + CRSF_DISPLAYPORT_OPEN_ROWS_OFFSET); + const uint8_t cols = *(frameStart + CRSF_DISPLAYPORT_OPEN_COLS_OFFSET); + crsfDisplayPortSetDimensions(rows, cols); crsfDisplayPortMenuOpen(); break; case CRSF_DISPLAYPORT_SUBCMD_CLOSE: @@ -460,7 +467,6 @@ void crsfProcessDisplayPortCmd(uint8_t cmd) break; case CRSF_DISPLAYPORT_SUBCMD_POLL: crsfDisplayPortRefresh(); - crsfDisplayPortScreen()->reset = true; break; default: break; @@ -518,13 +524,12 @@ void handleCrsfTelemetry(timeUs_t currentTimeUs) } const int nextRow = crsfDisplayPortNextRow(); if (nextRow >= 0) { - crsfDisplayPortRow_t *row = &crsfDisplayPortScreen()->rows[nextRow]; sbuf_t crsfDisplayPortBuf; sbuf_t *dst = &crsfDisplayPortBuf; crsfInitializeFrame(dst); - crsfFrameDisplayPortRow(dst, nextRow, row->data); + crsfFrameDisplayPortRow(dst, nextRow); crsfFinalize(dst); - row->pendingTransport = false; + crsfDisplayPortScreen()->pendingTransport[nextRow] = false; crsfLastCycleTime = currentTimeUs; return; } diff --git a/src/main/telemetry/crsf.h b/src/main/telemetry/crsf.h index 9cada9957..1b2cc32e0 100644 --- a/src/main/telemetry/crsf.h +++ b/src/main/telemetry/crsf.h @@ -36,7 +36,7 @@ void crsfScheduleDeviceInfoResponse(void); void crsfScheduleMspResponse(void); int getCrsfFrame(uint8_t *frame, crsfFrameType_e frameType); #if defined(USE_CRSF_CMS_TELEMETRY) -void crsfProcessDisplayPortCmd(uint8_t cmd); +void crsfProcessDisplayPortCmd(uint8_t *frameStart); #endif #if defined(USE_MSP_OVER_TELEMETRY) void initCrsfMspBuffer(void);