/* * Copyright (C) EdgeTX * * Based on code named * opentx - https://github.com/opentx/opentx * th9x - http://code.google.com/p/th9x * er9x - http://code.google.com/p/er9x * gruvin9x - http://code.google.com/p/gruvin9x * * License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "lcdwidget.h" void LcdWidget::setData(int width, int height, int depth) { lcdWidth = width; lcdHeight = height; lcdDepth = depth; if (depth >= 8) lcdSize = (width * height) * ((depth + 7) / 8); else lcdSize = (width * ((height + 7) / 8)) * depth; localBuf = (unsigned char *)malloc(lcdSize); memset(localBuf, 0, lcdSize); } void LcdWidget::setBgDefaultColor(const QColor &color) { bgDefaultColor = color; } void LcdWidget::setFgDefaultColor(const QColor &color) { fgDefaultColor = color; } void LcdWidget::setBackgroundColor(const QColor &color) { bgColor = color; } void LcdWidget::makeScreenshot(const QString &fileName) { int width, height; if (lcdDepth < 12) { width = 2 * lcdWidth; height = 2 * lcdHeight; } else { width = lcdWidth; height = lcdHeight; } QPixmap buffer(width, height); QPainter p(&buffer); doPaint(p); if (fileName.isEmpty()) { QApplication::clipboard()->setPixmap(buffer); qInfo() << "Screenshot saved to clipboard"; } else { buffer.toImage().save(fileName); qInfo() << "Screenshot saved to:" << fileName; } } void LcdWidget::onLcdChanged(uint8_t* lcdBuf, bool light) { // Ingest only: store the latest frame and let frameTimer drive the repaint. // Sampling on a fixed cadence caps the repaint rate without dropping the // final frame of a burst, regardless of how frames are delivered. QMutexLocker locker(&lcdMtx); lightEnable = light; if (lcdBuf) memcpy(localBuf, lcdBuf, lcdSize); dirty = true; if (!frameTimer.isActive()) frameTimer.start(); } void LcdWidget::onFrameTick() { QMutexLocker locker(&lcdMtx); if (!dirty) { // idle: stop until the next frame arrives frameTimer.stop(); return; } dirty = false; update(); } void LcdWidget::doPaint(QPainter &p) { if (!localBuf) return; if (lcdDepth == 16) { QImage img((const uchar*)localBuf, lcdWidth, lcdHeight, lcdWidth * 2, QImage::Format_RGB16); p.drawImage(0, 0, img); return; } if (lcdDepth == 12) { QImage img(lcdWidth, lcdHeight, QImage::Format_RGB32); for (int y = 0; y < lcdHeight; y++) { QRgb* line = (QRgb*)img.scanLine(y); for (int x = 0; x < lcdWidth; x++) { uint16_t z = ((uint16_t *)localBuf)[y * lcdWidth + x]; line[x] = qRgb(255 * ((z & 0xF00) >> 8) / 0x0F, 255 * ((z & 0x0F0) >> 4) / 0x0F, 255 * (z & 0x00F) / 0x0F); } } p.drawImage(0, 0, img); return; } QColor bg = lightEnable ? bgColor : bgDefaultColor; QRgb bgRgb = bg.rgb(); if (lcdDepth == 1) { QRgb fgRgb = fgDefaultColor.rgb(); QImage img(lcdWidth, lcdHeight, QImage::Format_RGB32); for (int y = 0; y < lcdHeight; y++) { QRgb* line = (QRgb*)img.scanLine(y); uint16_t idx = (y / 8) * lcdWidth; uint8_t mask = 1 << (y % 8); for (int x = 0; x < lcdWidth; x++, idx++) { line[x] = (localBuf[idx] & mask) ? fgRgb : bgRgb; } } p.drawImage(QRect(0, 0, 2 * lcdWidth, 2 * lcdHeight), img); return; } // lcdDepth == 4 int bgR = bg.red(), bgG = bg.green(), bgB = bg.blue(); QImage img(lcdWidth, lcdHeight, QImage::Format_RGB32); for (int y = 0; y < lcdHeight; y++) { QRgb* line = (QRgb*)img.scanLine(y); uint16_t idx = (y / 2) * lcdWidth; for (int x = 0; x < lcdWidth; x++, idx++) { uint8_t z = (y & 1) ? (localBuf[idx] >> 4) : (localBuf[idx] & 0x0F); line[x] = qRgb(bgR - (z * bgR) / 15, bgG - (z * bgG) / 15, bgB - (z * bgB) / 15); } } p.drawImage(QRect(0, 0, 2 * lcdWidth, 2 * lcdHeight), img); } void LcdWidget::paintEvent(QPaintEvent *) { QPainter p(this); doPaint(p); } void LcdWidget::mouseMoveEvent(QMouseEvent *event) { emit touchEvent(TouchSlide, event->pos().x(), event->pos().y()); } void LcdWidget::mousePressEvent(QMouseEvent *event) { emit touchEvent(TouchDown, event->pos().x(), event->pos().y()); } void LcdWidget::mouseReleaseEvent(QMouseEvent *event) { emit touchEvent(TouchUp, event->pos().x(), event->pos().y()); }