VisionSOM-STM32MP1 simple swipe demo: Difference between revisions
From SomLabs Wiki
No edit summary |
No edit summary |
||
| Line 6: | Line 6: | ||
[[File:swipedemo_page1.jpg|400px]] [[File:swipedemo_page2.jpg|400px]] | [[File:swipedemo_page1.jpg|400px]] [[File:swipedemo_page2.jpg|400px]] | ||
</span> | </span> | ||
== OpenSTLinux configuration == | |||
This example requires the qtcharts module to be included during system build. It may be added to the recipes-st/images/st-image-weston.bbappend file in the meta-somlabs layer. | |||
<pre> | |||
inherit populate_sdk_qt5 | |||
IMAGE_INSTALL += " \ | |||
qtbase-dev \ | |||
qtbase-mkspecs \ | |||
qtbase-tools \ | |||
qtdeclarative-qmlplugins \ | |||
qtquickcontrols2-qmlplugins \ | |||
qtwayland \ | |||
gstreamer1.0 \ | |||
gstreamer1.0-plugins-good \ | |||
qtcharts \ | |||
" | |||
</pre> | |||
== GUI implementation == | == GUI implementation == | ||
Latest revision as of 12:37, 9 April 2021
VisionSOM-STM32MP1 simple swipe demo
This project is a simple demo presenting the Qt application with swipe view and line chart. It was tested on the VisionSOM-STM32MP1 module with VisionCB-STM32MP1-STD and the SL-TFT7-TP-800-480-P RGB display. All project files man be downloaded here: SwipeDemo.zip.
OpenSTLinux configuration
This example requires the qtcharts module to be included during system build. It may be added to the recipes-st/images/st-image-weston.bbappend file in the meta-somlabs layer.
inherit populate_sdk_qt5
IMAGE_INSTALL += " \
qtbase-dev \
qtbase-mkspecs \
qtbase-tools \
qtdeclarative-qmlplugins \
qtquickcontrols2-qmlplugins \
qtwayland \
gstreamer1.0 \
gstreamer1.0-plugins-good \
qtcharts \
"
GUI implementation
The GUI is implemented in the three files described below. The main GUI file: main.qml, defines the application window with two pages. It also contains the implementation of necessary functions that are separated from the ui.qml files.
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow {
visible: true
visibility: "FullScreen"
title: qsTr("Tabs")
SwipeView {
id: swipeView
anchors.fill: parent
currentIndex: tabBar.currentIndex
Page1Form {
button.onCheckedChanged: ledHandler.setEnabled(button.checked)
slider.onValueChanged: ledHandler.setBrightness(slider.value)
}
Page2Form {
id: chartPage
Connections {
target: pointGenerator
onDoAddSample: {
chartPage.addPoint(value)
}
}
function addPoint(value) {
dataSeries.append(numberOfPoints, value)
if (dataSeries.count > maxNumberOfPoints) {
dataSeries.remove(0)
}
dataSeries.xAxis.min += 1
dataSeries.xAxis.max += 1
numberOfPoints += 1
}
}
}
footer: TabBar {
id: tabBar
currentIndex: swipeView.currentIndex
TabButton {
text: qsTr("Page 1")
}
TabButton {
text: qsTr("Page 2")
}
}
}
The Page1Form.ui.qml file contains the first application page description. It defines a checkable button and a slited. Both for LEDs controlling.
import QtQuick 2.9
import QtQuick.Controls 2.2
Page {
property alias button: button
property alias slider: slider
header: Label {
text: qsTr("Page 1")
font.pixelSize: Qt.application.font.pixelSize * 2
padding: 10
}
Button {
id: button
y: 110
width: 120
height: 60
text: qsTr("LED")
anchors.left: parent.left
anchors.leftMargin: 100
anchors.verticalCenter: parent.verticalCenter
checkable: true
}
Slider {
id: slider
x: 260
y: 110
width: 300
anchors.right: parent.right
anchors.rightMargin: 100
anchors.verticalCenterOffset: 0
anchors.verticalCenter: parent.verticalCenter
from: 0
to: 100
stepSize: 10
value: 0
}
}
The Page2Form.ui.qml file contains the second application page description. It defines a ChartView with a line chart and two axes. The line chart has maximum of 100 points. The function responsible for dynamic points adding is implemented in the main.qml file.
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtCharts 2.0
ChartView {
antialiasing: true
animationOptions: ChartView.NoAnimation
property int numberOfPoints: 0
property int maxNumberOfPoints: 100
property alias dataSeries: dataSeries
LineSeries {
id: dataSeries
name: "Values"
useOpenGL: true
property alias xAxis: xAxis
axisX: ValueAxis {
id: xAxis
min: -1 * maxNumberOfPoints
max: 0
visible: false
}
axisY: ValueAxis {
min: 0
max: 100
}
}
}
Application logic
The project contains the LedHandler class responsible for handling the events generated by the button and slider. It simply uses /sys/class/leds filed for brightness control.
#ifndef LEDHANDLER_H
#define LEDHANDLER_H
#include <QObject>
#include <QFile>
class LedHandler : public QObject
{
Q_OBJECT
public:
explicit LedHandler(QObject *parent = nullptr);
signals:
public slots:
void setEnabled(bool enabled);
void setBrightness(unsigned int brightness);
private:
QFile* gpioLedFile;
QFile* pwmLedFile;
};
#endif // LEDHANDLER_H
#include "ledhandler.h"
#include <QDebug>
LedHandler::LedHandler(QObject *parent) : QObject(parent)
{
this->gpioLedFile = new QFile("/sys/class/leds/led3/brightness");
this->gpioLedFile->open(QIODevice::WriteOnly);
this->pwmLedFile = new QFile("/sys/class/leds/led2/brightness");
this->pwmLedFile->open(QIODevice::WriteOnly);
}
void LedHandler::setEnabled(bool enabled)
{
qDebug() << "Enabled" << enabled;
if (enabled)
this->gpioLedFile->write("1");
else
this->gpioLedFile->write("0");
this->gpioLedFile->flush();
}
void LedHandler::setBrightness(unsigned int brightness)
{
qDebug() << "Brightness" << brightness;
this->pwmLedFile->write(QString::number(brightness).toLatin1());
this->pwmLedFile->flush();
}
The second class added in this project is the PointGenerator class. It simply uses a QTimer for sending a signal to the chart every one second.
#ifndef POINTGENERATOR_H
#define POINTGENERATOR_H
#include <QObject>
#include <QTimer>
class PointGenerator : public QObject
{
Q_OBJECT
public:
explicit PointGenerator(QObject *parent = nullptr);
signals:
void doAddSample(int value);
public slots:
void timeout();
private:
QTimer* timer;
};
#endif // POINTGENERATOR_H
#include "pointgenerator.h"
#include <QDateTime>
PointGenerator::PointGenerator(QObject *parent) : QObject(parent)
{
this->timer = new QTimer();
this->timer->setSingleShot(false);
this->timer->start(1000);
connect(this->timer, SIGNAL(timeout()), this, SLOT(timeout()));
qsrand(QDateTime::currentMSecsSinceEpoch() / 1000);
}
void PointGenerator::timeout()
{
emit this->doAddSample(qrand() % 100);
}
Finally the main.cpp file contains the main application function that creates the application and connects the necessary objects with the GUI.
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "ledhandler.h"
#include "pointgenerator.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
LedHandler ledHandler;
ledHandler.setBrightness(0);
ledHandler.setEnabled(false);
PointGenerator pointGenerator;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("ledHandler", &ledHandler);
engine.rootContext()->setContextProperty("pointGenerator", &pointGenerator);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}