Remove premature non-DRI layers
This commit is contained in:
@@ -1,100 +0,0 @@
|
||||
#include "APP/AppKeyButton.h"
|
||||
|
||||
#include "APP/AppTheme.h"
|
||||
|
||||
namespace APP
|
||||
{
|
||||
|
||||
App_KeyButton::App_KeyButton(quint16 Usage, const QString& Text, QWidget* p_Parent)
|
||||
: QPushButton(Text, p_Parent),
|
||||
appUsage(Usage),
|
||||
appBaseText(Text)
|
||||
{
|
||||
setMinimumSize(88, 72);
|
||||
setCheckable(false);
|
||||
App_Func_RefreshText();
|
||||
App_Func_RefreshStyle();
|
||||
}
|
||||
|
||||
quint16 App_KeyButton::App_Func_GetUsage() const
|
||||
{
|
||||
return appUsage;
|
||||
}
|
||||
|
||||
void App_KeyButton::App_Func_SetPressedState(bool IsPressed)
|
||||
{
|
||||
if (appIsPressed == IsPressed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
appIsPressed = IsPressed;
|
||||
App_Func_RefreshStyle();
|
||||
}
|
||||
|
||||
void App_KeyButton::App_Func_SetLatchedState(bool IsLatched)
|
||||
{
|
||||
if (appIsLatched == IsLatched)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
appIsLatched = IsLatched;
|
||||
App_Func_RefreshStyle();
|
||||
}
|
||||
|
||||
void App_KeyButton::App_Func_SetFeatureText(const QString& Text)
|
||||
{
|
||||
if (appFeatureText == Text.trimmed())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
appFeatureText = Text.trimmed();
|
||||
App_Func_RefreshText();
|
||||
}
|
||||
|
||||
void App_KeyButton::App_Func_RefreshText()
|
||||
{
|
||||
if (appFeatureText.isEmpty())
|
||||
{
|
||||
setText(appBaseText);
|
||||
return;
|
||||
}
|
||||
|
||||
setText(QStringLiteral("%1\n%2").arg(appBaseText, appFeatureText));
|
||||
}
|
||||
|
||||
void App_KeyButton::App_Func_RefreshStyle()
|
||||
{
|
||||
const App_ThemePalette Palette = App_Theme_DefaultPalette();
|
||||
const QColor FillColor = appIsPressed
|
||||
? Palette.Accent
|
||||
: (appIsLatched ? Palette.AccentSoft : Palette.Surface);
|
||||
const QColor TextColor = appIsPressed
|
||||
? QColor(15, 23, 42)
|
||||
: Palette.TextPrimary;
|
||||
|
||||
setStyleSheet(QStringLiteral(
|
||||
"QPushButton {"
|
||||
" background:rgb(%1,%2,%3);"
|
||||
" color:rgb(%4,%5,%6);"
|
||||
" border:1px solid rgb(%7,%8,%9);"
|
||||
" border-radius:12px;"
|
||||
" font-size:16px;"
|
||||
" font-weight:600;"
|
||||
" padding:8px;"
|
||||
"}"
|
||||
)
|
||||
.arg(FillColor.red())
|
||||
.arg(FillColor.green())
|
||||
.arg(FillColor.blue())
|
||||
.arg(TextColor.red())
|
||||
.arg(TextColor.green())
|
||||
.arg(TextColor.blue())
|
||||
.arg(Palette.Border.red())
|
||||
.arg(Palette.Border.green())
|
||||
.arg(Palette.Border.blue()));
|
||||
}
|
||||
|
||||
} // namespace APP
|
||||
@@ -1,30 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
#include <QtWidgets/QPushButton>
|
||||
|
||||
namespace APP
|
||||
{
|
||||
|
||||
class App_KeyButton : public QPushButton
|
||||
{
|
||||
public:
|
||||
explicit App_KeyButton(quint16 Usage, const QString& Text, QWidget* p_Parent = nullptr);
|
||||
|
||||
quint16 App_Func_GetUsage() const;
|
||||
void App_Func_SetPressedState(bool IsPressed);
|
||||
void App_Func_SetLatchedState(bool IsLatched);
|
||||
void App_Func_SetFeatureText(const QString& Text);
|
||||
|
||||
private:
|
||||
void App_Func_RefreshText();
|
||||
void App_Func_RefreshStyle();
|
||||
|
||||
quint16 appUsage = 0;
|
||||
bool appIsPressed = false;
|
||||
bool appIsLatched = false;
|
||||
QString appBaseText;
|
||||
QString appFeatureText;
|
||||
};
|
||||
|
||||
} // namespace APP
|
||||
@@ -1,133 +0,0 @@
|
||||
#include "APP/AppKeyboardPage.h"
|
||||
|
||||
#include "APP/AppKeyButton.h"
|
||||
#include "APP/AppTheme.h"
|
||||
|
||||
#include <QtWidgets/QFrame>
|
||||
#include <QtWidgets/QGridLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
namespace APP
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
struct App_KeySpec
|
||||
{
|
||||
quint16 Usage;
|
||||
const char* Text;
|
||||
int Row;
|
||||
int Column;
|
||||
int RowSpan;
|
||||
int ColumnSpan;
|
||||
};
|
||||
|
||||
const App_KeySpec kKeySpecList[] = {
|
||||
{ 0x0053, "Num", 0, 0, 1, 1 },
|
||||
{ 0x0054, "/", 0, 1, 1, 1 },
|
||||
{ 0x0055, "*", 0, 2, 1, 1 },
|
||||
{ 0x0056, "-", 0, 3, 1, 1 },
|
||||
{ 0x005F, "7", 1, 0, 1, 1 },
|
||||
{ 0x0060, "8", 1, 1, 1, 1 },
|
||||
{ 0x0061, "9", 1, 2, 1, 1 },
|
||||
{ 0x0057, "+", 1, 3, 2, 1 },
|
||||
{ 0x005C, "4", 2, 0, 1, 1 },
|
||||
{ 0x005D, "5", 2, 1, 1, 1 },
|
||||
{ 0x005E, "6", 2, 2, 1, 1 },
|
||||
{ 0x0059, "1", 3, 0, 1, 1 },
|
||||
{ 0x005A, "2", 3, 1, 1, 1 },
|
||||
{ 0x005B, "3", 3, 2, 1, 1 },
|
||||
{ 0x0058, "Enter", 3, 3, 2, 1 },
|
||||
{ 0x0062, "0", 4, 0, 1, 2 },
|
||||
{ 0x0063, ".", 4, 2, 1, 1 },
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
App_KeyboardPage::App_KeyboardPage(QWidget* p_Parent)
|
||||
: QWidget(p_Parent)
|
||||
{
|
||||
App_Func_CreateLayout();
|
||||
}
|
||||
|
||||
void App_KeyboardPage::App_Func_SetPressedUsages(const QVector<quint16>& UsageList)
|
||||
{
|
||||
for (auto It = appButtonMap.begin(); It != appButtonMap.end(); ++It)
|
||||
{
|
||||
It.value()->App_Func_SetPressedState(UsageList.contains(It.key()));
|
||||
}
|
||||
}
|
||||
|
||||
void App_KeyboardPage::App_Func_SetLatchedUsage(quint16 Usage, bool IsLatched)
|
||||
{
|
||||
App_KeyButton* const p_Button = appButtonMap.value(Usage, nullptr);
|
||||
if (p_Button != nullptr)
|
||||
{
|
||||
p_Button->App_Func_SetLatchedState(IsLatched);
|
||||
}
|
||||
}
|
||||
|
||||
void App_KeyboardPage::App_Func_SetFeatureLabel(quint16 Usage, const QString& Text)
|
||||
{
|
||||
App_KeyButton* const p_Button = appButtonMap.value(Usage, nullptr);
|
||||
if (p_Button != nullptr)
|
||||
{
|
||||
p_Button->App_Func_SetFeatureText(Text);
|
||||
}
|
||||
}
|
||||
|
||||
void App_KeyboardPage::App_Func_CreateLayout()
|
||||
{
|
||||
const App_ThemePalette Palette = App_Theme_DefaultPalette();
|
||||
|
||||
QVBoxLayout* const p_RootLayout = new QVBoxLayout(this);
|
||||
p_RootLayout->setContentsMargins(0, 0, 0, 0);
|
||||
p_RootLayout->setSpacing(12);
|
||||
|
||||
QFrame* const p_Card = new QFrame(this);
|
||||
p_Card->setStyleSheet(App_Theme_BuildCardStyleSheet());
|
||||
p_RootLayout->addWidget(p_Card);
|
||||
|
||||
QVBoxLayout* const p_CardLayout = new QVBoxLayout(p_Card);
|
||||
p_CardLayout->setContentsMargins(20, 20, 20, 20);
|
||||
p_CardLayout->setSpacing(14);
|
||||
|
||||
QLabel* const p_Title = new QLabel(QStringLiteral("Keyboard"), p_Card);
|
||||
p_Title->setProperty("role", QStringLiteral("title"));
|
||||
p_CardLayout->addWidget(p_Title);
|
||||
|
||||
QLabel* const p_Body = new QLabel(
|
||||
QStringLiteral("Start from one button, then grow into the whole keypad layout."),
|
||||
p_Card);
|
||||
p_Body->setProperty("role", QStringLiteral("body"));
|
||||
p_Body->setWordWrap(true);
|
||||
p_CardLayout->addWidget(p_Body);
|
||||
|
||||
QGridLayout* const p_GridLayout = new QGridLayout();
|
||||
p_GridLayout->setSpacing(12);
|
||||
p_CardLayout->addLayout(p_GridLayout);
|
||||
|
||||
for (const App_KeySpec& KeySpec : kKeySpecList)
|
||||
{
|
||||
App_KeyButton* const p_Button =
|
||||
new App_KeyButton(KeySpec.Usage, QString::fromUtf8(KeySpec.Text), p_Card);
|
||||
p_GridLayout->addWidget(
|
||||
p_Button,
|
||||
KeySpec.Row,
|
||||
KeySpec.Column,
|
||||
KeySpec.RowSpan,
|
||||
KeySpec.ColumnSpan);
|
||||
appButtonMap.insert(KeySpec.Usage, p_Button);
|
||||
}
|
||||
|
||||
for (int Column = 0; Column < 4; ++Column)
|
||||
{
|
||||
p_GridLayout->setColumnStretch(Column, 1);
|
||||
}
|
||||
|
||||
Q_UNUSED(Palette);
|
||||
}
|
||||
|
||||
} // namespace APP
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QHash>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
namespace APP
|
||||
{
|
||||
|
||||
class App_KeyButton;
|
||||
|
||||
class App_KeyboardPage : public QWidget
|
||||
{
|
||||
public:
|
||||
explicit App_KeyboardPage(QWidget* p_Parent = nullptr);
|
||||
|
||||
void App_Func_SetPressedUsages(const QVector<quint16>& UsageList);
|
||||
void App_Func_SetLatchedUsage(quint16 Usage, bool IsLatched);
|
||||
void App_Func_SetFeatureLabel(quint16 Usage, const QString& Text);
|
||||
|
||||
private:
|
||||
void App_Func_CreateLayout();
|
||||
|
||||
QHash<quint16, App_KeyButton*> appButtonMap;
|
||||
};
|
||||
|
||||
} // namespace APP
|
||||
@@ -1,71 +0,0 @@
|
||||
#include "APP/AppMainWindow.h"
|
||||
|
||||
#include "APP/AppKeyboardPage.h"
|
||||
#include "APP/AppSettingsPage.h"
|
||||
#include "APP/AppTheme.h"
|
||||
|
||||
#include <QtWidgets/QTabWidget>
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
namespace APP
|
||||
{
|
||||
|
||||
App_MainWindow::App_MainWindow(QWidget* p_Parent)
|
||||
: QWidget(p_Parent)
|
||||
{
|
||||
setWindowTitle(QStringLiteral("KeyBorad"));
|
||||
resize(860, 760);
|
||||
setStyleSheet(App_Theme_BuildWindowStyleSheet());
|
||||
|
||||
QVBoxLayout* const p_RootLayout = new QVBoxLayout(this);
|
||||
p_RootLayout->setContentsMargins(20, 20, 20, 20);
|
||||
p_RootLayout->setSpacing(12);
|
||||
|
||||
appTabWidget = new QTabWidget(this);
|
||||
appKeyboardPage = new App_KeyboardPage(appTabWidget);
|
||||
appSettingsPage = new App_SettingsPage(appTabWidget);
|
||||
|
||||
appTabWidget->addTab(appKeyboardPage, QStringLiteral("Keyboard"));
|
||||
appTabWidget->addTab(appSettingsPage, QStringLiteral("Settings"));
|
||||
|
||||
p_RootLayout->addWidget(appTabWidget);
|
||||
|
||||
appPollTimer = new QTimer(this);
|
||||
connect(appPollTimer, &QTimer::timeout, this, [this]()
|
||||
{
|
||||
if (Lgc_Core_Poll(&appLogic))
|
||||
{
|
||||
App_Func_RefreshFromLogic();
|
||||
}
|
||||
});
|
||||
|
||||
App_Func_StartLogic();
|
||||
}
|
||||
|
||||
void App_MainWindow::App_Func_StartLogic()
|
||||
{
|
||||
Lgc_Core_Init(&appLogic);
|
||||
Lgc_Core_Start(&appLogic);
|
||||
App_Func_RefreshFromLogic();
|
||||
appPollTimer->start(30);
|
||||
}
|
||||
|
||||
void App_MainWindow::App_Func_RefreshFromLogic()
|
||||
{
|
||||
const Lgc_State& State = Lgc_Core_GetState(&appLogic);
|
||||
appSettingsPage->App_Func_SetConnectionText(State.ConnectionText);
|
||||
appSettingsPage->App_Func_SetLastActionText(State.LastActionText);
|
||||
}
|
||||
|
||||
App_KeyboardPage* App_MainWindow::App_Func_GetKeyboardPage() const
|
||||
{
|
||||
return appKeyboardPage;
|
||||
}
|
||||
|
||||
App_SettingsPage* App_MainWindow::App_Func_GetSettingsPage() const
|
||||
{
|
||||
return appSettingsPage;
|
||||
}
|
||||
|
||||
} // namespace APP
|
||||
@@ -1,35 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "LOGIC/Lgc_Core.h"
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
class QTabWidget;
|
||||
class QTimer;
|
||||
|
||||
namespace APP
|
||||
{
|
||||
|
||||
class App_KeyboardPage;
|
||||
class App_SettingsPage;
|
||||
|
||||
class App_MainWindow : public QWidget
|
||||
{
|
||||
public:
|
||||
explicit App_MainWindow(QWidget* p_Parent = nullptr);
|
||||
|
||||
App_KeyboardPage* App_Func_GetKeyboardPage() const;
|
||||
App_SettingsPage* App_Func_GetSettingsPage() const;
|
||||
|
||||
private:
|
||||
void App_Func_StartLogic();
|
||||
void App_Func_RefreshFromLogic();
|
||||
|
||||
QTabWidget* appTabWidget = nullptr;
|
||||
App_KeyboardPage* appKeyboardPage = nullptr;
|
||||
App_SettingsPage* appSettingsPage = nullptr;
|
||||
QTimer* appPollTimer = nullptr;
|
||||
Lgc_Core appLogic;
|
||||
};
|
||||
|
||||
} // namespace APP
|
||||
@@ -1,61 +0,0 @@
|
||||
#include "APP/AppSettingsPage.h"
|
||||
|
||||
#include "APP/AppTheme.h"
|
||||
|
||||
#include <QtWidgets/QFrame>
|
||||
#include <QtWidgets/QFormLayout>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
|
||||
namespace APP
|
||||
{
|
||||
|
||||
App_SettingsPage::App_SettingsPage(QWidget* p_Parent)
|
||||
: QWidget(p_Parent)
|
||||
{
|
||||
QVBoxLayout* const p_RootLayout = new QVBoxLayout(this);
|
||||
p_RootLayout->setContentsMargins(0, 0, 0, 0);
|
||||
p_RootLayout->setSpacing(12);
|
||||
|
||||
QFrame* const p_Card = new QFrame(this);
|
||||
p_Card->setStyleSheet(App_Theme_BuildCardStyleSheet());
|
||||
p_RootLayout->addWidget(p_Card);
|
||||
|
||||
QVBoxLayout* const p_CardLayout = new QVBoxLayout(p_Card);
|
||||
p_CardLayout->setContentsMargins(20, 20, 20, 20);
|
||||
p_CardLayout->setSpacing(14);
|
||||
|
||||
QLabel* const p_Title = new QLabel(QStringLiteral("Settings"), p_Card);
|
||||
p_Title->setProperty("role", QStringLiteral("title"));
|
||||
p_CardLayout->addWidget(p_Title);
|
||||
|
||||
QLabel* const p_Body = new QLabel(
|
||||
QStringLiteral("Use this page to present transport status and the latest function result."),
|
||||
p_Card);
|
||||
p_Body->setProperty("role", QStringLiteral("body"));
|
||||
p_Body->setWordWrap(true);
|
||||
p_CardLayout->addWidget(p_Body);
|
||||
|
||||
QFormLayout* const p_FormLayout = new QFormLayout();
|
||||
p_FormLayout->setHorizontalSpacing(12);
|
||||
p_FormLayout->setVerticalSpacing(12);
|
||||
p_CardLayout->addLayout(p_FormLayout);
|
||||
|
||||
appConnectionLabel = new QLabel(QStringLiteral("Disconnected"), p_Card);
|
||||
appLastActionLabel = new QLabel(QStringLiteral("Idle"), p_Card);
|
||||
|
||||
p_FormLayout->addRow(QStringLiteral("Transport"), appConnectionLabel);
|
||||
p_FormLayout->addRow(QStringLiteral("Last Action"), appLastActionLabel);
|
||||
}
|
||||
|
||||
void App_SettingsPage::App_Func_SetConnectionText(const QString& Text)
|
||||
{
|
||||
appConnectionLabel->setText(Text.trimmed().isEmpty() ? QStringLiteral("Disconnected") : Text.trimmed());
|
||||
}
|
||||
|
||||
void App_SettingsPage::App_Func_SetLastActionText(const QString& Text)
|
||||
{
|
||||
appLastActionLabel->setText(Text.trimmed().isEmpty() ? QStringLiteral("Idle") : Text.trimmed());
|
||||
}
|
||||
|
||||
} // namespace APP
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
class QLabel;
|
||||
|
||||
namespace APP
|
||||
{
|
||||
|
||||
class App_SettingsPage : public QWidget
|
||||
{
|
||||
public:
|
||||
explicit App_SettingsPage(QWidget* p_Parent = nullptr);
|
||||
|
||||
void App_Func_SetConnectionText(const QString& Text);
|
||||
void App_Func_SetLastActionText(const QString& Text);
|
||||
|
||||
private:
|
||||
QLabel* appConnectionLabel = nullptr;
|
||||
QLabel* appLastActionLabel = nullptr;
|
||||
};
|
||||
|
||||
} // namespace APP
|
||||
@@ -1,86 +0,0 @@
|
||||
#include "APP/AppTheme.h"
|
||||
|
||||
namespace APP
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
QString App_Func_RgbText(const QColor& Color)
|
||||
{
|
||||
return QStringLiteral("rgb(%1, %2, %3)")
|
||||
.arg(Color.red())
|
||||
.arg(Color.green())
|
||||
.arg(Color.blue());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
App_ThemePalette App_Theme_DefaultPalette()
|
||||
{
|
||||
return App_ThemePalette();
|
||||
}
|
||||
|
||||
QString App_Theme_BuildWindowStyleSheet()
|
||||
{
|
||||
const App_ThemePalette Palette = App_Theme_DefaultPalette();
|
||||
|
||||
return QStringLiteral(
|
||||
"QWidget {"
|
||||
" background:%1;"
|
||||
" color:%2;"
|
||||
"}"
|
||||
"QTabWidget::pane {"
|
||||
" border:1px solid %3;"
|
||||
" border-radius:12px;"
|
||||
" background:%4;"
|
||||
"}"
|
||||
"QTabBar::tab {"
|
||||
" background:%4;"
|
||||
" color:%5;"
|
||||
" padding:10px 16px;"
|
||||
" margin-right:6px;"
|
||||
" border:1px solid %3;"
|
||||
" border-bottom:none;"
|
||||
" border-top-left-radius:10px;"
|
||||
" border-top-right-radius:10px;"
|
||||
"}"
|
||||
"QTabBar::tab:selected {"
|
||||
" color:%2;"
|
||||
" background:%1;"
|
||||
"}"
|
||||
)
|
||||
.arg(App_Func_RgbText(Palette.Window))
|
||||
.arg(App_Func_RgbText(Palette.TextPrimary))
|
||||
.arg(App_Func_RgbText(Palette.Border))
|
||||
.arg(App_Func_RgbText(Palette.Surface))
|
||||
.arg(App_Func_RgbText(Palette.TextMuted));
|
||||
}
|
||||
|
||||
QString App_Theme_BuildCardStyleSheet()
|
||||
{
|
||||
const App_ThemePalette Palette = App_Theme_DefaultPalette();
|
||||
|
||||
return QStringLiteral(
|
||||
"QFrame {"
|
||||
" background:%1;"
|
||||
" border:1px solid %2;"
|
||||
" border-radius:14px;"
|
||||
"}"
|
||||
"QLabel[role=\"title\"] {"
|
||||
" color:%3;"
|
||||
" font-size:20px;"
|
||||
" font-weight:600;"
|
||||
"}"
|
||||
"QLabel[role=\"body\"] {"
|
||||
" color:%4;"
|
||||
" font-size:13px;"
|
||||
"}"
|
||||
)
|
||||
.arg(App_Func_RgbText(Palette.Surface))
|
||||
.arg(App_Func_RgbText(Palette.Border))
|
||||
.arg(App_Func_RgbText(Palette.TextPrimary))
|
||||
.arg(App_Func_RgbText(Palette.TextMuted));
|
||||
}
|
||||
|
||||
} // namespace APP
|
||||
@@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtGui/QColor>
|
||||
|
||||
namespace APP
|
||||
{
|
||||
|
||||
struct App_ThemePalette
|
||||
{
|
||||
QColor Window = QColor(15, 23, 42);
|
||||
QColor Surface = QColor(17, 24, 39);
|
||||
QColor Border = QColor(51, 65, 85);
|
||||
QColor TextPrimary = QColor(226, 232, 240);
|
||||
QColor TextMuted = QColor(148, 163, 184);
|
||||
QColor Accent = QColor(76, 201, 240);
|
||||
QColor AccentSoft = QColor(34, 197, 94);
|
||||
};
|
||||
|
||||
App_ThemePalette App_Theme_DefaultPalette();
|
||||
QString App_Theme_BuildWindowStyleSheet();
|
||||
QString App_Theme_BuildCardStyleSheet();
|
||||
|
||||
} // namespace APP
|
||||
@@ -1,59 +0,0 @@
|
||||
#include "COM/Com_ProtoCodec.h"
|
||||
|
||||
#include "COM/Com_CdcDecode.h"
|
||||
#include "COM/Com_CdcEncode.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
quint16 Com_Func_ReadLe16(const QByteArray& ByteArray, int Offset)
|
||||
{
|
||||
return static_cast<quint16>(
|
||||
static_cast<quint8>(ByteArray.at(Offset)) |
|
||||
(static_cast<quint16>(static_cast<quint8>(ByteArray.at(Offset + 1))) << 8));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool Com_ProtoCodec_ParseFrame(const QByteArray& ByteArray, Packet* p_Packet)
|
||||
{
|
||||
return Com_Cdc_Func_ParseFrame(ByteArray, p_Packet);
|
||||
}
|
||||
|
||||
bool Com_ProtoCodec_TryTakeFrame(QByteArray* p_Buffer, Packet* p_Packet)
|
||||
{
|
||||
return Com_Cdc_Func_TryTakeFrame(p_Buffer, p_Packet);
|
||||
}
|
||||
|
||||
QByteArray Com_ProtoCodec_BuildHelloReq()
|
||||
{
|
||||
const Packet_HelloReq HelloReq;
|
||||
return Com_Cdc_Func_BuildHelloReq(HelloReq);
|
||||
}
|
||||
|
||||
bool Com_ProtoCodec_IsHelloRsp(const Packet& PacketData)
|
||||
{
|
||||
return (PacketData.type == Com_Type_HelloRsp) &&
|
||||
(PacketData.data.size() == Packet_len::Com_Len_HelloRsp);
|
||||
}
|
||||
|
||||
bool Com_ProtoCodec_ParseHelloRsp(
|
||||
const Packet& PacketData,
|
||||
Packet_HelloRsp* p_HelloRsp)
|
||||
{
|
||||
if ((p_HelloRsp == nullptr) || !Com_ProtoCodec_IsHelloRsp(PacketData))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Packet_HelloRsp HelloRsp;
|
||||
HelloRsp.ProtocolVersion = static_cast<quint8>(PacketData.data.at(0));
|
||||
HelloRsp.VendorId = Com_Func_ReadLe16(PacketData.data, 1);
|
||||
HelloRsp.ProductId = Com_Func_ReadLe16(PacketData.data, 3);
|
||||
HelloRsp.FirmwareMajor = static_cast<quint8>(PacketData.data.at(5));
|
||||
HelloRsp.FirmwareMinor = static_cast<quint8>(PacketData.data.at(6));
|
||||
HelloRsp.CapabilityFlags = Com_Func_ReadLe16(PacketData.data, 7);
|
||||
|
||||
*p_HelloRsp = HelloRsp;
|
||||
return true;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
|
||||
#include "COM/Com_Cdc.h"
|
||||
|
||||
bool Com_ProtoCodec_ParseFrame(const QByteArray& ByteArray, Packet* p_Packet);
|
||||
bool Com_ProtoCodec_TryTakeFrame(QByteArray* p_Buffer, Packet* p_Packet);
|
||||
|
||||
QByteArray Com_ProtoCodec_BuildHelloReq();
|
||||
bool Com_ProtoCodec_IsHelloRsp(const Packet& PacketData);
|
||||
bool Com_ProtoCodec_ParseHelloRsp(
|
||||
const Packet& PacketData,
|
||||
Packet_HelloRsp* p_HelloRsp);
|
||||
@@ -37,12 +37,12 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'" Label="QtSettings">
|
||||
<QtInstall>D:\App\Qt\5.13.1\msvc2015_64</QtInstall>
|
||||
<QtModules>core;serialport;widgets</QtModules>
|
||||
<QtModules>core;serialport</QtModules>
|
||||
<QtBuildConfig>debug</QtBuildConfig>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'" Label="QtSettings">
|
||||
<QtInstall>D:\App\Qt\5.13.1\msvc2015_64</QtInstall>
|
||||
<QtModules>core;serialport;widgets</QtModules>
|
||||
<QtModules>core;serialport</QtModules>
|
||||
<QtBuildConfig>release</QtBuildConfig>
|
||||
</PropertyGroup>
|
||||
<Target Name="QtMsBuildNotFound" BeforeTargets="CustomBuild;ClCompile" Condition="!Exists('$(QtMsBuild)\qt.targets') or !Exists('$(QtMsBuild)\qt.props')">
|
||||
@@ -94,18 +94,7 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="APP\AppKeyButton.cpp" />
|
||||
<ClInclude Include="APP\AppKeyButton.h" />
|
||||
<ClCompile Include="APP\AppKeyboardPage.cpp" />
|
||||
<ClInclude Include="APP\AppKeyboardPage.h" />
|
||||
<ClCompile Include="APP\AppMainWindow.cpp" />
|
||||
<ClInclude Include="APP\AppMainWindow.h" />
|
||||
<ClCompile Include="APP\AppSettingsPage.cpp" />
|
||||
<ClInclude Include="APP\AppSettingsPage.h" />
|
||||
<ClInclude Include="APP\AppTheme.h" />
|
||||
<ClInclude Include="COM\Com_Cdc.h" />
|
||||
<ClCompile Include="COM\Com_ProtoCodec.cpp" />
|
||||
<ClInclude Include="COM\Com_ProtoCodec.h" />
|
||||
<ClCompile Include="COM\Com_CdcEncode.cpp" />
|
||||
<ClInclude Include="COM\Com_CdcEncode.h" />
|
||||
<ClCompile Include="COM\Com_CdcDecode.cpp" />
|
||||
@@ -113,14 +102,6 @@
|
||||
<ClCompile Include="DRI\Dri_Cdc.cpp" />
|
||||
<ClCompile Include="DRI\GATT\Dri_Gatt.cpp" />
|
||||
<ClInclude Include="DRI\GATT\Dri_Gatt.h" />
|
||||
<ClCompile Include="APP\AppTheme.cpp" />
|
||||
<ClCompile Include="LOGIC\Lgc_Core.cpp" />
|
||||
<ClInclude Include="LOGIC\Lgc_Core.h" />
|
||||
<ClCompile Include="LOGIC\Lgc_FunctionExecutor.cpp" />
|
||||
<ClInclude Include="LOGIC\Lgc_FunctionExecutor.h" />
|
||||
<ClCompile Include="LOGIC\Lgc_Session.cpp" />
|
||||
<ClInclude Include="LOGIC\Lgc_Session.h" />
|
||||
<ClInclude Include="LOGIC\Lgc_State.h" />
|
||||
<ClCompile Include="main.cpp" />
|
||||
<ClInclude Include="DRI\Dri_Cdc.h" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -23,42 +23,9 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="APP\AppKeyButton.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="APP\AppKeyButton.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="APP\AppKeyboardPage.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="APP\AppKeyboardPage.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="APP\AppMainWindow.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="APP\AppMainWindow.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="APP\AppSettingsPage.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="APP\AppSettingsPage.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="APP\AppTheme.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="COM\Com_Cdc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="COM\Com_ProtoCodec.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="COM\Com_ProtoCodec.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="COM\Com_CdcEncode.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
@@ -80,30 +47,6 @@
|
||||
<ClInclude Include="DRI\GATT\Dri_Gatt.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="APP\AppTheme.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LOGIC\Lgc_Core.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="LOGIC\Lgc_Core.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="LOGIC\Lgc_FunctionExecutor.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="LOGIC\Lgc_FunctionExecutor.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="LOGIC\Lgc_Session.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClInclude Include="LOGIC\Lgc_Session.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LOGIC\Lgc_State.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClCompile Include="main.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
#include "LOGIC/Lgc_Core.h"
|
||||
|
||||
#include "COM/Com_ProtoCodec.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void Lgc_Func_ApplyHelloRsp(
|
||||
Lgc_Core* p_Core,
|
||||
const Packet_HelloRsp& HelloRsp)
|
||||
{
|
||||
p_Core->State.IsConnected = true;
|
||||
p_Core->State.IsHandshakeDone = true;
|
||||
p_Core->State.ProtocolVersion = HelloRsp.ProtocolVersion;
|
||||
p_Core->State.VendorId = HelloRsp.VendorId;
|
||||
p_Core->State.ProductId = HelloRsp.ProductId;
|
||||
p_Core->State.FirmwareMajor = HelloRsp.FirmwareMajor;
|
||||
p_Core->State.FirmwareMinor = HelloRsp.FirmwareMinor;
|
||||
p_Core->State.CapabilityFlags = HelloRsp.CapabilityFlags;
|
||||
p_Core->State.ActiveTransport = Lgc_TransportType::Cdc;
|
||||
p_Core->State.ActiveEndpointName = p_Core->Session.CdcPort.PortName;
|
||||
p_Core->State.ConnectionText = QStringLiteral("CDC connected: %1")
|
||||
.arg(p_Core->Session.CdcPort.PortName);
|
||||
p_Core->State.LastActionText = QStringLiteral("Handshake completed.");
|
||||
}
|
||||
|
||||
void Lgc_Func_UpdateActionText(Lgc_Core* p_Core, const Packet& PacketData)
|
||||
{
|
||||
switch (PacketData.type)
|
||||
{
|
||||
case Com_Type_HelloRsp:
|
||||
p_Core->State.LastActionText = QStringLiteral("Received HelloRsp.");
|
||||
break;
|
||||
case Com_Type_Bitmap:
|
||||
p_Core->State.LastActionText = QStringLiteral("Received Bitmap.");
|
||||
break;
|
||||
case Com_Type_FunctionKeyEvent:
|
||||
p_Core->State.LastActionText = QStringLiteral("Received FunctionKeyEvent.");
|
||||
break;
|
||||
case Com_Type_LedState:
|
||||
p_Core->State.LastActionText = QStringLiteral("Received LedState.");
|
||||
break;
|
||||
case Com_Type_TimeSync:
|
||||
p_Core->State.LastActionText = QStringLiteral("Received TimeSync.");
|
||||
break;
|
||||
case Com_Type_ThemeRgb:
|
||||
p_Core->State.LastActionText = QStringLiteral("Received ThemeRgb.");
|
||||
break;
|
||||
case Com_Type_Ack:
|
||||
p_Core->State.LastActionText = QStringLiteral("Received Ack.");
|
||||
break;
|
||||
case Com_Type_Error:
|
||||
p_Core->State.LastActionText = QStringLiteral("Received Error.");
|
||||
break;
|
||||
default:
|
||||
p_Core->State.LastActionText = QStringLiteral("Received packet type 0x%1.")
|
||||
.arg(static_cast<quint8>(PacketData.type), 2, 16, QLatin1Char('0'))
|
||||
.toUpper();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Lgc_Core_Init(Lgc_Core* p_Core)
|
||||
{
|
||||
if (p_Core == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
p_Core->State = Lgc_State();
|
||||
Lgc_Session_Init(&p_Core->Session);
|
||||
}
|
||||
|
||||
bool Lgc_Core_Start(Lgc_Core* p_Core)
|
||||
{
|
||||
if (p_Core == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Dri_Cdc_Struct_OpenConfig Config;
|
||||
Packet_HelloRsp HelloRsp;
|
||||
if (Lgc_Session_TryStartCdc(&p_Core->Session, Config, &HelloRsp))
|
||||
{
|
||||
Lgc_Func_ApplyHelloRsp(p_Core, HelloRsp);
|
||||
return true;
|
||||
}
|
||||
|
||||
p_Core->State.IsConnected = false;
|
||||
p_Core->State.IsHandshakeDone = false;
|
||||
p_Core->State.ConnectionText = QStringLiteral("No device found.");
|
||||
p_Core->State.LastActionText = QStringLiteral("Handshake failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Lgc_Core_Poll(Lgc_Core* p_Core)
|
||||
{
|
||||
if (p_Core == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Packet PacketData;
|
||||
if (!Lgc_Session_ReadNextPacket(&p_Core->Session, &PacketData))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Lgc_Func_UpdateActionText(p_Core, PacketData);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Lgc_Core_Close(Lgc_Core* p_Core)
|
||||
{
|
||||
if (p_Core == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Lgc_Session_Close(&p_Core->Session);
|
||||
p_Core->State = Lgc_State();
|
||||
}
|
||||
|
||||
const Lgc_State& Lgc_Core_GetState(const Lgc_Core* p_Core)
|
||||
{
|
||||
return p_Core->State;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "LOGIC/Lgc_Session.h"
|
||||
#include "LOGIC/Lgc_State.h"
|
||||
|
||||
struct Lgc_Core
|
||||
{
|
||||
Lgc_State State;
|
||||
Lgc_Session Session;
|
||||
};
|
||||
|
||||
void Lgc_Core_Init(Lgc_Core* p_Core);
|
||||
bool Lgc_Core_Start(Lgc_Core* p_Core);
|
||||
bool Lgc_Core_Poll(Lgc_Core* p_Core);
|
||||
void Lgc_Core_Close(Lgc_Core* p_Core);
|
||||
const Lgc_State& Lgc_Core_GetState(const Lgc_Core* p_Core);
|
||||
@@ -1,68 +0,0 @@
|
||||
#include "LOGIC/Lgc_FunctionExecutor.h"
|
||||
|
||||
#include <QtCore/QUrl>
|
||||
#include <QtGui/QDesktopServices>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
QString Lgc_Func_GetFunctionName(const Lgc_FunctionDefinition& Function)
|
||||
{
|
||||
return Function.Name.trimmed().isEmpty()
|
||||
? QStringLiteral("Unnamed Function")
|
||||
: Function.Name.trimmed();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool Lgc_FunctionExecutor_Run(
|
||||
const Lgc_FunctionDefinition& Function,
|
||||
QString* p_TextStatus)
|
||||
{
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
p_TextStatus->clear();
|
||||
}
|
||||
|
||||
switch (Function.Type)
|
||||
{
|
||||
case Lgc_FunctionType::None:
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("%1 has no executable action.")
|
||||
.arg(Lgc_Func_GetFunctionName(Function));
|
||||
}
|
||||
return false;
|
||||
|
||||
case Lgc_FunctionType::Shortcut:
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("Shortcut execution will be connected after transport is ready.");
|
||||
}
|
||||
return false;
|
||||
|
||||
case Lgc_FunctionType::ShortcutSequence:
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = QStringLiteral("Shortcut sequence execution will be connected after transport is ready.");
|
||||
}
|
||||
return false;
|
||||
|
||||
case Lgc_FunctionType::Website:
|
||||
{
|
||||
const QUrl Url = QUrl::fromUserInput(Function.WebsiteUrl.trimmed());
|
||||
const bool IsOpened = Url.isValid() && !Url.isEmpty() && QDesktopServices::openUrl(Url);
|
||||
|
||||
if (p_TextStatus != nullptr)
|
||||
{
|
||||
*p_TextStatus = IsOpened
|
||||
? QStringLiteral("Opened website: %1").arg(Url.toString())
|
||||
: QStringLiteral("Failed to open website for %1.").arg(Lgc_Func_GetFunctionName(Function));
|
||||
}
|
||||
|
||||
return IsOpened;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
enum class Lgc_FunctionType : quint8
|
||||
{
|
||||
None = 0,
|
||||
Shortcut,
|
||||
ShortcutSequence,
|
||||
Website,
|
||||
};
|
||||
|
||||
struct Lgc_FunctionDefinition
|
||||
{
|
||||
int Id = 0;
|
||||
QString Name;
|
||||
QString Description;
|
||||
Lgc_FunctionType Type = Lgc_FunctionType::None;
|
||||
QStringList ShortcutTokens;
|
||||
QString WebsiteUrl;
|
||||
};
|
||||
|
||||
bool Lgc_FunctionExecutor_Run(
|
||||
const Lgc_FunctionDefinition& Function,
|
||||
QString* p_TextStatus);
|
||||
@@ -1,152 +0,0 @@
|
||||
#include "LOGIC/Lgc_Session.h"
|
||||
|
||||
#include "COM/Com_ProtoCodec.h"
|
||||
|
||||
#include <QtCore/QElapsedTimer>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
bool Lgc_Func_TryHandshakeCdcPort(
|
||||
Dri_Cdc_Struct_Port* p_Port,
|
||||
QByteArray* p_ReadBuffer,
|
||||
Packet_HelloRsp* p_HelloRsp)
|
||||
{
|
||||
const QByteArray HelloReqFrame = Com_ProtoCodec_BuildHelloReq();
|
||||
if (!Dri_Cdc_WriteBytes(p_Port, HelloReqFrame, 200))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QElapsedTimer Timer;
|
||||
Timer.start();
|
||||
while (Timer.elapsed() < 200)
|
||||
{
|
||||
QByteArray ReadBytes;
|
||||
if (Dri_Cdc_ReadBytes(p_Port, &ReadBytes, 20) && !ReadBytes.isEmpty())
|
||||
{
|
||||
p_ReadBuffer->append(ReadBytes);
|
||||
}
|
||||
|
||||
Packet PacketData;
|
||||
while (Com_ProtoCodec_TryTakeFrame(p_ReadBuffer, &PacketData))
|
||||
{
|
||||
if (!Com_ProtoCodec_ParseHelloRsp(PacketData, p_HelloRsp))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Lgc_Session_Init(Lgc_Session* p_Session)
|
||||
{
|
||||
if (p_Session == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
*p_Session = Lgc_Session();
|
||||
}
|
||||
|
||||
void Lgc_Session_Close(Lgc_Session* p_Session)
|
||||
{
|
||||
if (p_Session == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Dri_Cdc_Close(&p_Session->CdcPort);
|
||||
Dri_Gatt_Deinit(&p_Session->GattPort);
|
||||
p_Session->CdcReadBuffer.clear();
|
||||
p_Session->IsStarted = false;
|
||||
p_Session->IsHandshakeDone = false;
|
||||
p_Session->ActiveTransport = Lgc_TransportType::None;
|
||||
}
|
||||
|
||||
bool Lgc_Session_TryStartCdc(
|
||||
Lgc_Session* p_Session,
|
||||
const Dri_Cdc_Struct_OpenConfig& Config,
|
||||
Packet_HelloRsp* p_HelloRsp)
|
||||
{
|
||||
if ((p_Session == nullptr) || (p_HelloRsp == nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const QVector<Dri_Cdc_Struct_PortInfo> PortList = Dri_Cdc_Enum();
|
||||
for (const Dri_Cdc_Struct_PortInfo& PortInfo : PortList)
|
||||
{
|
||||
Dri_Cdc_Struct_Port Port;
|
||||
if (!Dri_Cdc_Open(&Port, PortInfo.PortName, Config))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QByteArray ReadBuffer;
|
||||
Packet_HelloRsp HelloRsp;
|
||||
if (Lgc_Func_TryHandshakeCdcPort(&Port, &ReadBuffer, &HelloRsp))
|
||||
{
|
||||
Dri_Cdc_Close(&p_Session->CdcPort);
|
||||
p_Session->CdcPort = Port;
|
||||
p_Session->CdcReadBuffer = ReadBuffer;
|
||||
p_Session->IsStarted = true;
|
||||
p_Session->IsHandshakeDone = true;
|
||||
p_Session->ActiveTransport = Lgc_TransportType::Cdc;
|
||||
*p_HelloRsp = HelloRsp;
|
||||
return true;
|
||||
}
|
||||
|
||||
Dri_Cdc_Close(&Port);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Lgc_Session_TryStartGatt(Lgc_Session* p_Session)
|
||||
{
|
||||
if (p_Session == nullptr)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Dri_Gatt_Init(&p_Session->GattPort))
|
||||
{
|
||||
p_Session->IsStarted = true;
|
||||
p_Session->ActiveTransport = Lgc_TransportType::Gatt;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Lgc_Session_ReadNextPacket(
|
||||
Lgc_Session* p_Session,
|
||||
Packet* p_Packet)
|
||||
{
|
||||
if ((p_Session == nullptr) || (p_Packet == nullptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
*p_Packet = Packet();
|
||||
|
||||
if (p_Session->ActiveTransport == Lgc_TransportType::Cdc)
|
||||
{
|
||||
QByteArray ReadBytes;
|
||||
if (Dri_Cdc_ReadBytes(&p_Session->CdcPort, &ReadBytes, 0) && !ReadBytes.isEmpty())
|
||||
{
|
||||
p_Session->CdcReadBuffer.append(ReadBytes);
|
||||
}
|
||||
|
||||
return Com_ProtoCodec_TryTakeFrame(&p_Session->CdcReadBuffer, p_Packet);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "COM/Com_Cdc.h"
|
||||
#include "DRI/Dri_Cdc.h"
|
||||
#include "DRI/GATT/Dri_Gatt.h"
|
||||
#include "LOGIC/Lgc_State.h"
|
||||
|
||||
struct Lgc_Session
|
||||
{
|
||||
Dri_Cdc_Struct_Port CdcPort;
|
||||
Dri_Gatt_Struct_Port GattPort;
|
||||
QByteArray CdcReadBuffer;
|
||||
bool IsStarted = false;
|
||||
bool IsHandshakeDone = false;
|
||||
Lgc_TransportType ActiveTransport = Lgc_TransportType::None;
|
||||
};
|
||||
|
||||
void Lgc_Session_Init(Lgc_Session* p_Session);
|
||||
void Lgc_Session_Close(Lgc_Session* p_Session);
|
||||
bool Lgc_Session_TryStartCdc(
|
||||
Lgc_Session* p_Session,
|
||||
const Dri_Cdc_Struct_OpenConfig& Config,
|
||||
Packet_HelloRsp* p_HelloRsp);
|
||||
bool Lgc_Session_TryStartGatt(Lgc_Session* p_Session);
|
||||
bool Lgc_Session_ReadNextPacket(
|
||||
Lgc_Session* p_Session,
|
||||
Packet* p_Packet);
|
||||
@@ -1,27 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QtGlobal>
|
||||
|
||||
enum class Lgc_TransportType : quint8
|
||||
{
|
||||
None = 0,
|
||||
Cdc,
|
||||
Gatt,
|
||||
};
|
||||
|
||||
struct Lgc_State
|
||||
{
|
||||
bool IsConnected = false;
|
||||
bool IsHandshakeDone = false;
|
||||
Lgc_TransportType ActiveTransport = Lgc_TransportType::None;
|
||||
QString ActiveEndpointName;
|
||||
QString ConnectionText = QStringLiteral("Disconnected");
|
||||
QString LastActionText = QStringLiteral("Idle");
|
||||
quint32 ProtocolVersion = 0;
|
||||
quint32 CapabilityFlags = 0;
|
||||
quint16 VendorId = 0;
|
||||
quint16 ProductId = 0;
|
||||
quint8 FirmwareMajor = 0;
|
||||
quint8 FirmwareMinor = 0;
|
||||
};
|
||||
@@ -1,13 +1,14 @@
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include "APP/AppMainWindow.h"
|
||||
#include "DRI/Dri_Cdc.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication App(argc, argv);
|
||||
QCoreApplication App(argc, argv);
|
||||
|
||||
APP::App_MainWindow Window;
|
||||
Window.show();
|
||||
const QVector<Dri_Cdc_Struct_PortInfo> PortList = Dri_Cdc_Enum();
|
||||
qDebug() << "CDC ports:" << PortList.size();
|
||||
|
||||
return App.exec();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
# Generated Code
|
||||
|
||||
This directory is reserved for generated protocol code.
|
||||
|
||||
Planned layout:
|
||||
|
||||
- `cpp/` for host-side protobuf generated files
|
||||
- `nanopb/` for firmware-side generated files
|
||||
|
||||
Do not place hand-written logic here.
|
||||
@@ -1,97 +0,0 @@
|
||||
# Host APP Rebuild
|
||||
|
||||
## Goal
|
||||
|
||||
Keep the APP layer suitable for teaching from simple to complex.
|
||||
|
||||
Teaching order:
|
||||
|
||||
1. one button
|
||||
2. one keyboard page
|
||||
3. two pages
|
||||
4. one main window
|
||||
5. one shared theme
|
||||
|
||||
## Completed Nodes
|
||||
|
||||
### Node 1: theme helpers
|
||||
|
||||
Files:
|
||||
|
||||
- `KeyBorad/KeyBorad/APP/AppTheme.h`
|
||||
- `KeyBorad/KeyBorad/APP/AppTheme.cpp`
|
||||
|
||||
Design notes:
|
||||
|
||||
- centralize colors and style strings
|
||||
- keep styling readable
|
||||
- avoid mixing style text inside every widget
|
||||
|
||||
### Node 2: key button
|
||||
|
||||
Files:
|
||||
|
||||
- `KeyBorad/KeyBorad/APP/AppKeyButton.h`
|
||||
- `KeyBorad/KeyBorad/APP/AppKeyButton.cpp`
|
||||
|
||||
Design notes:
|
||||
|
||||
- teach one custom button first
|
||||
- keep state changes explicit
|
||||
- let one widget own its own text and style refresh
|
||||
|
||||
### Node 3: keyboard page
|
||||
|
||||
Files:
|
||||
|
||||
- `KeyBorad/KeyBorad/APP/AppKeyboardPage.h`
|
||||
- `KeyBorad/KeyBorad/APP/AppKeyboardPage.cpp`
|
||||
|
||||
Design notes:
|
||||
|
||||
- grow from one button to a full keypad
|
||||
- keep layout data local and explicit
|
||||
|
||||
### Node 4: settings page
|
||||
|
||||
Files:
|
||||
|
||||
- `KeyBorad/KeyBorad/APP/AppSettingsPage.h`
|
||||
- `KeyBorad/KeyBorad/APP/AppSettingsPage.cpp`
|
||||
|
||||
Design notes:
|
||||
|
||||
- use a second page early
|
||||
- give transport status and action feedback one simple home
|
||||
|
||||
### Node 5: main window integration
|
||||
|
||||
Files updated in this step:
|
||||
|
||||
- `KeyBorad/KeyBorad/APP/AppMainWindow.h`
|
||||
- `KeyBorad/KeyBorad/APP/AppMainWindow.cpp`
|
||||
- `KeyBorad/KeyBorad/main.cpp`
|
||||
|
||||
Implemented behavior:
|
||||
|
||||
- create the two-page window
|
||||
- own one `Lgc_Core`
|
||||
- start handshake on launch
|
||||
- poll the logic layer with a timer
|
||||
- refresh settings page texts from logic state
|
||||
|
||||
### Node 6: Qt property typing fix
|
||||
|
||||
Files updated in this step:
|
||||
|
||||
- `KeyBorad/KeyBorad/APP/AppKeyboardPage.cpp`
|
||||
- `KeyBorad/KeyBorad/APP/AppSettingsPage.cpp`
|
||||
|
||||
Design notes:
|
||||
|
||||
- keep widget property values explicit under MSVC + Qt
|
||||
- avoid relying on implicit conversion from string literal to `QVariant`
|
||||
|
||||
Implemented behavior:
|
||||
|
||||
- replace raw `"title"` / `"body"` property values with `QStringLiteral(...)`
|
||||
@@ -1,58 +0,0 @@
|
||||
# Host COM Rebuild
|
||||
|
||||
## Goal
|
||||
|
||||
Keep the protocol layer small and explicit.
|
||||
|
||||
The COM layer should:
|
||||
|
||||
- define packet-facing helpers
|
||||
- own frame parsing and packet building
|
||||
- avoid transport concerns
|
||||
- avoid UI and session concerns
|
||||
|
||||
## Completed Nodes
|
||||
|
||||
### Node 1: legacy protocol baseline
|
||||
|
||||
Files already present before this step:
|
||||
|
||||
- `KeyBorad/KeyBorad/COM/Com_Cdc.h`
|
||||
- `KeyBorad/KeyBorad/COM/Com_CdcEncode.h`
|
||||
- `KeyBorad/KeyBorad/COM/Com_CdcEncode.cpp`
|
||||
- `KeyBorad/KeyBorad/COM/Com_CdcDecode.h`
|
||||
- `KeyBorad/KeyBorad/COM/Com_CdcDecode.cpp`
|
||||
|
||||
Design notes:
|
||||
|
||||
- these files preserve the old packet format
|
||||
- they already encode and decode complete CDC frames
|
||||
- they also contain per-packet payload helpers
|
||||
|
||||
### Node 2: unified protocol entry
|
||||
|
||||
Files added in this step:
|
||||
|
||||
- `KeyBorad/KeyBorad/COM/Com_ProtoCodec.h`
|
||||
- `KeyBorad/KeyBorad/COM/Com_ProtoCodec.cpp`
|
||||
|
||||
Design notes:
|
||||
|
||||
- provides a thin and readable entry point for higher layers
|
||||
- keeps `DRI` from depending on packet parsing
|
||||
- keeps `LGC` from depending on low-level byte layout details
|
||||
- starts from the smallest useful handshake path
|
||||
|
||||
Implemented behavior:
|
||||
|
||||
- build `HelloReq` frame
|
||||
- validate whether a parsed packet is `HelloRsp`
|
||||
- decode `HelloRsp`
|
||||
- forward frame parsing and stream extraction to the existing low-level codec
|
||||
|
||||
## Next COM nodes
|
||||
|
||||
- bitmap encode/decode helper
|
||||
- ack/error helper
|
||||
- time sync and theme helper
|
||||
- replace direct `Com_Cdc*` calls in higher layers with `Com_ProtoCodec*`
|
||||
@@ -1,77 +0,0 @@
|
||||
# Host LGC Rebuild
|
||||
|
||||
## Goal
|
||||
|
||||
Keep the logic layer small, readable, and teachable.
|
||||
|
||||
The logic layer should:
|
||||
|
||||
- own connection state
|
||||
- own handshake state
|
||||
- call DRI for bytes
|
||||
- call COM for frame and packet parsing
|
||||
- expose a small interface to APP
|
||||
|
||||
The logic layer should not:
|
||||
|
||||
- parse serial bytes by itself
|
||||
- enumerate devices directly
|
||||
- own widget code
|
||||
|
||||
## Completed Nodes
|
||||
|
||||
### Node 1: function executor shell
|
||||
|
||||
Files:
|
||||
|
||||
- `KeyBorad/KeyBorad/LOGIC/Lgc_FunctionExecutor.h`
|
||||
- `KeyBorad/KeyBorad/LOGIC/Lgc_FunctionExecutor.cpp`
|
||||
|
||||
Design notes:
|
||||
|
||||
- keep function execution out of session code
|
||||
- reserve one place for OS-specific actions
|
||||
- keep the initial implementation small
|
||||
|
||||
### Node 2: state model
|
||||
|
||||
Files updated in this step:
|
||||
|
||||
- `KeyBorad/KeyBorad/LOGIC/Lgc_State.h`
|
||||
|
||||
Design notes:
|
||||
|
||||
- state is plain data
|
||||
- connection text and last action text live here
|
||||
- handshake result fields live here
|
||||
|
||||
### Node 3: session handshake path
|
||||
|
||||
Files completed in this step:
|
||||
|
||||
- `KeyBorad/KeyBorad/LOGIC/Lgc_Session.h`
|
||||
- `KeyBorad/KeyBorad/LOGIC/Lgc_Session.cpp`
|
||||
|
||||
Implemented behavior:
|
||||
|
||||
- try CDC handshake
|
||||
- send `HelloReq`
|
||||
- wait for `HelloRsp`
|
||||
- store the active transport
|
||||
- keep a stream buffer for CDC bytes
|
||||
- return the next parsed packet to upper layers
|
||||
|
||||
### Node 4: core facade
|
||||
|
||||
Files completed in this step:
|
||||
|
||||
- `KeyBorad/KeyBorad/LOGIC/Lgc_Core.h`
|
||||
- `KeyBorad/KeyBorad/LOGIC/Lgc_Core.cpp`
|
||||
|
||||
Implemented behavior:
|
||||
|
||||
- give APP one small entry point
|
||||
- start CDC handshake through session
|
||||
- expose `Start / Poll / Close / GetState`
|
||||
- refresh state from `HelloRsp`
|
||||
- update a simple action text when packets arrive
|
||||
Reference in New Issue
Block a user