18 Commits

Author SHA1 Message Date
c2a3e8417a easier linter 2024-08-29 14:35:33 +02:00
92098b6ba1 linter
add main to exclude
2023-12-23 23:43:43 +01:00
9e7668727e build env 2023-12-23 23:39:13 +01:00
30cda25039 build scripts 2023-12-23 23:38:43 +01:00
f65f70d5c3 linter 2023-12-23 22:49:28 +01:00
e5273c7012 clangformat everything 2023-12-23 21:37:08 +01:00
e19e7c9253 website backend
fix warning
2023-12-23 16:25:16 +01:00
50fe918561 tests
fix tftp tests
2023-12-23 16:17:36 +01:00
9d18c40a43 tests
Change sources and include to cmake path instead of relative path
2023-12-23 16:17:21 +01:00
Roelandts_Gert
fc87693d64 Merge pull request #35 from Sani7/website_02
Website 02
2023-12-11 14:57:16 +01:00
TeunBugwood
5279b14975 img 0 0 2023-12-11 14:45:27 +01:00
TeunBugwood
af0c6ad421 data file 2023-12-11 14:43:09 +01:00
TeunBugwood
ebd0479cd9 img 2023-12-11 14:40:50 +01:00
TeunBugwood
d1991d9abc updated tabs etc 2023-12-11 14:03:42 +01:00
TeunBugwood
5b0666920c Update main.c 2023-12-11 14:01:24 +01:00
TeunBugwood
cd2839e6ca Update website_backend.c 2023-12-11 13:34:47 +01:00
TeunBugwood
dd176256bb WBE update
Fixed some things that made the site not work. This is not the final version, just for the demo.
2023-12-11 13:31:46 +01:00
TeunBugwood
ec09cb9625 New website branch
previous was doomed, that is why I made a new brench that was updated with the main.
2023-12-11 13:20:19 +01:00
46 changed files with 252323 additions and 46939 deletions

11
.lint/exclude Normal file
View File

@@ -0,0 +1,11 @@
project/Core/Inc/main.h
project/Core/Inc/stm32f7xx_hal_conf.h
project/Core/Inc/stm32f7xx_it.h
project/Core/Inc/fsdata_custom.c
project/Core/Src/main.c
project/Core/Src/stm32f7xx_hal_msp.c
project/Core/Src/syscalls.c
project/Core/Src/sysmem.c
project/Core/Src/system_stm32f7xx.c
project/Core/Src/stm32f7xx_it.c
mkllfs/build/CMakeFiles/3.27.7/CompilerIdC/CMakeCCompilerId.c

4
.lint/search Normal file
View File

@@ -0,0 +1,4 @@
project/Core/
mkllfs
tests/
Applications/Qt-application_for_UDP_broadcast/

View File

@@ -1,15 +1,11 @@
#include "about.h" #include "about.h"
#include "ui_about.h" #include "ui_about.h"
About::About(QWidget *parent) : About::About(QWidget* parent) : QDialog(parent), ui(new Ui::About) {
QDialog(parent),
ui(new Ui::About)
{
ui->setupUi(this); ui->setupUi(this);
ui->lblVersion->setText(ui->lblVersion->text() + " " + __DATE__ + " " + __TIME__); ui->lblVersion->setText(ui->lblVersion->text() + " " + __DATE__ + " " + __TIME__);
} }
About::~About() About::~About() {
{
delete ui; delete ui;
} }

View File

@@ -7,8 +7,7 @@ namespace Ui {
class About; class About;
} }
class About : public QDialog class About : public QDialog {
{
Q_OBJECT Q_OBJECT
public: public:

View File

@@ -2,8 +2,7 @@
#include <QApplication> #include <QApplication>
int main(int argc, char *argv[]) int main(int argc, char* argv[]) {
{
QApplication a(argc, argv); QApplication a(argc, argv);
MainWindow w; MainWindow w;
w.show(); w.show();

View File

@@ -1,17 +1,13 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QUdpSocket" #include "QUdpSocket"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this); ui->setupUi(this);
m_udpSocket = new QUdpSocket(this); m_udpSocket = new QUdpSocket(this);
m_udpSocket->bind(QHostAddress::Any, UDP_PORT, QUdpSocket::ShareAddress); m_udpSocket->bind(QHostAddress::Any, UDP_PORT, QUdpSocket::ShareAddress);
connect(m_udpSocket, &QUdpSocket::readyRead, connect(m_udpSocket, &QUdpSocket::readyRead, this, &MainWindow::processPendingDatagrams);
this, &MainWindow::processPendingDatagrams);
// Timer just to ask twice (udp) // Timer just to ask twice (udp)
m_timer = new QTimer(this); m_timer = new QTimer(this);
@@ -32,29 +28,25 @@ MainWindow::MainWindow(QWidget *parent)
} }
// //Example items for screenshot: // //Example items for screenshot:
// QListWidgetItem * item = new QListWidgetItem(QIcon(":/res/stm32.png"), "00:80:E1:05:44:21 @ 192.168.0.11 (John Doe)"); // QListWidgetItem * item = new QListWidgetItem(QIcon(":/res/stm32.png"), "00:80:E1:05:44:21 @ 192.168.0.11 (John
// ui->devices->addItem(item); // Doe)"); ui->devices->addItem(item); QListWidgetItem * item2 = new QListWidgetItem(QIcon(":/res/rpi.png"),
// QListWidgetItem * item2 = new QListWidgetItem(QIcon(":/res/rpi.png"), "E4:5F:01:05:44:21 @ 192.168.0.11 (Jane Doe)"); // "E4:5F:01:05:44:21 @ 192.168.0.11 (Jane Doe)"); ui->devices->addItem(item2); QListWidgetItem * item3 = new
// ui->devices->addItem(item2); // QListWidgetItem(QIcon(":/res/unknown.png"), "44:44:44:05:44:21 @ 192.168.0.11 (Juul Doe)");
// QListWidgetItem * item3 = new QListWidgetItem(QIcon(":/res/unknown.png"), "44:44:44:05:44:21 @ 192.168.0.11 (Juul Doe)");
// ui->devices->addItem(item3); // ui->devices->addItem(item3);
connect(ui->actionAbout_Qt, &QAction::triggered, QApplication::aboutQt); connect(ui->actionAbout_Qt, &QAction::triggered, QApplication::aboutQt);
} }
MainWindow::~MainWindow() MainWindow::~MainWindow() {
{
delete ui; delete ui;
} }
void MainWindow::on_pbRefresh_clicked() void MainWindow::on_pbRefresh_clicked() {
{
this->func = 0; this->func = 0;
SendRequest(); SendRequest();
m_timer->start(); m_timer->start();
} }
void MainWindow::SendRequest() void MainWindow::SendRequest() {
{
int broadcasts_send = 0; int broadcasts_send = 0;
int data_send = 0; int data_send = 0;
QUdpSocket udpSocket; QUdpSocket udpSocket;
@@ -77,16 +69,15 @@ void MainWindow::SendRequest()
} }
} }
} }
} } else if (this->func == 1) {
else if(this->func == 1){
QHostAddress addr(ui->comboBox->currentText()); QHostAddress addr(ui->comboBox->currentText());
udpSocket.writeDatagram(this->data, addr, UDP_PORT); udpSocket.writeDatagram(this->data, addr, UDP_PORT);
data_send++; data_send++;
} }
if (broadcasts_send == 0 && data_send == 0) { if (broadcasts_send == 0 && data_send == 0) {
ui->pteLog->appendPlainText("Warning: no Network Interface Cards or valid IP adresses found (no broadcasts send)"); ui->pteLog->appendPlainText(
"Warning: no Network Interface Cards or valid IP adresses found (no broadcasts send)");
} else if (data_send != 0) { } else if (data_send != 0) {
ui->pteLog->appendPlainText(tr("Info: %1 message sent to %2").arg(data_send).arg(ui->comboBox->currentText())); ui->pteLog->appendPlainText(tr("Info: %1 message sent to %2").arg(data_send).arg(ui->comboBox->currentText()));
} else { } else {
@@ -94,8 +85,7 @@ void MainWindow::SendRequest()
} }
} }
void MainWindow::processPendingDatagrams() void MainWindow::processPendingDatagrams() {
{
QByteArray datagram; QByteArray datagram;
QHostAddress host; QHostAddress host;
@@ -114,13 +104,9 @@ void MainWindow::processPendingDatagrams()
} }
} }
void MainWindow::processDatagram(QString msg,QString host) void MainWindow::processDatagram(QString msg, QString host) {
{
// Append received data to log // Append received data to log
QString logLine = tr("Van %1: \"%2\"") QString logLine = tr("Van %1: \"%2\"").arg(host).arg(msg);
.arg(host)
.arg(msg);
ui->pteLog->appendPlainText(logLine); ui->pteLog->appendPlainText(logLine);
// We receive our own request. So a check to see if it is the request: // We receive our own request. So a check to see if it is the request:
@@ -133,9 +119,9 @@ void MainWindow::processDatagram(QString msg,QString host)
ui->comboBox->addItem(host); ui->comboBox->addItem(host);
} }
// RegEx for MAC adress // RegEx for MAC adress
QRegularExpression macRegExp("([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})"); QRegularExpression macRegExp(
"([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})[:-]([0-9A-F]{2})");
QRegularExpressionMatch match = macRegExp.match(msg.toUpper()); QRegularExpressionMatch match = macRegExp.match(msg.toUpper());
if (match.hasMatch()) { if (match.hasMatch()) {
QString foundOUI = match.captured(1) % match.captured(2) % match.captured(3); QString foundOUI = match.captured(1) % match.captured(2) % match.captured(3);
@@ -176,8 +162,7 @@ void MainWindow::processDatagram(QString msg,QString host)
} }
} }
QListWidgetItem *MainWindow::searchItem(QString MAC) QListWidgetItem* MainWindow::searchItem(QString MAC) {
{
QListWidgetItem* item = nullptr; QListWidgetItem* item = nullptr;
for (int i = 0; i < ui->devices->count(); i++) { for (int i = 0; i < ui->devices->count(); i++) {
item = ui->devices->item(i); item = ui->devices->item(i);
@@ -189,8 +174,7 @@ QListWidgetItem *MainWindow::searchItem(QString MAC)
return item; return item;
} }
void MainWindow::on_devices_itemDoubleClicked(QListWidgetItem *item) void MainWindow::on_devices_itemDoubleClicked(QListWidgetItem* item) {
{
// Copy the IP to the clipboard // Copy the IP to the clipboard
QString itemText = item->text(); QString itemText = item->text();
int start = itemText.indexOf('@') + 2; int start = itemText.indexOf('@') + 2;
@@ -200,8 +184,7 @@ void MainWindow::on_devices_itemDoubleClicked(QListWidgetItem *item)
clipboard->setText(ip); clipboard->setText(ip);
} }
void MainWindow::on_devices_customContextMenuRequested(const QPoint &pos) void MainWindow::on_devices_customContextMenuRequested(const QPoint& pos) {
{
// create menu // create menu
QAction copyAction(QIcon(":/res/copy-icon.png"), "Copy IP"); QAction copyAction(QIcon(":/res/copy-icon.png"), "Copy IP");
QMenu menu; QMenu menu;
@@ -217,42 +200,30 @@ void MainWindow::on_devices_customContextMenuRequested(const QPoint &pos)
} }
} }
void MainWindow::on_actionAbout_triggered() void MainWindow::on_actionAbout_triggered() {
{
About ab(this); About ab(this);
ab.exec(); ab.exec();
} }
void MainWindow::on_name_textEdited(const QString &arg1) void MainWindow::on_name_textEdited(const QString& arg1) {
{
this->name = arg1; this->name = arg1;
} }
void MainWindow::on_surname_textEdited(const QString& arg1) {
void MainWindow::on_surname_textEdited(const QString &arg1)
{
this->surname = arg1; this->surname = arg1;
} }
void MainWindow::on_comboBox_currentIndexChanged(int index) {
void MainWindow::on_comboBox_currentIndexChanged(int index)
{
if (index == 0) { if (index == 0) {
ui->ChangeOwner->setDisabled(true); ui->ChangeOwner->setDisabled(true);
} } else {
else{
ui->ChangeOwner->setDisabled(false); ui->ChangeOwner->setDisabled(false);
} }
} }
void MainWindow::on_ChangeOwner_clicked() {
void MainWindow::on_ChangeOwner_clicked()
{
this->data = ("func1:name: " + this->name + ", surname: " + this->surname + "").toUtf8(); this->data = ("func1:name: " + this->name + ", surname: " + this->surname + "").toUtf8();
this->func = 1; this->func = 1;
SendRequest(); SendRequest();
m_timer->start(); m_timer->start();
} }

View File

@@ -6,8 +6,8 @@
#include <QtWidgets> #include <QtWidgets>
#define QD qDebug() << __FILE__ << __LINE__ #define QD qDebug() << __FILE__ << __LINE__
#include "about.h"
#include <QString> #include <QString>
#include "about.h"
// UDP protocol: // UDP protocol:
// REQ= Where are you?v1.0 // REQ= Where are you?v1.0
@@ -17,11 +17,12 @@
#define UDP_ANS_OWNER "my owner is " #define UDP_ANS_OWNER "my owner is "
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; } namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE QT_END_NAMESPACE
class MainWindow : public QMainWindow class MainWindow : public QMainWindow {
{
Q_OBJECT Q_OBJECT
public: public:

8
build_app.sh Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/bash
cd project/
rm -fr build/*
cmake -B build/ -G Ninja
ninja -C build/
cd ../

7
build_tests.sh Normal file
View File

@@ -0,0 +1,7 @@
#!/bin/bash
rm -fr build/*
cmake -B build/ -G Ninja
ninja -C build/
ctest --test-dir build

View File

@@ -0,0 +1,8 @@
FROM fedora:39
RUN dnf update -y
RUN dnf install -y git
RUN dnf install -y ninja-build make cmake gcc-c++ gcc clang-tools-extra clang-devel clang
RUN dnf install -y gtest-devel gtest
RUN dnf install -y arm-none-eabi-gcc-cs arm-none-eabi-gcc-cs-c++ arm-none-eabi-binutils-cs.x86_64 arm-none-eabi-newlib.noarch
ENTRYPOINT [ "/bin/bash" ]

15
lint.sh Normal file
View File

@@ -0,0 +1,15 @@
#!/bin/bash
if (( $# < 1 )); then
>&2 echo "Illegal number of parameters"
exit 1
fi
# save unsaved work
git stash --include-untracked
clang-format -i "$@"
git add -A && git commit -m "Lint"
git stash pop

BIN
llfs-data/base.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
llfs-data/clap.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

BIN
llfs-data/dafoe.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

BIN
llfs-data/fellowkids.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

BIN
llfs-data/goose.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

122
llfs-data/index.css Normal file
View File

@@ -0,0 +1,122 @@
body{
font-family:Arial;
}
h1{
font-size: 175%;
padding: 10px;
margin: 10px;
}
h2 {
font-size: 150%;
padding: 8px;
position: absolute;
top: -6px;
left: 20px;
background-color:orangered;
color: white;
border-radius: 20px;
padding-left: 30px;
padding-right: 30px;
}
h3 {
font-size: 125%;
padding: 10px;
margin: 10px;
}
p {
padding: 10px;
margin: 10px;
}
header {
padding: 30px;
background-color: orangered;
}
header:after {
content:"";
display: block;
clear: both;
}
.logo{
width:100px;
transform:rotate(-10deg);
-moz-transform:rotate(-10deg);
-webkit-transform:rotate(-10deg);
-o-transform:rotate(-10deg);
float:left;
}
.title{
color: white;
font-size: 40px;
font: 60px "Lucida Sans Unicode", "Lucida Grande", sans-serif;
text-align: center;
padding-top: 10px;
}
.column {
flex-grow: 0;
flex-basis: 48%;
position: relative;
}
.right {
margin-left: 2%;
}
.content {
padding: 20px;
display: flex;
}
/*Geef vorm aan de vakjes op de site*/
.card {
background-color: white;
border-radius:10px;
padding:1%;
border: 1px solid black;
margin: 2% 0;
width: 100%;
padding-top: 30px;
}
.image {
width: 25%;
height: auto;
border: 10px solid transparent;
}
.image:hover {
border: 10px solid lightsalmon;
border-radius: 10px;
}
#selected {
border: 10px solid lightsalmon;
border-radius: 10px;
}
.sendButton {
position: absolute;
margin-top: 8%;
text-align: center;
margin-left: 40%;
font-size: 150%;
padding: 20px;
background-color:orangered;
color: white;
border-radius: 20px;
}
.sendButton:hover {
background-color:white;
color: orangered ;
}
/*---------------------------------------------------------------------------------------*/
footer {
background-color: orangered;
padding: 20px;
text-align: center;
border-top:20px solid lightskyblue; /*solid is vast*/
border-bottom:20px solid lightskyblue;
margin-top: 20px;
}
.foot {
color: white;
}
html{
background-color: white;
}
#myImg {
border: none;
transition: border 0.3s;
}

133
llfs-data/index.html Normal file
View File

@@ -0,0 +1,133 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Webservices & Applications</title>
<link href="reset.css" rel="stylesheet" />
<link href="index.css" rel="stylesheet" />
</head>
<body>
<div>
<header>
<img class="logo" src="st.bmp" alt="STM"/>
<p class="title">
Webservices & Applications
</p>
</header>
<form action="cgi">
<div class="content row">
<div class="column left">
<div class="card">
<h2>Adjustments</h2>
<label for="send_text">Text LCD:</label>
<input type="text" id="send_text" name="vtxt"><br><br>
<label for="send_colorTxt">Select the text color:</label>
<input type="color" id="send_colorTxt" name="vktxt" value="#0000ff"><br><br>
<label for="send_colorBack">Select the background color:</label>
<input type="color" id="send_colorBack" name="vka" value="#0000ff"><br><br>
<!--<span class="sendButton" onClick="start();">
<input type="submit" value="Send">
</span>-->
<input type="submit" value="Send" class="sendButton" onClick="start();">
</div>
</div>
<div class="column right">
<div class="card">
<h2 >Images</h2>
<label for="vfo">Choose your photo:</label>
<div class="gallery" id="gallery">
<input type="hidden" id="gallery1" name="vfo" value="">
</div>
</div>
</div>
</div>
</form>
<script>
document.getElementById('send_colorBack').addEventListener('input', function() { document.body.style.backgroundColor = this.value; });
document.getElementById('send_colorTxt').addEventListener('input', function() { document.getElementById('send_text').style.color = this.value; });
/*--------------------------------------------------------------*/
// Function to load images from the folder
function loadImages() {
console.log("loadImages");
const xhttp = new XMLHttpRequest();
xhttp.onload = function() {
const imageContainer = document.getElementById('gallery');
console.log(this.responseText);
images = this.responseText.split('|');
console.log(images);
for (let i = 0; i < images.length; i++) {
console.log(images[i]);
const img = document.createElement('img');;
img.src= images[i];
img.alt = images[i];
img.className = `image ${i}`;
img.value = images[i];
img.onload = () => {
imageContainer.appendChild(img);
}
img.onclick = () => {
selecteerFoto(img, i, images[i]);
}
}
}
xhttp.open("GET", "images.info");
xhttp.send();
}
function selecteerFoto(image, i, images) {
var gallery = document.getElementById('gallery1');
var value = gallery.getAttribute('value');
var Pictures = document.querySelectorAll('.gallery img');
Pictures.forEach(function(image) {
image.removeAttribute('id');
image.removeAttribute('name');
});
image.id = "selected";
image.name = "vfo";
image.value = images[i];
gallery.setAttribute('value', images);
}
// Call the function to load the images
loadImages();
const xhr = new XMLHttpRequest();
function start() {
var send_text = document.getElementById("send_text").value;
var send_colorTxt = document.getElementById("send_colorTxt").value;
var send_colorBack = document.getElementById("send_colorBack").value;
var sendPicture = document.getElementById("selected").alt;
var url = "cgi?";
var queryString = url + "vtxt=" + send_text + "&vktxt=" + encodeURIComponent(send_colorTxt) + "&vka=" + encodeURIComponent(send_colorBack) + "&vfo=" + sendPicture;
console.log(queryString);
xhr.onreadystatechange = showAnswer;
xhr.open("GET", queryString);
xhr.send();
}
function showAnswer() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
}
</script>
<footer>
<p class="foot">
Copyright &copy; Thomas More Mechelen-Antwerpen vzw -
Campus De Nayer - Professionele bachelor elektronica-ict
2023
</p>
</footer>
</div>
</body>
</html>

BIN
llfs-data/mind.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

62
llfs-data/reset.css Normal file
View File

@@ -0,0 +1,62 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0b1 | 201101
NOTE: WORK IN PROGRESS
USE WITH CAUTION AND TEST WITH ABANDON */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
/* remember to define visible focus styles!
:focus {
outline: ?????;
} */
/* remember to highlight inserts somehow! */
ins {
text-decoration: none;
}
del {
text-decoration: line-through;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

BIN
llfs-data/webp.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

View File

@@ -60,7 +60,8 @@ int main(int argc, char** argv) {
} }
// Write the header of the output file // Write the header of the output file
fprintf(out_file, "/**\n" fprintf(out_file,
"/**\n"
" * @file %s\n" " * @file %s\n"
" * @brief Linked list file system (llfs) data file.\n" " * @brief Linked list file system (llfs) data file.\n"
" * This file was generated by mkllfs %s.\n" " * This file was generated by mkllfs %s.\n"
@@ -125,7 +126,8 @@ int main(int argc, char** argv) {
// Make the last file the root file of the llfs // Make the last file the root file of the llfs
fprintf(out_file, "\n"); fprintf(out_file, "\n");
fprintf(out_file, "const struct llfs_data_file *llfs_root =%s%s;\n", (strcmp(prev_llfs_name, "NULL") == 0 ? " " : " &"), prev_llfs_name); fprintf(out_file, "const struct llfs_data_file *llfs_root =%s%s;\n",
(strcmp(prev_llfs_name, "NULL") == 0 ? " " : " &"), prev_llfs_name);
// Print the number of files // Print the number of files
printf("Successfully converted %d files.\r\n", file_count); printf("Successfully converted %d files.\r\n", file_count);

View File

@@ -48,21 +48,20 @@ extern "C" {
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
# include <windows.h>
#include <tchar.h> #include <tchar.h>
#include <windows.h>
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4996) #pragma warning(disable : 4996)
#else #else
#include <dirent.h> #include <dirent.h>
#include <libgen.h> #include <libgen.h>
# include <sys/stat.h>
#include <stddef.h> #include <stddef.h>
#include <sys/stat.h>
#endif #endif
#ifdef __MINGW32__ #ifdef __MINGW32__
#include <tchar.h> #include <tchar.h>
#endif #endif
/* types */ /* types */
/* Windows UNICODE wide character support */ /* Windows UNICODE wide character support */
@@ -139,25 +138,21 @@ extern "C" {
/* readdir_r is a POSIX-only function, and may not be available under various /* readdir_r is a POSIX-only function, and may not be available under various
* environments/settings, e.g. MinGW. Use readdir fallback */ * environments/settings, e.g. MinGW. Use readdir fallback */
#if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE ||\ #if _POSIX_C_SOURCE >= 1 || _XOPEN_SOURCE || _BSD_SOURCE || _SVID_SOURCE || _POSIX_SOURCE
_POSIX_SOURCE
#define _TINYDIR_HAS_READDIR_R #define _TINYDIR_HAS_READDIR_R
#endif #endif
#if _POSIX_C_SOURCE >= 200112L #if _POSIX_C_SOURCE >= 200112L
#define _TINYDIR_HAS_FPATHCONF #define _TINYDIR_HAS_FPATHCONF
#include <unistd.h> #include <unistd.h>
#endif #endif
#if _BSD_SOURCE || _SVID_SOURCE || \ #if _BSD_SOURCE || _SVID_SOURCE || (_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
#define _TINYDIR_HAS_DIRFD #define _TINYDIR_HAS_DIRFD
#include <sys/types.h> #include <sys/types.h>
#endif #endif
#if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD &&\ #if defined _TINYDIR_HAS_FPATHCONF && defined _TINYDIR_HAS_DIRFD && defined _PC_NAME_MAX
defined _PC_NAME_MAX
#define _TINYDIR_USE_FPATHCONF #define _TINYDIR_USE_FPATHCONF
#endif #endif
#if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R ||\ #if defined __MINGW32__ || !defined _TINYDIR_HAS_READDIR_R || !(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX)
!(defined _TINYDIR_USE_FPATHCONF || defined NAME_MAX)
#define _TINYDIR_USE_READDIR #define _TINYDIR_USE_READDIR
#endif #endif
@@ -195,8 +190,7 @@ extern "C" {
#define _TINYDIR_FREE(_ptr) free(_ptr) #define _TINYDIR_FREE(_ptr) free(_ptr)
#endif /* !defined(_TINYDIR_MALLOC) */ #endif /* !defined(_TINYDIR_MALLOC) */
typedef struct tinydir_file typedef struct tinydir_file {
{
_tinydir_char_t path[_TINYDIR_PATH_MAX]; _tinydir_char_t path[_TINYDIR_PATH_MAX];
_tinydir_char_t name[_TINYDIR_FILENAME_MAX]; _tinydir_char_t name[_TINYDIR_FILENAME_MAX];
_tinydir_char_t* extension; _tinydir_char_t* extension;
@@ -212,8 +206,7 @@ typedef struct tinydir_file
#endif #endif
} tinydir_file; } tinydir_file;
typedef struct tinydir_dir typedef struct tinydir_dir {
{
_tinydir_char_t path[_TINYDIR_PATH_MAX]; _tinydir_char_t path[_TINYDIR_PATH_MAX];
int has_next; int has_next;
size_t n_files; size_t n_files;
@@ -231,7 +224,6 @@ typedef struct tinydir_dir
#endif #endif
} tinydir_dir; } tinydir_dir;
/* declarations */ /* declarations */
_TINYDIR_FUNC _TINYDIR_FUNC
@@ -263,12 +255,10 @@ size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp);
#endif #endif
#endif #endif
/* definitions*/ /* definitions*/
_TINYDIR_FUNC _TINYDIR_FUNC
int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path) int tinydir_open(tinydir_dir* dir, const _tinydir_char_t* path) {
{
#ifndef _MSC_VER #ifndef _MSC_VER
#ifndef _TINYDIR_USE_READDIR #ifndef _TINYDIR_USE_READDIR
int error; int error;
@@ -279,13 +269,11 @@ int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
#endif #endif
_tinydir_char_t* pathp; _tinydir_char_t* pathp;
if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0) if (dir == NULL || path == NULL || _tinydir_strlen(path) == 0) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) {
{
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return -1; return -1;
} }
@@ -305,8 +293,7 @@ int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
_tinydir_strcpy(dir->path, path); _tinydir_strcpy(dir->path, path);
/* Remove trailing slashes */ /* Remove trailing slashes */
pathp = &dir->path[_tinydir_strlen(dir->path) - 1]; pathp = &dir->path[_tinydir_strlen(dir->path) - 1];
while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/'))) while (pathp != dir->path && (*pathp == TINYDIR_STRING('\\') || *pathp == TINYDIR_STRING('/'))) {
{
*pathp = TINYDIR_STRING('\0'); *pathp = TINYDIR_STRING('\0');
pathp++; pathp++;
} }
@@ -318,13 +305,11 @@ int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
#else #else
dir->_h = FindFirstFile(path_buf, &dir->_f); dir->_h = FindFirstFile(path_buf, &dir->_f);
#endif #endif
if (dir->_h == INVALID_HANDLE_VALUE) if (dir->_h == INVALID_HANDLE_VALUE) {
{
errno = ENOENT; errno = ENOENT;
#else #else
dir->_d = _tinydir_opendir(path); dir->_d = _tinydir_opendir(path);
if (dir->_d == NULL) if (dir->_d == NULL) {
{
#endif #endif
goto bail; goto bail;
} }
@@ -337,15 +322,17 @@ int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
#else #else
/* allocate dirent buffer for readdir_r */ /* allocate dirent buffer for readdir_r */
size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */ size = _tinydir_dirent_buf_size(dir->_d); /* conversion to int */
if (size == -1) return -1; if (size == -1)
return -1;
dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size); dir->_ep = (struct _tinydir_dirent*)_TINYDIR_MALLOC(size);
if (dir->_ep == NULL) return -1; if (dir->_ep == NULL)
return -1;
error = readdir_r(dir->_d, dir->_ep, &dir->_e); error = readdir_r(dir->_d, dir->_ep, &dir->_e);
if (error != 0) return -1; if (error != 0)
return -1;
#endif #endif
if (dir->_e == NULL) if (dir->_e == NULL) {
{
dir->has_next = 0; dir->has_next = 0;
} }
#endif #endif
@@ -358,55 +345,45 @@ int tinydir_open(tinydir_dir *dir, const _tinydir_char_t *path)
} }
_TINYDIR_FUNC _TINYDIR_FUNC
int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path) int tinydir_open_sorted(tinydir_dir* dir, const _tinydir_char_t* path) {
{
/* Count the number of files first, to pre-allocate the files array */ /* Count the number of files first, to pre-allocate the files array */
size_t n_files = 0; size_t n_files = 0;
if (tinydir_open(dir, path) == -1) if (tinydir_open(dir, path) == -1) {
{
return -1; return -1;
} }
while (dir->has_next) while (dir->has_next) {
{
n_files++; n_files++;
if (tinydir_next(dir) == -1) if (tinydir_next(dir) == -1) {
{
goto bail; goto bail;
} }
} }
tinydir_close(dir); tinydir_close(dir);
if (n_files == 0 || tinydir_open(dir, path) == -1) if (n_files == 0 || tinydir_open(dir, path) == -1) {
{
return -1; return -1;
} }
dir->n_files = 0; dir->n_files = 0;
dir->_files = (tinydir_file*)_TINYDIR_MALLOC(sizeof *dir->_files * n_files); dir->_files = (tinydir_file*)_TINYDIR_MALLOC(sizeof *dir->_files * n_files);
if (dir->_files == NULL) if (dir->_files == NULL) {
{
goto bail; goto bail;
} }
while (dir->has_next) while (dir->has_next) {
{
tinydir_file* p_file; tinydir_file* p_file;
dir->n_files++; dir->n_files++;
p_file = &dir->_files[dir->n_files - 1]; p_file = &dir->_files[dir->n_files - 1];
if (tinydir_readfile(dir, p_file) == -1) if (tinydir_readfile(dir, p_file) == -1) {
{
goto bail; goto bail;
} }
if (tinydir_next(dir) == -1) if (tinydir_next(dir) == -1) {
{
goto bail; goto bail;
} }
/* Just in case the number of files has changed between the first and /* Just in case the number of files has changed between the first and
second reads, terminate without writing into unallocated memory */ second reads, terminate without writing into unallocated memory */
if (dir->n_files == n_files) if (dir->n_files == n_files) {
{
break; break;
} }
} }
@@ -421,10 +398,8 @@ int tinydir_open_sorted(tinydir_dir *dir, const _tinydir_char_t *path)
} }
_TINYDIR_FUNC _TINYDIR_FUNC
void tinydir_close(tinydir_dir *dir) void tinydir_close(tinydir_dir* dir) {
{ if (dir == NULL) {
if (dir == NULL)
{
return; return;
} }
@@ -434,14 +409,12 @@ void tinydir_close(tinydir_dir *dir)
_TINYDIR_FREE(dir->_files); _TINYDIR_FREE(dir->_files);
dir->_files = NULL; dir->_files = NULL;
#ifdef _MSC_VER #ifdef _MSC_VER
if (dir->_h != INVALID_HANDLE_VALUE) if (dir->_h != INVALID_HANDLE_VALUE) {
{
FindClose(dir->_h); FindClose(dir->_h);
} }
dir->_h = INVALID_HANDLE_VALUE; dir->_h = INVALID_HANDLE_VALUE;
#else #else
if (dir->_d) if (dir->_d) {
{
_tinydir_closedir(dir->_d); _tinydir_closedir(dir->_d);
} }
dir->_d = NULL; dir->_d = NULL;
@@ -454,15 +427,12 @@ void tinydir_close(tinydir_dir *dir)
} }
_TINYDIR_FUNC _TINYDIR_FUNC
int tinydir_next(tinydir_dir *dir) int tinydir_next(tinydir_dir* dir) {
{ if (dir == NULL) {
if (dir == NULL)
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if (!dir->has_next) if (!dir->has_next) {
{
errno = ENOENT; errno = ENOENT;
return -1; return -1;
} }
@@ -473,12 +443,10 @@ int tinydir_next(tinydir_dir *dir)
#ifdef _TINYDIR_USE_READDIR #ifdef _TINYDIR_USE_READDIR
dir->_e = _tinydir_readdir(dir->_d); dir->_e = _tinydir_readdir(dir->_d);
#else #else
if (dir->_ep == NULL) if (dir->_ep == NULL) {
{
return -1; return -1;
} }
if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0) if (readdir_r(dir->_d, dir->_ep, &dir->_e) != 0) {
{
return -1; return -1;
} }
#endif #endif
@@ -487,9 +455,7 @@ int tinydir_next(tinydir_dir *dir)
{ {
dir->has_next = 0; dir->has_next = 0;
#ifdef _MSC_VER #ifdef _MSC_VER
if (GetLastError() != ERROR_SUCCESS && if (GetLastError() != ERROR_SUCCESS && GetLastError() != ERROR_NO_MORE_FILES) {
GetLastError() != ERROR_NO_MORE_FILES)
{
tinydir_close(dir); tinydir_close(dir);
errno = EIO; errno = EIO;
return -1; return -1;
@@ -501,11 +467,9 @@ int tinydir_next(tinydir_dir *dir)
} }
_TINYDIR_FUNC _TINYDIR_FUNC
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file) int tinydir_readfile(const tinydir_dir* dir, tinydir_file* file) {
{
const _tinydir_char_t* filename; const _tinydir_char_t* filename;
if (dir == NULL || file == NULL) if (dir == NULL || file == NULL) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
@@ -524,16 +488,12 @@ int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
#else #else
dir->_e->d_name; dir->_e->d_name;
#endif #endif
if (_tinydir_strlen(dir->path) + if (_tinydir_strlen(dir->path) + _tinydir_strlen(filename) + 1 + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) {
_tinydir_strlen(filename) + 1 + _TINYDIR_PATH_EXTRA >=
_TINYDIR_PATH_MAX)
{
/* the path for the file will be too long */ /* the path for the file will be too long */
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return -1; return -1;
} }
if (_tinydir_strlen(filename) >= _TINYDIR_FILENAME_MAX) if (_tinydir_strlen(filename) >= _TINYDIR_FILENAME_MAX) {
{
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return -1; return -1;
} }
@@ -546,17 +506,15 @@ int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
#ifndef _MSC_VER #ifndef _MSC_VER
#ifdef __MINGW32__ #ifdef __MINGW32__
if (_tstat( if (_tstat(
#elif (defined _BSD_SOURCE) || (defined _DEFAULT_SOURCE) \ #elif (defined _BSD_SOURCE) || (defined _DEFAULT_SOURCE) || ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \
|| ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \ || ((defined _POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) || ((defined __APPLE__) && (defined __MACH__)) \
|| ((defined _POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) \
|| ((defined __APPLE__) && (defined __MACH__)) \
|| (defined BSD) || (defined BSD)
if (lstat( if (lstat(
#else #else
if (stat( if (stat(
#endif #endif
file->path, &file->_s) == -1) file->path, &file->_s)
{ == -1) {
return -1; return -1;
} }
#endif #endif
@@ -570,19 +528,18 @@ int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
#endif #endif
file->is_reg = file->is_reg =
#ifdef _MSC_VER #ifdef _MSC_VER
!!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) || !!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NORMAL)
( || (!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE)
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DEVICE) && && !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && && !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) &&
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) &&
#ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM #ifdef FILE_ATTRIBUTE_INTEGRITY_STREAM
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) && !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_INTEGRITY_STREAM) &&
#endif #endif
#ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA #ifdef FILE_ATTRIBUTE_NO_SCRUB_DATA
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) && !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_NO_SCRUB_DATA) &&
#endif #endif
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) && !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE)
!(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY)); && !(dir->_f.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY));
#else #else
S_ISREG(file->_s.st_mode); S_ISREG(file->_s.st_mode);
#endif #endif
@@ -591,15 +548,12 @@ int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
} }
_TINYDIR_FUNC _TINYDIR_FUNC
int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i) int tinydir_readfile_n(const tinydir_dir* dir, tinydir_file* file, size_t i) {
{ if (dir == NULL || file == NULL) {
if (dir == NULL || file == NULL)
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if (i >= dir->n_files) if (i >= dir->n_files) {
{
errno = ENOENT; errno = ENOENT;
return -1; return -1;
} }
@@ -611,24 +565,20 @@ int tinydir_readfile_n(const tinydir_dir *dir, tinydir_file *file, size_t i)
} }
_TINYDIR_FUNC _TINYDIR_FUNC
int tinydir_open_subdir_n(tinydir_dir *dir, size_t i) int tinydir_open_subdir_n(tinydir_dir* dir, size_t i) {
{
_tinydir_char_t path[_TINYDIR_PATH_MAX]; _tinydir_char_t path[_TINYDIR_PATH_MAX];
if (dir == NULL) if (dir == NULL) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if (i >= dir->n_files || !dir->_files[i].is_dir) if (i >= dir->n_files || !dir->_files[i].is_dir) {
{
errno = ENOENT; errno = ENOENT;
return -1; return -1;
} }
_tinydir_strcpy(path, dir->_files[i].path); _tinydir_strcpy(path, dir->_files[i].path);
tinydir_close(dir); tinydir_close(dir);
if (tinydir_open_sorted(dir, path) == -1) if (tinydir_open_sorted(dir, path) == -1) {
{
return -1; return -1;
} }
@@ -637,8 +587,7 @@ int tinydir_open_subdir_n(tinydir_dir *dir, size_t i)
/* Open a single file given its path */ /* Open a single file given its path */
_TINYDIR_FUNC _TINYDIR_FUNC
int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path) int tinydir_file_open(tinydir_file* file, const _tinydir_char_t* path) {
{
tinydir_dir dir; tinydir_dir dir;
int result = 0; int result = 0;
int found = 0; int found = 0;
@@ -651,13 +600,11 @@ int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
_tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX]; _tinydir_char_t ext_buf[_TINYDIR_FILENAME_MAX];
#endif #endif
if (file == NULL || path == NULL || _tinydir_strlen(path) == 0) if (file == NULL || path == NULL || _tinydir_strlen(path) == 0) {
{
errno = EINVAL; errno = EINVAL;
return -1; return -1;
} }
if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) if (_tinydir_strlen(path) + _TINYDIR_PATH_EXTRA >= _TINYDIR_PATH_MAX) {
{
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return -1; return -1;
} }
@@ -665,23 +612,13 @@ int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
/* Get the parent path */ /* Get the parent path */
#if (defined _MSC_VER || defined __MINGW32__) #if (defined _MSC_VER || defined __MINGW32__)
#if ((defined _MSC_VER) && (_MSC_VER >= 1400)) #if ((defined _MSC_VER) && (_MSC_VER >= 1400))
errno = _tsplitpath_s( errno = _tsplitpath_s(path, drive_buf, _TINYDIR_DRIVE_MAX, dir_name_buf, _TINYDIR_FILENAME_MAX, file_name_buf,
path, _TINYDIR_FILENAME_MAX, ext_buf, _TINYDIR_FILENAME_MAX);
drive_buf, _TINYDIR_DRIVE_MAX,
dir_name_buf, _TINYDIR_FILENAME_MAX,
file_name_buf, _TINYDIR_FILENAME_MAX,
ext_buf, _TINYDIR_FILENAME_MAX);
#else #else
_tsplitpath( _tsplitpath(path, drive_buf, dir_name_buf, file_name_buf, ext_buf);
path,
drive_buf,
dir_name_buf,
file_name_buf,
ext_buf);
#endif #endif
if (errno) if (errno) {
{
return -1; return -1;
} }
@@ -695,8 +632,7 @@ int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
/* Emulate the behavior of dirname by returning "." for dir name if it's /* Emulate the behavior of dirname by returning "." for dir name if it's
empty */ empty */
if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0') if (drive_buf[0] == '\0' && dir_name_buf[0] == '\0') {
{
_tinydir_strcpy(dir_name_buf, TINYDIR_STRING(".")); _tinydir_strcpy(dir_name_buf, TINYDIR_STRING("."));
} }
/* Concatenate the drive letter and dir name to form full dir name */ /* Concatenate the drive letter and dir name to form full dir name */
@@ -728,29 +664,24 @@ int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
} }
/* Open the parent directory */ /* Open the parent directory */
if (tinydir_open(&dir, dir_name) == -1) if (tinydir_open(&dir, dir_name) == -1) {
{
return -1; return -1;
} }
/* Read through the parent directory and look for the file */ /* Read through the parent directory and look for the file */
while (dir.has_next) while (dir.has_next) {
{ if (tinydir_readfile(&dir, file) == -1) {
if (tinydir_readfile(&dir, file) == -1)
{
result = -1; result = -1;
goto bail; goto bail;
} }
if (_tinydir_strcmp(file->name, base_name) == 0) if (_tinydir_strcmp(file->name, base_name) == 0) {
{
/* File found */ /* File found */
found = 1; found = 1;
break; break;
} }
tinydir_next(&dir); tinydir_next(&dir);
} }
if (!found) if (!found) {
{
result = -1; result = -1;
errno = ENOENT; errno = ENOENT;
} }
@@ -761,26 +692,20 @@ int tinydir_file_open(tinydir_file *file, const _tinydir_char_t *path)
} }
_TINYDIR_FUNC _TINYDIR_FUNC
void _tinydir_get_ext(tinydir_file *file) void _tinydir_get_ext(tinydir_file* file) {
{
_tinydir_char_t* period = _tinydir_strrchr(file->name, TINYDIR_STRING('.')); _tinydir_char_t* period = _tinydir_strrchr(file->name, TINYDIR_STRING('.'));
if (period == NULL) if (period == NULL) {
{
file->extension = &(file->name[_tinydir_strlen(file->name)]); file->extension = &(file->name[_tinydir_strlen(file->name)]);
} } else {
else
{
file->extension = period + 1; file->extension = period + 1;
} }
} }
_TINYDIR_FUNC _TINYDIR_FUNC
int _tinydir_file_cmp(const void *a, const void *b) int _tinydir_file_cmp(const void* a, const void* b) {
{
const tinydir_file* fa = (const tinydir_file*)a; const tinydir_file* fa = (const tinydir_file*)a;
const tinydir_file* fb = (const tinydir_file*)b; const tinydir_file* fb = (const tinydir_file*)b;
if (fa->is_dir != fb->is_dir) if (fa->is_dir != fb->is_dir) {
{
return -(fa->is_dir - fb->is_dir); return -(fa->is_dir - fb->is_dir);
} }
return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX); return _tinydir_strncmp(fa->name, fb->name, _TINYDIR_FILENAME_MAX);
@@ -800,8 +725,7 @@ from https://womble.decadent.org.uk/readdir_r-advisory.html
* 255, since some systems (including at least HP-UX) incorrectly * * 255, since some systems (including at least HP-UX) incorrectly *
* define it to be a smaller value. */ * define it to be a smaller value. */
_TINYDIR_FUNC _TINYDIR_FUNC
size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp) size_t _tinydir_dirent_buf_size(_TINYDIR_DIR* dirp) {
{
long name_max; long name_max;
size_t name_end; size_t name_end;
/* parameter may be unused */ /* parameter may be unused */
@@ -821,8 +745,7 @@ size_t _tinydir_dirent_buf_size(_TINYDIR_DIR *dirp)
#error "buffer size for readdir_r cannot be determined" #error "buffer size for readdir_r cannot be determined"
#endif #endif
name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1; name_end = (size_t)offsetof(struct _tinydir_dirent, d_name) + name_max + 1;
return (name_end > sizeof(struct _tinydir_dirent) ? return (name_end > sizeof(struct _tinydir_dirent) ? name_end : sizeof(struct _tinydir_dirent));
name_end : sizeof(struct _tinydir_dirent));
} }
#endif #endif
#endif #endif

View File

@@ -20,13 +20,16 @@
#include "lcd_api.h" #include "lcd_api.h"
// Defines used by UDP callback // Defines used by UDP callback
#define UDP_BROADCAST_MAX_DATA_SIZE ((UDP_BROADCAST_MAX_NAME_SIZE * 2) - 2 + 25) // Define the maximum expected data size #define UDP_BROADCAST_MAX_DATA_SIZE \
((UDP_BROADCAST_MAX_NAME_SIZE * 2) - 2 + 25) // Define the maximum expected data size
#define UDP_BROADCAST_UDP_QUESTION1 "Where are you?v1.0" // Expected question from UDP client #define UDP_BROADCAST_UDP_QUESTION1 "Where are you?v1.0" // Expected question from UDP client
#define UDP_BROADCAST_MAX_FUNC_LEN 7 #define UDP_BROADCAST_MAX_FUNC_LEN 7
#define UDP_BROADCAST_MAX_COLON_COMMA_COUNT 4 #define UDP_BROADCAST_MAX_COLON_COMMA_COUNT 4
// Defines used by owner details // Defines used by owner details
#define UDP_BROADCAST_MAX_REPLY_SIZE (UDP_BROADCAST_MAX_MAC_ADDR_LEN + sizeof(UDP_BROADCAST_REPLY_MIDDLE_TEXT) + (UDP_BROADCAST_MAX_NAME_SIZE * 2) + UDP_BROADCAST_MAX_REPLY_SIZE_EXTRA) #define UDP_BROADCAST_MAX_REPLY_SIZE \
(UDP_BROADCAST_MAX_MAC_ADDR_LEN + sizeof(UDP_BROADCAST_REPLY_MIDDLE_TEXT) + (UDP_BROADCAST_MAX_NAME_SIZE * 2) \
+ UDP_BROADCAST_MAX_REPLY_SIZE_EXTRA)
#define UDP_BROADCAST_REPLY_MIDDLE_TEXT "is present and my owner is" #define UDP_BROADCAST_REPLY_MIDDLE_TEXT "is present and my owner is"
#define UDP_BROADCAST_MAX_MAC_ADDR_LEN 19 // Format is: "xx:xx:xx:xx:xx:xx" #define UDP_BROADCAST_MAX_MAC_ADDR_LEN 19 // Format is: "xx:xx:xx:xx:xx:xx"
@@ -36,7 +39,6 @@
#define UDP_BROADCAST_LCD_NAME_PRE_TEXT "New owner: " #define UDP_BROADCAST_LCD_NAME_PRE_TEXT "New owner: "
#define UDP_BROADCAST_LCD_TEXT_SIZE (strlen(UDP_BROADCAST_LCD_NAME_PRE_TEXT) + UDP_BROADCAST_MAX_NAME_SIZE) #define UDP_BROADCAST_LCD_TEXT_SIZE (strlen(UDP_BROADCAST_LCD_NAME_PRE_TEXT) + UDP_BROADCAST_MAX_NAME_SIZE)
/** /**
* @struct owner_details_t * @struct owner_details_t
* @brief contains information about the owner * @brief contains information about the owner

View File

@@ -13,10 +13,10 @@
#ifndef __ANIMATEDGIF__ #ifndef __ANIMATEDGIF__
#define __ANIMATEDGIF__ #define __ANIMATEDGIF__
#include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#define memcpy_P memcpy #define memcpy_P memcpy
#define PROGMEM #define PROGMEM
@@ -71,10 +71,7 @@ enum {
// RAW = 8-bit palettized pixels requiring transparent pixel handling // RAW = 8-bit palettized pixels requiring transparent pixel handling
// COOKED = 16 or 24-bpp fully rendered pixels ready for display // COOKED = 16 or 24-bpp fully rendered pixels ready for display
// //
enum { enum { GIF_DRAW_RAW = 0, GIF_DRAW_COOKED };
GIF_DRAW_RAW = 0,
GIF_DRAW_COOKED
};
enum { enum {
GIF_SUCCESS = 0, GIF_SUCCESS = 0,
@@ -89,24 +86,21 @@ enum {
GIF_ERROR_MEMORY GIF_ERROR_MEMORY
}; };
typedef struct gif_file_tag typedef struct gif_file_tag {
{
int32_t iPos; // current file position int32_t iPos; // current file position
int32_t iSize; // file size int32_t iSize; // file size
uint8_t* pData; // memory file pointer uint8_t* pData; // memory file pointer
void* fHandle; // class pointer to File/SdFat or whatever you want void* fHandle; // class pointer to File/SdFat or whatever you want
} GIFFILE; } GIFFILE;
typedef struct gif_info_tag typedef struct gif_info_tag {
{
int32_t iFrameCount; // total frames in file int32_t iFrameCount; // total frames in file
int32_t iDuration; // duration of animation in milliseconds int32_t iDuration; // duration of animation in milliseconds
int32_t iMaxDelay; // maximum frame delay int32_t iMaxDelay; // maximum frame delay
int32_t iMinDelay; // minimum frame delay int32_t iMinDelay; // minimum frame delay
} GIFINFO; } GIFINFO;
typedef struct gif_draw_tag typedef struct gif_draw_tag {
{
int iX, iY; // Corner offset of this frame on the canvas int iX, iY; // Corner offset of this frame on the canvas
int y; // current line being drawn (0 = top line of image) int y; // current line being drawn (0 = top line of image)
int iWidth, iHeight; // size of this frame int iWidth, iHeight; // size of this frame
@@ -132,8 +126,7 @@ typedef void (GIF_FREE_CALLBACK)(void *buffer);
// //
// our private structure to hold a GIF image decode state // our private structure to hold a GIF image decode state
// //
typedef struct gif_image_tag typedef struct gif_image_tag {
{
int iWidth, iHeight, iCanvasWidth, iCanvasHeight; int iWidth, iHeight, iCanvasWidth, iCanvasHeight;
int iX, iY; // GIF corner offset int iX, iY; // GIF corner offset
int iBpp; int iBpp;
@@ -171,16 +164,22 @@ typedef struct gif_image_tag
// //
// The GIF class wraps portable C code which does the actual work // The GIF class wraps portable C code which does the actual work
// //
class AnimatedGIF class AnimatedGIF {
{
public: public:
int open(uint8_t* pData, int iDataSize, GIF_DRAW_CALLBACK* pfnDraw); int open(uint8_t* pData, int iDataSize, GIF_DRAW_CALLBACK* pfnDraw);
int openFLASH(uint8_t* pData, int iDataSize, GIF_DRAW_CALLBACK* pfnDraw); int openFLASH(uint8_t* pData, int iDataSize, GIF_DRAW_CALLBACK* pfnDraw);
int open(const char *szFilename, GIF_OPEN_CALLBACK *pfnOpen, GIF_CLOSE_CALLBACK *pfnClose, GIF_READ_CALLBACK *pfnRead, GIF_SEEK_CALLBACK *pfnSeek, GIF_DRAW_CALLBACK *pfnDraw); int open(const char* szFilename,
GIF_OPEN_CALLBACK* pfnOpen,
GIF_CLOSE_CALLBACK* pfnClose,
GIF_READ_CALLBACK* pfnRead,
GIF_SEEK_CALLBACK* pfnSeek,
GIF_DRAW_CALLBACK* pfnDraw);
void close(); void close();
void reset(); void reset();
void begin(unsigned char ucPaletteType = GIF_PALETTE_RGB565_LE); void begin(unsigned char ucPaletteType = GIF_PALETTE_RGB565_LE);
void begin(int iEndian, unsigned char ucPaletteType) { begin(ucPaletteType); }; void begin(int iEndian, unsigned char ucPaletteType) {
begin(ucPaletteType);
};
int playFrame(bool bSync, int* delayMilliseconds, void* pUser = NULL); int playFrame(bool bSync, int* delayMilliseconds, void* pUser = NULL);
int getCanvasWidth(); int getCanvasWidth();
int allocFrameBuf(GIF_ALLOC_CALLBACK* pfnAlloc); int allocFrameBuf(GIF_ALLOC_CALLBACK* pfnAlloc);

View File

@@ -7,15 +7,15 @@
#ifndef INC_LCD_API_H_ #ifndef INC_LCD_API_H_
#define INC_LCD_API_H_ #define INC_LCD_API_H_
#include <ctype.h>
#include <stdbool.h> #include <stdbool.h>
#include <string.h> #include <string.h>
#include <ctype.h>
#define LOGGER_LEVEL_ALL #define LOGGER_LEVEL_ALL
#include "log.h"
#include "../../Drivers/BSP/STM32746G-Discovery/stm32746g_discovery_lcd.h" #include "../../Drivers/BSP/STM32746G-Discovery/stm32746g_discovery_lcd.h"
#include "llfs.h"
#include "gifdec.h" #include "gifdec.h"
#include "llfs.h"
#include "log.h"
/** /**
* @brief The maximum amount of GIFs that can be displayed at the same time * @brief The maximum amount of GIFs that can be displayed at the same time
@@ -61,7 +61,6 @@
#define LCD_FONT20 (&Font20) #define LCD_FONT20 (&Font20)
#define LCD_FONT24 (&Font24) #define LCD_FONT24 (&Font24)
extern LTDC_HandleTypeDef hLtdcHandler; extern LTDC_HandleTypeDef hLtdcHandler;
typedef struct { typedef struct {
@@ -121,7 +120,12 @@ void lcd_display_text(const char* text, uint32_t x_pos, uint32_t y_pos, uint32_t
* @param[in] y_size Height of image * @param[in] y_size Height of image
* @param[in] color_mode Color mode (see defined color modes above in file) * @param[in] color_mode Color mode (see defined color modes above in file)
*/ */
void lcd_draw_raw_img(const void* p_src, uint32_t x_pos, uint32_t y_pos, uint32_t x_size, uint32_t y_size, uint32_t color_mode); void lcd_draw_raw_img(const void* p_src,
uint32_t x_pos,
uint32_t y_pos,
uint32_t x_size,
uint32_t y_size,
uint32_t color_mode);
/** /**
* @brief Draw BMP image on screen * @brief Draw BMP image on screen
@@ -187,7 +191,8 @@ void lcd_stop_all_gifs(void);
/** /**
* @brief Draw GIF image on screen from memory * @brief Draw GIF image on screen from memory
* Draw GIF image from memory to the LCD screen at position X, Y * Draw GIF image from memory to the LCD screen at position X, Y
* @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_gif_t handle will be invalid for further use * @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_gif_t
* handle will be invalid for further use
* @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen * @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen
* *
* @param src Pointer to the GIF image data * @param src Pointer to the GIF image data
@@ -201,7 +206,8 @@ lcd_gif_t* lcd_draw_gif(uint8_t* src, size_t size, uint32_t x_pos, uint32_t y_po
/** /**
* @brief Draw GIF image on screen from filesystem * @brief Draw GIF image on screen from filesystem
* Draw GIF image from filesystem to the LCD screen at position X, Y * Draw GIF image from filesystem to the LCD screen at position X, Y
* @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_git_t handle will be invalidated * @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_git_t
* handle will be invalidated
* @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen * @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen
* *
* @param name The filename of the GIF image * @param name The filename of the GIF image
@@ -214,7 +220,8 @@ lcd_gif_t* lcd_draw_gif_from_fs(const char* name, uint32_t x_pos, uint32_t y_pos
/** /**
* @brief Draw GIF image on screen from filesystem * @brief Draw GIF image on screen from filesystem
* Draw GIF image from filesystem to the LCD screen at position X, Y * Draw GIF image from filesystem to the LCD screen at position X, Y
* @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_git_t handle will be invalidated * @warning If the GIF has a loop count specified, it will stop after the specified amount of loops and the lcd_git_t
* handle will be invalidated
* @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen * @note Before drawing over a GIF, make sure to call lcd_stop_gif(), otherwise the GIF will keep overwriting the screen
* *
* @param file The pointer to the llfs_file_t * @param file The pointer to the llfs_file_t

View File

@@ -11,8 +11,8 @@
#ifndef LOG_H #ifndef LOG_H
#define LOG_H #define LOG_H
#include <stdint.h>
#include <errno.h> #include <errno.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/times.h> #include <sys/times.h>
@@ -88,27 +88,37 @@
#endif #endif
#if LOGGER_LEVEL <= 1 #if LOGGER_LEVEL <= 1
#define LOG_DEBUG(tag, fmt, ...) printf(LOG_COLOR_D"[Debug] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__) #define LOG_DEBUG(tag, fmt, ...) \
printf(LOG_COLOR_D "[Debug] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, \
##__VA_ARGS__)
#else #else
#define LOG_DEBUG(tag, fmt, ...) #define LOG_DEBUG(tag, fmt, ...)
#endif #endif
#if LOGGER_LEVEL <= 2 #if LOGGER_LEVEL <= 2
#define LOG_INFO(tag, fmt, ...) printf(LOG_COLOR_I"[Info] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__) #define LOG_INFO(tag, fmt, ...) \
printf(LOG_COLOR_I "[Info] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, \
##__VA_ARGS__)
#else #else
#define LOG_INFO(tag, fmt, ...) #define LOG_INFO(tag, fmt, ...)
#endif #endif
#if LOGGER_LEVEL <= 3 #if LOGGER_LEVEL <= 3
#define LOG_WARN(tag, fmt, ...) printf(LOG_COLOR_W"[Warning] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__) #define LOG_WARN(tag, fmt, ...) \
printf(LOG_COLOR_W "[Warning] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, \
##__VA_ARGS__)
#else #else
#define LOG_WARN(tag, fmt, ...) #define LOG_WARN(tag, fmt, ...)
#endif #endif
#if LOGGER_LEVEL <= 4 #if LOGGER_LEVEL <= 4
#define LOG_CRIT(tag, fmt, ...) printf(LOG_COLOR_C"[Critical] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__) #define LOG_CRIT(tag, fmt, ...) \
printf(LOG_COLOR_C "[Critical] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, \
##__VA_ARGS__)
#else #else
#define LOG_CRIT(tag, fmt, ...) #define LOG_CRIT(tag, fmt, ...)
#endif #endif
#if LOGGER_LEVEL <= 4 #if LOGGER_LEVEL <= 4
#define LOG_FATAL(tag, fmt, ...) printf(LOG_COLOR_F"[Fatal] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, ##__VA_ARGS__) #define LOG_FATAL(tag, fmt, ...) \
printf(LOG_COLOR_F "[Fatal] (%8lu) [%s]: " fmt LOG_RESET_COLOR "\r\n", logger_get_timestamp(), tag, \
##__VA_ARGS__)
#else #else
#define LOG_FATAL(tag, fmt, ...) #define LOG_FATAL(tag, fmt, ...)
#endif #endif

View File

@@ -11,15 +11,13 @@
#define MODBUSPORT 502 // 502 is the default #define MODBUSPORT 502 // 502 is the default
#include <tcp.h>
#include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <tcp.h>
#include "lcd_api.h" #include "lcd_api.h"
#include "llfs.h" #include "llfs.h"
/** /**
* @fn void modbus_init * @fn void modbus_init
* @brief Initializes the modbus tcp * @brief Initializes the modbus tcp

View File

@@ -7,15 +7,13 @@
#ifndef INC_TCP_CMD_H_ #ifndef INC_TCP_CMD_H_
#define INC_TCP_CMD_H_ #define INC_TCP_CMD_H_
#include <stdio.h>
#include <string.h>
#include <tcp.h>
#include "lcd_api.h" #include "lcd_api.h"
#include "llfs.h" #include "llfs.h"
#include "log.h" #include "log.h"
#include <tcp.h>
#include <stdio.h>
#include <string.h>
void tcp_cmd_init(void); void tcp_cmd_init(void);
#endif /* INC_TCP_CMD_H_ */ #endif /* INC_TCP_CMD_H_ */

View File

@@ -0,0 +1,82 @@
/**
* @file website_backend.h
* @brief Backend for the website to operate
* @author Toon B.
*/
#ifndef INC_WEBSITE_BACKEND_
#define INC_WEBSITE_BACKEND_
/* Include headers C lib */
#include <stdint.h>
#include <string.h>
/* Defines */
#define LOGGER_LEVEL_ALL
#define STR_MAX 200
#define CLR_MAX 11
#define IMG_X 0
#define IMG_Y 0
#define SD_IMG "st.bmp"
/* Include headers */
#include "httpd.h"
#include "lcd_api.h"
#include "llfs.h"
#include "log.h"
#include "lwip.h"
#include "lwip/apps/fs.h"
/**
* @fn void wbe_init(void)
* @brief Initialise the http server. It also sets the beginning screen
* of the display.
*/
void wbe_init(void);
/**
* @fn int fs_open_custom(struct fs_file*, const char*)
* @brief Function is called when the frontend wants to reach/open a file
* or endpoint on the backend.
*
* @param[in] file, the file pointer of the file that the frontend wants
* @param[in] name, the name of the file or endpoint that the frontend asks for
* @return[out] returns 0 if file or endpoint was not found, 1 if it was found
*/
int fs_open_custom(struct fs_file* file, const char* name);
/**
* @fn void fs_close_custom(struct fs_file*)
* @brief Called when closing files and endpoints
*
* @param[in] file, the file pointer of the file that the frontend wants
*/
void fs_close_custom(struct fs_file* file);
/**
* @fn void httpd_cgi_handler(struct fs_file*, const char*, int, char**, char**)
* @brief When data is send from the frontend to the backend with the CGI
* tag and parameters, this function is called. With this comes parameters that
* we want to read for further use.
*
* @param[in] file, the file pointer of the file that the frontend wants
* @param[in] uri, the URI that is given to the backend from the frontend (here cgi)
* @param[in] num_parm, the number of parameters that is given with the URI
* @param[in] pc_param, contains the name of each parameter
* @param[in] pc_value, is the value of each parameter
*/
void httpd_cgi_handler(struct fs_file* file, const char* uri, int num_parm, char** pc_param, char** pc_value);
/**
* @fn void wbe_display(const char*, const uint32_t, const uint32_t, const char*)
* @brief Function displays the sentence, its color, the background and the given
* image on the LCD screen.
*
* @param[in] txt, is the text string that needs to be displayed
* @param[in] txt_color, the color of the wanted string
* @param[in] background_color, color of the background of the screen
* @param[in] image, name of the wanted image to be displayed
*/
void wbe_display(const char* txt, const uint32_t txt_color, const uint32_t background_color, const char* image);
#endif /* INC_WEBSITE_BACKEND_ */

View File

@@ -56,13 +56,11 @@ static void udp_broadcast_name_to_lcd(void){
text[UDP_BROADCAST_LCD_TEXT_SIZE - 1] = '\0'; // Make the last a NULL byte text[UDP_BROADCAST_LCD_TEXT_SIZE - 1] = '\0'; // Make the last a NULL byte
lcd_display_text(text, owner_name_x_pos, owner_name_y_pos, LCD_BLACK, LCD_WHITE, LCD_FONT12); lcd_display_text(text, owner_name_x_pos, owner_name_y_pos, LCD_BLACK, LCD_WHITE, LCD_FONT12);
snprintf(text, UDP_BROADCAST_LCD_TEXT_SIZE, "%s%s",UDP_BROADCAST_LCD_NAME_PRE_TEXT, snprintf(text, UDP_BROADCAST_LCD_TEXT_SIZE, "%s%s", UDP_BROADCAST_LCD_NAME_PRE_TEXT, udp_owner.name);
udp_owner.name);
lcd_display_text(text, owner_name_x_pos, owner_name_y_pos, LCD_BLACK, LCD_WHITE, LCD_FONT12); lcd_display_text(text, owner_name_x_pos, owner_name_y_pos, LCD_BLACK, LCD_WHITE, LCD_FONT12);
} }
/** /**
* @fn uint8_t udp_broadcast_set_owner_details_name(owner_details_t*, const char*) * @fn uint8_t udp_broadcast_set_owner_details_name(owner_details_t*, const char*)
* @brief set_owner_details_name() sets the owner's name in the owner_details_t struct * @brief set_owner_details_name() sets the owner's name in the owner_details_t struct
@@ -76,7 +74,6 @@ static void udp_broadcast_name_to_lcd(void){
*/ */
static uint8_t udp_broadcast_set_owner_details_name(const char* name) { static uint8_t udp_broadcast_set_owner_details_name(const char* name) {
if (name == NULL) { if (name == NULL) {
LOG_WARN(TAG, "%s: string given is a NULL pointer", __func__); LOG_WARN(TAG, "%s: string given is a NULL pointer", __func__);
return 1; return 1;
@@ -144,8 +141,8 @@ static void udp_broadcast_format_reply(void) {
udp_owner.mac_address[1], udp_owner.mac_address[2], udp_owner.mac_address[3], udp_owner.mac_address[4], udp_owner.mac_address[1], udp_owner.mac_address[2], udp_owner.mac_address[3], udp_owner.mac_address[4],
udp_owner.mac_address[5]); udp_owner.mac_address[5]);
snprintf(reply_buf, UDP_BROADCAST_MAX_REPLY_SIZE, "%s %s %s %s", mac_addr_str, UDP_BROADCAST_REPLY_MIDDLE_TEXT, udp_owner.surname, snprintf(reply_buf, UDP_BROADCAST_MAX_REPLY_SIZE, "%s %s %s %s", mac_addr_str, UDP_BROADCAST_REPLY_MIDDLE_TEXT,
udp_owner.name); udp_owner.surname, udp_owner.name);
udp_broadcast_set_owner_details_reply(reply_buf); udp_broadcast_set_owner_details_reply(reply_buf);
} }
@@ -163,7 +160,6 @@ static void udp_broadcast_format_reply(void) {
*/ */
err_t udp_broadcast_set_owner_details(const char* name, const char* surname) { err_t udp_broadcast_set_owner_details(const char* name, const char* surname) {
if (!udp_broadcast_set_owner_details_name(name) && !udp_broadcast_set_owner_details_surname(surname)) { if (!udp_broadcast_set_owner_details_name(name) && !udp_broadcast_set_owner_details_surname(surname)) {
// If both return 0 it's okay // If both return 0 it's okay
udp_broadcast_set_owner_details_mac(); udp_broadcast_set_owner_details_mac();
udp_broadcast_format_reply(); udp_broadcast_format_reply();
@@ -245,9 +241,9 @@ static uint8_t udp_broadcast_check_function(const char data[UDP_BROADCAST_MAX_DA
counter++; counter++;
} }
} }
if (enders[2] - enders[1] < UDP_BROADCAST_MAX_NAME_SIZE + 2 && data_len - enders[3] < UDP_BROADCAST_MAX_NAME_SIZE + 2 if (enders[2] - enders[1] < UDP_BROADCAST_MAX_NAME_SIZE + 2
&& strncmp(data + enders[0], ":name", 5) == 0 && strncmp(data + enders[2], ", surname", 9) == 0) { && data_len - enders[3] < UDP_BROADCAST_MAX_NAME_SIZE + 2 && strncmp(data + enders[0], ":name", 5) == 0
&& strncmp(data + enders[2], ", surname", 9) == 0) {
counter = 0; counter = 0;
for (uint8_t i = enders[1] + 2; i < enders[2]; i++) { for (uint8_t i = enders[1] + 2; i < enders[2]; i++) {
buffer[counter] = data[i]; buffer[counter] = data[i];
@@ -336,7 +332,6 @@ static void udp_receive_callback(void* arg,
LOG_INFO(TAG, "%s: tried to reply to %s at port: %d: %s", __func__, source_ip_str, 64000, udp_owner.reply); LOG_INFO(TAG, "%s: tried to reply to %s at port: %d: %s", __func__, source_ip_str, 64000, udp_owner.reply);
} }
defer: defer:
pbuf_free(p); pbuf_free(p);
pbuf_free(p_data); pbuf_free(p_data);
@@ -375,8 +370,6 @@ err_t udp_broadcast_connection_init(void) {
return err; return err;
} }
/** /**
* @fn err_t udp_broadcast_init() * @fn err_t udp_broadcast_init()
* @brief udp_broadcast_init() initializes the owner's variables and calls upon @see udp_broadcast_connection_init() * @brief udp_broadcast_init() initializes the owner's variables and calls upon @see udp_broadcast_connection_init()

View File

@@ -41,8 +41,7 @@ static int32_t seekFile(GIFFILE *pFile, int32_t iPosition);
static void closeFile(void* handle); static void closeFile(void* handle);
// C API // C API
int GIF_openRAM(GIFIMAGE *pGIF, uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK *pfnDraw) int GIF_openRAM(GIFIMAGE* pGIF, uint8_t* pData, int iDataSize, GIF_DRAW_CALLBACK* pfnDraw) {
{
pGIF->iError = GIF_SUCCESS; pGIF->iError = GIF_SUCCESS;
pGIF->pfnRead = readMem; pGIF->pfnRead = readMem;
pGIF->pfnSeek = seekMem; pGIF->pfnSeek = seekMem;
@@ -54,20 +53,17 @@ int GIF_openRAM(GIFIMAGE *pGIF, uint8_t *pData, int iDataSize, GIF_DRAW_CALLBACK
return GIFInit(pGIF); return GIFInit(pGIF);
} /* GIF_openRAM() */ } /* GIF_openRAM() */
void GIF_close(GIFIMAGE *pGIF) void GIF_close(GIFIMAGE* pGIF) {
{
if (pGIF->pfnClose) if (pGIF->pfnClose)
(*pGIF->pfnClose)(pGIF->GIFFile.fHandle); (*pGIF->pfnClose)(pGIF->GIFFile.fHandle);
} /* GIF_close() */ } /* GIF_close() */
void GIF_begin(GIFIMAGE *pGIF, unsigned char ucPaletteType) void GIF_begin(GIFIMAGE* pGIF, unsigned char ucPaletteType) {
{
memset(pGIF, 0, sizeof(GIFIMAGE)); memset(pGIF, 0, sizeof(GIFIMAGE));
pGIF->ucPaletteType = ucPaletteType; pGIF->ucPaletteType = ucPaletteType;
} /* GIF_begin() */ } /* GIF_begin() */
void GIF_reset(GIFIMAGE *pGIF) void GIF_reset(GIFIMAGE* pGIF) {
{
(*pGIF->pfnSeek)(&pGIF->GIFFile, 0); (*pGIF->pfnSeek)(&pGIF->GIFFile, 0);
} /* GIF_reset() */ } /* GIF_reset() */
@@ -77,8 +73,7 @@ void GIF_reset(GIFIMAGE *pGIF)
// 0 = good decode, no more frames // 0 = good decode, no more frames
// -1 = error // -1 = error
// //
int GIF_playFrame(GIFIMAGE *pGIF, int *delayMilliseconds, void *pUser) int GIF_playFrame(GIFIMAGE* pGIF, int* delayMilliseconds, void* pUser) {
{
int rc; int rc;
if (delayMilliseconds) if (delayMilliseconds)
@@ -87,17 +82,14 @@ int GIF_playFrame(GIFIMAGE *pGIF, int *delayMilliseconds, void *pUser)
{ {
(*pGIF->pfnSeek)(&pGIF->GIFFile, 0); // seek to start (*pGIF->pfnSeek)(&pGIF->GIFFile, 0); // seek to start
} }
if (GIFParseInfo(pGIF, 0)) if (GIFParseInfo(pGIF, 0)) {
{
pGIF->pUser = pUser; pGIF->pUser = pUser;
if (pGIF->iError == GIF_EMPTY_FRAME) // don't try to decode it if (pGIF->iError == GIF_EMPTY_FRAME) // don't try to decode it
return 0; return 0;
rc = DecodeLZW(pGIF, 0); rc = DecodeLZW(pGIF, 0);
if (rc != 0) // problem if (rc != 0) // problem
return 0; return 0;
} } else {
else
{
return 0; // error parsing the frame info, we may be at the end of the file return 0; // error parsing the frame info, we may be at the end of the file
} }
// Return 1 for more frames or 0 if this was the last frame // Return 1 for more frames or 0 if this was the last frame
@@ -106,23 +98,19 @@ int GIF_playFrame(GIFIMAGE *pGIF, int *delayMilliseconds, void *pUser)
return (pGIF->GIFFile.iPos < pGIF->GIFFile.iSize - 1); return (pGIF->GIFFile.iPos < pGIF->GIFFile.iSize - 1);
} /* GIF_playFrame() */ } /* GIF_playFrame() */
int GIF_getCanvasWidth(GIFIMAGE *pGIF) int GIF_getCanvasWidth(GIFIMAGE* pGIF) {
{
return pGIF->iCanvasWidth; return pGIF->iCanvasWidth;
} /* GIF_getCanvasWidth() */ } /* GIF_getCanvasWidth() */
int GIF_getCanvasHeight(GIFIMAGE *pGIF) int GIF_getCanvasHeight(GIFIMAGE* pGIF) {
{
return pGIF->iCanvasHeight; return pGIF->iCanvasHeight;
} /* GIF_getCanvasHeight() */ } /* GIF_getCanvasHeight() */
int GIF_getLoopCount(GIFIMAGE *pGIF) int GIF_getLoopCount(GIFIMAGE* pGIF) {
{
return pGIF->iRepeatCount; return pGIF->iRepeatCount;
} /* GIF_getLoopCount() */ } /* GIF_getLoopCount() */
int GIF_getComment(GIFIMAGE *pGIF, char *pDest) int GIF_getComment(GIFIMAGE* pGIF, char* pDest) {
{
int32_t iOldPos; int32_t iOldPos;
iOldPos = pGIF->GIFFile.iPos; // keep old position iOldPos = pGIF->GIFFile.iPos; // keep old position
@@ -134,8 +122,7 @@ int GIF_getComment(GIFIMAGE *pGIF, char *pDest)
} /* GIF_getComment() */ } /* GIF_getComment() */
int GIF_getLastError(GIFIMAGE *pGIF) int GIF_getLastError(GIFIMAGE* pGIF) {
{
return pGIF->iError; return pGIF->iError;
} /* GIF_getLastError() */ } /* GIF_getLastError() */
@@ -143,8 +130,7 @@ int GIF_getLastError(GIFIMAGE *pGIF)
// //
// Helper functions for memory based images // Helper functions for memory based images
// //
static int32_t readMem(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen) static int32_t readMem(GIFFILE* pFile, uint8_t* pBuf, int32_t iLen) {
{
int32_t iBytesRead; int32_t iBytesRead;
iBytesRead = iLen; iBytesRead = iLen;
@@ -157,8 +143,7 @@ static int32_t readMem(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen)
return iBytesRead; return iBytesRead;
} /* readMem() */ } /* readMem() */
static int32_t readFLASH(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen) static int32_t readFLASH(GIFFILE* pFile, uint8_t* pBuf, int32_t iLen) {
{
int32_t iBytesRead; int32_t iBytesRead;
iBytesRead = iLen; iBytesRead = iLen;
@@ -171,31 +156,31 @@ static int32_t readFLASH(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen)
return iBytesRead; return iBytesRead;
} /* readFLASH() */ } /* readFLASH() */
static int32_t seekMem(GIFFILE *pFile, int32_t iPosition) static int32_t seekMem(GIFFILE* pFile, int32_t iPosition) {
{ if (iPosition < 0)
if (iPosition < 0) iPosition = 0; iPosition = 0;
else if (iPosition >= pFile->iSize) iPosition = pFile->iSize-1; else if (iPosition >= pFile->iSize)
iPosition = pFile->iSize - 1;
pFile->iPos = iPosition; pFile->iPos = iPosition;
return iPosition; return iPosition;
} /* seekMem() */ } /* seekMem() */
#if defined(__LINUX__) || defined(__MCUXPRESSO) #if defined(__LINUX__) || defined(__MCUXPRESSO)
static void closeFile(void *handle) static void closeFile(void* handle) {
{
fclose((FILE*)handle); fclose((FILE*)handle);
} /* closeFile() */ } /* closeFile() */
static int32_t seekFile(GIFFILE *pFile, int32_t iPosition) static int32_t seekFile(GIFFILE* pFile, int32_t iPosition) {
{ if (iPosition < 0)
if (iPosition < 0) iPosition = 0; iPosition = 0;
else if (iPosition >= pFile->iSize) iPosition = pFile->iSize-1; else if (iPosition >= pFile->iSize)
iPosition = pFile->iSize - 1;
pFile->iPos = iPosition; pFile->iPos = iPosition;
fseek((FILE*)pFile->fHandle, iPosition, SEEK_SET); fseek((FILE*)pFile->fHandle, iPosition, SEEK_SET);
return iPosition; return iPosition;
} /* seekMem() */ } /* seekMem() */
static int32_t readFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen) static int32_t readFile(GIFFILE* pFile, uint8_t* pBuf, int32_t iLen) {
{
int32_t iBytesRead; int32_t iBytesRead;
iBytesRead = iLen; iBytesRead = iLen;
@@ -218,8 +203,7 @@ static int32_t readFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen)
// returns 1 for success, 0 for failure // returns 1 for success, 0 for failure
// Fills in the canvas size of the GIFIMAGE structure // Fills in the canvas size of the GIFIMAGE structure
// //
static int GIFInit(GIFIMAGE *pGIF) static int GIFInit(GIFIMAGE* pGIF) {
{
pGIF->GIFFile.iPos = 0; // start at beginning of file pGIF->GIFFile.iPos = 0; // start at beginning of file
if (!GIFParseInfo(pGIF, 1)) // gather info for the first frame if (!GIFParseInfo(pGIF, 1)) // gather info for the first frame
return 0; // something went wrong; not a GIF file? return 0; // something went wrong; not a GIF file?
@@ -237,8 +221,7 @@ static int GIFInit(GIFIMAGE *pGIF)
// and return the canvas size only // and return the canvas size only
// Returns 1 for success, 0 for failure // Returns 1 for success, 0 for failure
// //
static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly) static int GIFParseInfo(GIFIMAGE* pPage, int bInfoOnly) {
{
int i, j, iColorTableBits; int i, j, iColorTableBits;
int iBytesRead; int iBytesRead;
unsigned char c, *p; unsigned char c, *p;
@@ -282,10 +265,8 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
{ // by default, convert to byte-reversed RGB565 for immediate use { // by default, convert to byte-reversed RGB565 for immediate use
// Read enough additional data for the color table // Read enough additional data for the color table
iBytesRead += (*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucFileBuf[iBytesRead], 3 * (1 << iColorTableBits)); iBytesRead += (*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucFileBuf[iBytesRead], 3 * (1 << iColorTableBits));
if (pPage->ucPaletteType == GIF_PALETTE_RGB565_LE || pPage->ucPaletteType == GIF_PALETTE_RGB565_BE) if (pPage->ucPaletteType == GIF_PALETTE_RGB565_LE || pPage->ucPaletteType == GIF_PALETTE_RGB565_BE) {
{ for (i = 0; i < (1 << iColorTableBits); i++) {
for (i=0; i<(1<<iColorTableBits); i++)
{
uint16_t usRGB565; uint16_t usRGB565;
usRGB565 = ((p[iOffset] >> 3) << 11); // R usRGB565 = ((p[iOffset] >> 3) << 11); // R
usRGB565 |= ((p[iOffset + 1] >> 2) << 5); // G usRGB565 |= ((p[iOffset + 1] >> 2) << 5); // G
@@ -296,8 +277,7 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
pPage->pPalette[i] = __builtin_bswap16(usRGB565); // SPI wants MSB first pPage->pPalette[i] = __builtin_bswap16(usRGB565); // SPI wants MSB first
iOffset += 3; iOffset += 3;
} }
} } else // just copy it as-is
else // just copy it as-is
{ {
memcpy(pPage->pPalette, &p[iOffset], (1 << iColorTableBits) * 3); memcpy(pPage->pPalette, &p[iOffset], (1 << iColorTableBits) * 3);
iOffset += (1 << iColorTableBits) * 3; iOffset += (1 << iColorTableBits) * 3;
@@ -316,7 +296,8 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
{ {
pPage->ucGIFBits = p[iOffset + 1]; // packed fields pPage->ucGIFBits = p[iOffset + 1]; // packed fields
pPage->iFrameDelay = (INTELSHORT(&p[iOffset + 2])) * 10; // delay in ms pPage->iFrameDelay = (INTELSHORT(&p[iOffset + 2])) * 10; // delay in ms
if (pPage->iFrameDelay <= 1) // 0-1 is going to make it run at 60fps; use 100 (10fps) as a reasonable substitute if (pPage->iFrameDelay
<= 1) // 0-1 is going to make it run at 60fps; use 100 (10fps) as a reasonable substitute
pPage->iFrameDelay = 100; pPage->iFrameDelay = 100;
if (pPage->ucGIFBits & 1) // transparent color is used if (pPage->ucGIFBits & 1) // transparent color is used
pPage->ucTransparent = p[iOffset + 4]; // transparent color index pPage->ucTransparent = p[iOffset + 4]; // transparent color index
@@ -331,7 +312,8 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
c = p[iOffset++]; /* Block length */ c = p[iOffset++]; /* Block length */
if ((iBytesRead - iOffset) < (c + 32)) // need to read more data first if ((iBytesRead - iOffset) < (c + 32)) // need to read more data first
{ {
memmove(pPage->ucFileBuf, &pPage->ucFileBuf[iOffset], (iBytesRead-iOffset)); // move existing data down memmove(pPage->ucFileBuf, &pPage->ucFileBuf[iOffset],
(iBytesRead - iOffset)); // move existing data down
iBytesRead -= iOffset; iBytesRead -= iOffset;
iStartPos += iOffset; iStartPos += iOffset;
iOffset = 0; iOffset = 0;
@@ -339,8 +321,7 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
} }
if (c == 11) // fixed block length if (c == 11) // fixed block length
{ // Netscape app block contains the repeat count { // Netscape app block contains the repeat count
if (memcmp(&p[iOffset], "NETSCAPE2.0", 11) == 0) if (memcmp(&p[iOffset], "NETSCAPE2.0", 11) == 0) {
{
if (p[iOffset + 11] == 3 && p[iOffset + 12] == 1) // loop count if (p[iOffset + 11] == 3 && p[iOffset + 12] == 1) // loop count
pPage->iRepeatCount = INTELSHORT(&p[iOffset + 13]); pPage->iRepeatCount = INTELSHORT(&p[iOffset + 13]);
} }
@@ -373,7 +354,8 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
c = p[iOffset++]; /* Block length */ c = p[iOffset++]; /* Block length */
if ((iBytesRead - iOffset) < (c + 32)) // need to read more data first if ((iBytesRead - iOffset) < (c + 32)) // need to read more data first
{ {
memmove(pPage->ucFileBuf, &pPage->ucFileBuf[iOffset], (iBytesRead-iOffset)); // move existing data down memmove(pPage->ucFileBuf, &pPage->ucFileBuf[iOffset],
(iBytesRead - iOffset)); // move existing data down
iBytesRead -= iOffset; iBytesRead -= iOffset;
iStartPos += iOffset; iStartPos += iOffset;
iOffset = 0; iOffset = 0;
@@ -392,8 +374,7 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
pPage->iError = GIF_DECODE_ERROR; pPage->iError = GIF_DECODE_ERROR;
return 0; return 0;
} /* switch */ } /* switch */
} } else // invalid byte, stop decoding
else // invalid byte, stop decoding
{ {
if (pPage->GIFFile.iSize - iStartPos < 32) // non-image bytes at end of file? if (pPage->GIFFile.iSize - iStartPos < 32) // non-image bytes at end of file?
pPage->iError = GIF_EMPTY_FRAME; pPage->iError = GIF_EMPTY_FRAME;
@@ -430,10 +411,8 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
j = (1 << ((pPage->ucMap & 7) + 1)); j = (1 << ((pPage->ucMap & 7) + 1));
// Read enough additional data for the color table // Read enough additional data for the color table
iBytesRead += (*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucFileBuf[iBytesRead], j * 3); iBytesRead += (*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucFileBuf[iBytesRead], j * 3);
if (pPage->ucPaletteType == GIF_PALETTE_RGB565_LE || pPage->ucPaletteType == GIF_PALETTE_RGB565_BE) if (pPage->ucPaletteType == GIF_PALETTE_RGB565_LE || pPage->ucPaletteType == GIF_PALETTE_RGB565_BE) {
{ for (i = 0; i < j; i++) {
for (i=0; i<j; i++)
{
uint16_t usRGB565; uint16_t usRGB565;
usRGB565 = ((p[iOffset] >> 3) << 11); // R usRGB565 = ((p[iOffset] >> 3) << 11); // R
usRGB565 |= ((p[iOffset + 1] >> 2) << 5); // G usRGB565 |= ((p[iOffset + 1] >> 2) << 5); // G
@@ -444,8 +423,7 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
pPage->pLocalPalette[i] = __builtin_bswap16(usRGB565); // SPI wants MSB first pPage->pLocalPalette[i] = __builtin_bswap16(usRGB565); // SPI wants MSB first
iOffset += 3; iOffset += 3;
} }
} } else // just copy it as-is
else // just copy it as-is
{ {
memcpy(pPage->pLocalPalette, &p[iOffset], j * 3); memcpy(pPage->pLocalPalette, &p[iOffset], j * 3);
iOffset += j * 3; iOffset += j * 3;
@@ -459,18 +437,15 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
// into "pure" LZW // into "pure" LZW
pPage->iLZWSize = 0; // we're starting with no LZW data yet pPage->iLZWSize = 0; // we're starting with no LZW data yet
c = 1; // get chunk length c = 1; // get chunk length
while (c && iOffset < iBytesRead) while (c && iOffset < iBytesRead) {
{
// Serial.printf("iOffset=%d, iBytesRead=%d\n", iOffset, iBytesRead); // Serial.printf("iOffset=%d, iBytesRead=%d\n", iOffset, iBytesRead);
c = p[iOffset++]; // get chunk length c = p[iOffset++]; // get chunk length
// Serial.printf("Chunk size = %d\n", c); // Serial.printf("Chunk size = %d\n", c);
if (c <= (iBytesRead - iOffset)) if (c <= (iBytesRead - iOffset)) {
{
memcpy(&pPage->ucLZW[pPage->iLZWSize], &p[iOffset], c); memcpy(&pPage->ucLZW[pPage->iLZWSize], &p[iOffset], c);
pPage->iLZWSize += c; pPage->iLZWSize += c;
iOffset += c; iOffset += c;
} } else // partial chunk in our buffer
else // partial chunk in our buffer
{ {
int iPartialLen = (iBytesRead - iOffset); int iPartialLen = (iBytesRead - iOffset);
memcpy(&pPage->ucLZW[pPage->iLZWSize], &p[iOffset], iPartialLen); memcpy(&pPage->ucLZW[pPage->iLZWSize], &p[iOffset], iPartialLen);
@@ -484,8 +459,7 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
} }
// seeking on an SD card is VERY VERY SLOW, so use the data we've already read by de-chunking it // seeking on an SD card is VERY VERY SLOW, so use the data we've already read by de-chunking it
// in this case, there's too much data, so we have to seek backwards a bit // in this case, there's too much data, so we have to seek backwards a bit
if (iOffset < iBytesRead) if (iOffset < iBytesRead) {
{
// Serial.printf("Need to seek back %d bytes\n", iBytesRead - iOffset); // Serial.printf("Need to seek back %d bytes\n", iBytesRead - iOffset);
(*pPage->pfnSeek)(&pPage->GIFFile, iStartPos + iOffset); // position file to new spot (*pPage->pfnSeek)(&pPage->GIFFile, iStartPos + iOffset); // position file to new spot
} }
@@ -494,8 +468,7 @@ static int GIFParseInfo(GIFIMAGE *pPage, int bInfoOnly)
// //
// Gather info about an animated GIF file // Gather info about an animated GIF file
// //
int GIF_getInfo(GIFIMAGE *pPage, GIFINFO *pInfo) int GIF_getInfo(GIFIMAGE* pPage, GIFINFO* pInfo) {
{
int iOff, iNumFrames; int iOff, iNumFrames;
int iDelay, iMaxDelay, iMinDelay, iTotalDelay; int iDelay, iMaxDelay, iMinDelay, iTotalDelay;
int iReadAmount; int iReadAmount;
@@ -526,8 +499,7 @@ int GIF_getInfo(GIFIMAGE *pPage, GIFINFO *pInfo)
while (!bDone) // && iNumFrames < MAX_FRAMES) while (!bDone) // && iNumFrames < MAX_FRAMES)
{ {
bExt = 1; /* skip extension blocks */ bExt = 1; /* skip extension blocks */
while (bExt && iOff < iDataAvailable) while (bExt && iOff < iDataAvailable) {
{
if ((iDataAvailable - iOff) < 258) // need to read more data first if ((iDataAvailable - iOff) < 258) // need to read more data first
{ {
memmove(cBuf, &cBuf[iOff], (iDataAvailable - iOff)); // move existing data down memmove(cBuf, &cBuf[iOff], (iDataAvailable - iOff)); // move existing data down
@@ -538,8 +510,7 @@ int GIF_getInfo(GIFIMAGE *pPage, GIFINFO *pInfo)
iDataRemaining -= iReadAmount; iDataRemaining -= iReadAmount;
// lFileOff += iReadAmount; // lFileOff += iReadAmount;
} }
switch(cBuf[iOff]) switch (cBuf[iOff]) {
{
case 0x3b: /* End of file */ case 0x3b: /* End of file */
/* we were fooled into thinking there were more pages */ /* we were fooled into thinking there were more pages */
iNumFrames--; iNumFrames--;
@@ -558,8 +529,10 @@ int GIF_getInfo(GIFIMAGE *pPage, GIFINFO *pInfo)
iDelay = 2; iDelay = 2;
iDelay *= 10; // turn JIFFIES into milliseconds iDelay *= 10; // turn JIFFIES into milliseconds
iTotalDelay += iDelay; iTotalDelay += iDelay;
if (iDelay > iMaxDelay) iMaxDelay = iDelay; if (iDelay > iMaxDelay)
else if (iDelay < iMinDelay) iMinDelay = iDelay; iMaxDelay = iDelay;
else if (iDelay < iMinDelay)
iMinDelay = iDelay;
// (cBuf[iOff+6]; // transparent color index // (cBuf[iOff+6]; // transparent color index
} }
iOff += 2; /* skip to length */ iOff += 2; /* skip to length */
@@ -567,8 +540,7 @@ int GIF_getInfo(GIFIMAGE *pPage, GIFINFO *pInfo)
iOff++; iOff++;
// block terminator or optional sub blocks // block terminator or optional sub blocks
c = cBuf[iOff++]; /* Skip any sub-blocks */ c = cBuf[iOff++]; /* Skip any sub-blocks */
while (c) while (c) {
{
iOff += (int)c; iOff += (int)c;
c = cBuf[iOff++]; c = cBuf[iOff++];
if ((iDataAvailable - iOff) < (c + 258)) // need to read more data first if ((iDataAvailable - iOff) < (c + 258)) // need to read more data first
@@ -576,7 +548,8 @@ int GIF_getInfo(GIFIMAGE *pPage, GIFINFO *pInfo)
memmove(cBuf, &cBuf[iOff], (iDataAvailable - iOff)); // move existing data down memmove(cBuf, &cBuf[iOff], (iDataAvailable - iOff)); // move existing data down
iDataAvailable -= iOff; iDataAvailable -= iOff;
iOff = 0; iOff = 0;
iReadAmount = (*pPage->pfnRead)(&pPage->GIFFile, &cBuf[iDataAvailable], FILE_BUF_SIZE-iDataAvailable); iReadAmount = (*pPage->pfnRead)(&pPage->GIFFile, &cBuf[iDataAvailable],
FILE_BUF_SIZE - iDataAvailable);
iDataAvailable += iReadAmount; iDataAvailable += iReadAmount;
iDataRemaining -= iReadAmount; iDataRemaining -= iReadAmount;
// lFileOff += iReadAmount; // lFileOff += iReadAmount;
@@ -651,15 +624,14 @@ int GIF_getInfo(GIFIMAGE *pPage, GIFINFO *pInfo)
c = cBuf[iOff++]; /* Get length of next */ c = cBuf[iOff++]; /* Get length of next */
} }
/* End of image data, check for more pages... */ /* End of image data, check for more pages... */
if (cBuf[iOff] == 0x3b || (iDataRemaining == 0 && (iDataAvailable - iOff) < 32)) if (cBuf[iOff] == 0x3b || (iDataRemaining == 0 && (iDataAvailable - iOff) < 32)) {
{
bDone = 1; /* End of file has been reached */ bDone = 1; /* End of file has been reached */
} } else /* More pages to scan */
else /* More pages to scan */
{ {
iNumFrames++; iNumFrames++;
// read new page data starting at this offset // read new page data starting at this offset
if (pPage->GIFFile.iSize > FILE_BUF_SIZE && iDataRemaining > 0) // since we didn't read the whole file in one shot if (pPage->GIFFile.iSize > FILE_BUF_SIZE
&& iDataRemaining > 0) // since we didn't read the whole file in one shot
{ {
memmove(cBuf, &cBuf[iOff], (iDataAvailable - iOff)); // move existing data down memmove(cBuf, &cBuf[iOff], (iDataAvailable - iOff)); // move existing data down
iDataAvailable -= iOff; iDataAvailable -= iOff;
@@ -687,15 +659,13 @@ gifpagesz:
// returns 1 to signify more data available for this image // returns 1 to signify more data available for this image
// 0 indicates there is no more data // 0 indicates there is no more data
// //
static int GIFGetMoreData(GIFIMAGE *pPage) static int GIFGetMoreData(GIFIMAGE* pPage) {
{
int iDelta = (pPage->iLZWSize - pPage->iLZWOff); int iDelta = (pPage->iLZWSize - pPage->iLZWOff);
unsigned char c = 1; unsigned char c = 1;
// move any existing data down // move any existing data down
if (pPage->bEndOfFrame || iDelta >= (LZW_BUF_SIZE - MAX_CHUNK_SIZE) || iDelta <= 0) if (pPage->bEndOfFrame || iDelta >= (LZW_BUF_SIZE - MAX_CHUNK_SIZE) || iDelta <= 0)
return 1; // frame is finished or buffer is already full; no need to read more data return 1; // frame is finished or buffer is already full; no need to read more data
if (pPage->iLZWOff != 0) if (pPage->iLZWOff != 0) {
{
// NB: memcpy() fails on some systems because the src and dest ptrs overlap // NB: memcpy() fails on some systems because the src and dest ptrs overlap
// so copy the bytes in a simple loop to avoid problems // so copy the bytes in a simple loop to avoid problems
for (int i = 0; i < pPage->iLZWSize - pPage->iLZWOff; i++) { for (int i = 0; i < pPage->iLZWSize - pPage->iLZWOff; i++) {
@@ -704,8 +674,7 @@ static int GIFGetMoreData(GIFIMAGE *pPage)
pPage->iLZWSize -= pPage->iLZWOff; pPage->iLZWSize -= pPage->iLZWOff;
pPage->iLZWOff = 0; pPage->iLZWOff = 0;
} }
while (c && pPage->GIFFile.iPos < pPage->GIFFile.iSize && pPage->iLZWSize < (LZW_BUF_SIZE-MAX_CHUNK_SIZE)) while (c && pPage->GIFFile.iPos < pPage->GIFFile.iSize && pPage->iLZWSize < (LZW_BUF_SIZE - MAX_CHUNK_SIZE)) {
{
(*pPage->pfnRead)(&pPage->GIFFile, &c, 1); // current length (*pPage->pfnRead)(&pPage->GIFFile, &c, 1); // current length
(*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucLZW[pPage->iLZWSize], c); (*pPage->pfnRead)(&pPage->GIFFile, &pPage->ucLZW[pPage->iLZWSize], c);
pPage->iLZWSize += c; pPage->iLZWSize += c;
@@ -718,8 +687,7 @@ static int GIFGetMoreData(GIFIMAGE *pPage)
// Handle transparent pixels and disposal method // Handle transparent pixels and disposal method
// Used only when a frame buffer is allocated // Used only when a frame buffer is allocated
// //
static void DrawNewPixels(GIFIMAGE *pPage, GIFDRAW *pDraw) static void DrawNewPixels(GIFIMAGE* pPage, GIFDRAW* pDraw) {
{
uint8_t *d, *s; uint8_t *d, *s;
int x, iPitch = pPage->iCanvasWidth; int x, iPitch = pPage->iCanvasWidth;
@@ -733,16 +701,13 @@ static void DrawNewPixels(GIFIMAGE *pPage, GIFDRAW *pDraw)
if (pDraw->ucHasTransparency) // if transparency used if (pDraw->ucHasTransparency) // if transparency used
{ {
uint8_t c, ucTransparent = pDraw->ucTransparent; uint8_t c, ucTransparent = pDraw->ucTransparent;
for (x=0; x<pDraw->iWidth; x++) for (x = 0; x < pDraw->iWidth; x++) {
{
c = *s++; c = *s++;
if (c != ucTransparent) if (c != ucTransparent)
*d = c; *d = c;
d++; d++;
} }
} } else {
else
{
memcpy(d, s, pDraw->iWidth); // just overwrite the old pixels memcpy(d, s, pDraw->iWidth); // just overwrite the old pixels
} }
} /* DrawNewPixels() */ } /* DrawNewPixels() */
@@ -751,30 +716,24 @@ static void DrawNewPixels(GIFIMAGE *pPage, GIFDRAW *pDraw)
// to either RGB565 or RGB888 output // to either RGB565 or RGB888 output
// Used only when a frame buffer has been allocated // Used only when a frame buffer has been allocated
// //
static void ConvertNewPixels(GIFIMAGE *pPage, GIFDRAW *pDraw) static void ConvertNewPixels(GIFIMAGE* pPage, GIFDRAW* pDraw) {
{
uint8_t *d, *s; uint8_t *d, *s;
int x; int x;
s = &pPage->pFrameBuffer[(pPage->iCanvasWidth * (pDraw->iY + pDraw->y)) + pDraw->iX]; s = &pPage->pFrameBuffer[(pPage->iCanvasWidth * (pDraw->iY + pDraw->y)) + pDraw->iX];
d = &pPage->pFrameBuffer[pPage->iCanvasHeight * pPage->iCanvasWidth]; // point past bottom of frame buffer d = &pPage->pFrameBuffer[pPage->iCanvasHeight * pPage->iCanvasWidth]; // point past bottom of frame buffer
if (pPage->ucPaletteType == GIF_PALETTE_RGB565_LE || pPage->ucPaletteType == GIF_PALETTE_RGB565_BE) if (pPage->ucPaletteType == GIF_PALETTE_RGB565_LE || pPage->ucPaletteType == GIF_PALETTE_RGB565_BE) {
{
uint16_t *pPal, *pu16; uint16_t *pPal, *pu16;
pPal = (uint16_t*)pDraw->pPalette; pPal = (uint16_t*)pDraw->pPalette;
pu16 = (uint16_t*)d; pu16 = (uint16_t*)d;
for (x=0; x<pPage->iWidth; x++) for (x = 0; x < pPage->iWidth; x++) {
{
*pu16++ = pPal[*s++]; // convert to RGB565 pixels *pu16++ = pPal[*s++]; // convert to RGB565 pixels
} }
} } else {
else
{
uint8_t* pPal; uint8_t* pPal;
int pixel; int pixel;
pPal = (uint8_t*)pDraw->pPalette; pPal = (uint8_t*)pDraw->pPalette;
for (x=0; x<pPage->iWidth; x++) for (x = 0; x < pPage->iWidth; x++) {
{
pixel = *s++; pixel = *s++;
*d++ = pPal[(pixel * 3) + 0]; // convert to RGB888 pixels *d++ = pPal[(pixel * 3) + 0]; // convert to RGB888 pixels
*d++ = pPal[(pixel * 3) + 1]; *d++ = pPal[(pixel * 3) + 1];
@@ -786,8 +745,7 @@ static void ConvertNewPixels(GIFIMAGE *pPage, GIFDRAW *pDraw)
// //
// GIFMakePels // GIFMakePels
// //
static void GIFMakePels(GIFIMAGE *pPage, unsigned int code) static void GIFMakePels(GIFIMAGE* pPage, unsigned int code) {
{
int iPixCount; int iPixCount;
unsigned short* giftabs; unsigned short* giftabs;
unsigned char *buf, *s, *pEnd, *gifpels; unsigned char *buf, *s, *pEnd, *gifpels;
@@ -798,8 +756,7 @@ static void GIFMakePels(GIFIMAGE *pPage, unsigned int code)
buf = pPage->ucLineBuf + (pPage->iWidth - pPage->iXCount); buf = pPage->ucLineBuf + (pPage->iWidth - pPage->iXCount);
giftabs = pPage->usGIFTable; giftabs = pPage->usGIFTable;
gifpels = &pPage->ucGIFPixels[PIXEL_LAST]; gifpels = &pPage->ucGIFPixels[PIXEL_LAST];
while (code < LINK_UNUSED) while (code < LINK_UNUSED) {
{
if (s == pPage->ucFileBuf) /* Houston, we have a problem */ if (s == pPage->ucFileBuf) /* Houston, we have a problem */
{ {
return; /* Exit with error */ return; /* Exit with error */
@@ -809,15 +766,13 @@ static void GIFMakePels(GIFIMAGE *pPage, unsigned int code)
} }
iPixCount = (int)(intptr_t)(pPage->ucFileBuf + FILE_BUF_SIZE - s); iPixCount = (int)(intptr_t)(pPage->ucFileBuf + FILE_BUF_SIZE - s);
while (iPixCount && pPage->iYCount > 0) while (iPixCount && pPage->iYCount > 0) {
{
if (pPage->iXCount > iPixCount) /* Pixels fit completely on the line */ if (pPage->iXCount > iPixCount) /* Pixels fit completely on the line */
{ {
// memcpy(buf, s, iPixCount); // memcpy(buf, s, iPixCount);
// buf += iPixCount; // buf += iPixCount;
pEnd = buf + iPixCount; pEnd = buf + iPixCount;
while (buf < pEnd) while (buf < pEnd) {
{
*buf++ = *s++; *buf++ = *s++;
} }
pPage->iXCount -= iPixCount; pPage->iXCount -= iPixCount;
@@ -825,13 +780,11 @@ static void GIFMakePels(GIFIMAGE *pPage, unsigned int code)
if (ucNeedMore) if (ucNeedMore)
GIFGetMoreData(pPage); // check if we need to read more LZW data every 4 lines GIFGetMoreData(pPage); // check if we need to read more LZW data every 4 lines
return; return;
} } else /* Pixels cross into next line */
else /* Pixels cross into next line */
{ {
GIFDRAW gd; GIFDRAW gd;
pEnd = buf + pPage->iXCount; pEnd = buf + pPage->iXCount;
while (buf < pEnd) while (buf < pEnd) {
{
*buf++ = *s++; *buf++ = *s++;
} }
iPixCount -= pPage->iXCount; iPixCount -= pPage->iXCount;
@@ -867,8 +820,7 @@ static void GIFMakePels(GIFIMAGE *pPage, unsigned int code)
if (pPage->pFrameBuffer) // update the frame buffer if (pPage->pFrameBuffer) // update the frame buffer
{ {
DrawNewPixels(pPage, &gd); DrawNewPixels(pPage, &gd);
if (pPage->ucDrawType == GIF_DRAW_COOKED) if (pPage->ucDrawType == GIF_DRAW_COOKED) {
{
ConvertNewPixels(pPage, &gd); // prepare for output ConvertNewPixels(pPage, &gd); // prepare for output
gd.pPixels = &pPage->pFrameBuffer[pPage->iCanvasWidth * pPage->iCanvasHeight]; gd.pPixels = &pPage->pFrameBuffer[pPage->iCanvasWidth * pPage->iCanvasHeight];
} }
@@ -887,16 +839,20 @@ static void GIFMakePels(GIFIMAGE *pPage, unsigned int code)
// //
// Macro to extract a variable length code // Macro to extract a variable length code
// //
#define GET_CODE if (bitnum > (REGISTER_WIDTH - codesize)) { pImage->iLZWOff += (bitnum >> 3); \ #define GET_CODE \
bitnum &= 7; ulBits = INTELLONG(&p[pImage->iLZWOff]); } \ if (bitnum > (REGISTER_WIDTH - codesize)) { \
pImage->iLZWOff += (bitnum >> 3); \
bitnum &= 7; \
ulBits = INTELLONG(&p[pImage->iLZWOff]); \
} \
code = (unsigned short)(ulBits >> bitnum); /* Read a 32-bit chunk */ \ code = (unsigned short)(ulBits >> bitnum); /* Read a 32-bit chunk */ \
code &= sMask; bitnum += codesize; code &= sMask; \
bitnum += codesize;
// //
// Decode LZW into an image // Decode LZW into an image
// //
static int DecodeLZW(GIFIMAGE *pImage, int iOptions) static int DecodeLZW(GIFIMAGE* pImage, int iOptions) {
{
int i, bitnum; int i, bitnum;
unsigned short oldcode, codesize, nextcode, nextlim; unsigned short oldcode, codesize, nextcode, nextlim;
unsigned short *giftabs, cc, eoi; unsigned short *giftabs, cc, eoi;
@@ -925,8 +881,7 @@ static int DecodeLZW(GIFIMAGE *pImage, int iOptions)
// Initialize code table // Initialize code table
// this part only needs to be initialized once // this part only needs to be initialized once
for (i = 0; i < cc; i++) for (i = 0; i < cc; i++) {
{
gifpels[PIXEL_FIRST + i] = gifpels[PIXEL_LAST + i] = (unsigned short)i; gifpels[PIXEL_FIRST + i] = gifpels[PIXEL_LAST + i] = (unsigned short)i;
giftabs[i] = LINK_END; giftabs[i] = LINK_END;
} }
@@ -947,13 +902,13 @@ init_codetable:
oldcode = code; oldcode = code;
GIFMakePels(pImage, code); // first code is output as the first pixel GIFMakePels(pImage, code); // first code is output as the first pixel
// Main decode loop // Main decode loop
while (code != eoi && pImage->iYCount > 0) // && y < pImage->iHeight+1) /* Loop through all lines of the image (or strip) */ while (code != eoi
&& pImage->iYCount > 0) // && y < pImage->iHeight+1) /* Loop through all lines of the image (or strip) */
{ {
GET_CODE GET_CODE
if (code == cc) /* Clear code?, and not first code */ if (code == cc) /* Clear code?, and not first code */
goto init_codetable; goto init_codetable;
if (code != eoi) if (code != eoi) {
{
if (nextcode < nextlim) // for deferred cc case, don't let it overwrite the last entry (fff) if (nextcode < nextlim) // for deferred cc case, don't let it overwrite the last entry (fff)
{ {
giftabs[nextcode] = oldcode; giftabs[nextcode] = oldcode;
@@ -964,8 +919,7 @@ init_codetable:
gifpels[PIXEL_LAST + nextcode] = gifpels[PIXEL_FIRST + code]; gifpels[PIXEL_LAST + nextcode] = gifpels[PIXEL_FIRST + code];
} }
nextcode++; nextcode++;
if (nextcode >= nextlim && codesize < MAX_CODE_SIZE) if (nextcode >= nextlim && codesize < MAX_CODE_SIZE) {
{
codesize++; codesize++;
nextlim <<= 1; nextlim <<= 1;
sMask = (sMask << 1) | 1; sMask = (sMask << 1) | 1;
@@ -981,8 +935,7 @@ init_codetable:
// return -1; // return -1;
} /* DecodeLZW() */ } /* DecodeLZW() */
void GIF_setDrawCallback(GIFIMAGE *pGIF, GIF_DRAW_CALLBACK *pfnDraw) void GIF_setDrawCallback(GIFIMAGE* pGIF, GIF_DRAW_CALLBACK* pfnDraw) {
{
pGIF->pfnDraw = pfnDraw; pGIF->pfnDraw = pfnDraw;
} /* GIF_setDrawCallback() */ } /* GIF_setDrawCallback() */
// //
@@ -990,18 +943,19 @@ void GIF_setDrawCallback(GIFIMAGE *pGIF, GIF_DRAW_CALLBACK *pfnDraw)
// writes new values over previous line // writes new values over previous line
// expects RGB565 little endian pixels as input // expects RGB565 little endian pixels as input
// //
void GIF_scaleHalf(uint16_t *pCurrent, uint16_t *pPrev, int iWidth, int bBigEndian) void GIF_scaleHalf(uint16_t* pCurrent, uint16_t* pPrev, int iWidth, int bBigEndian) {
{
int x; int x;
uint16_t* d = pPrev; uint16_t* d = pPrev;
uint32_t gSum, rbSum, pix0, pix1, pix2, pix3; uint32_t gSum, rbSum, pix0, pix1, pix2, pix3;
const uint32_t RBMask = 0xf81f, GMask = 0x7e0; const uint32_t RBMask = 0xf81f, GMask = 0x7e0;
for (x=0; x<iWidth; x+=2) for (x = 0; x < iWidth; x += 2) {
{ pix0 = pCurrent[0];
pix0 = pCurrent[0]; pix1 = pCurrent[1]; pix1 = pCurrent[1];
pix2 = pPrev[0]; pix3 = pPrev[1]; pix2 = pPrev[0];
pCurrent += 2; pPrev += 2; pix3 = pPrev[1];
pCurrent += 2;
pPrev += 2;
gSum = (pix0 & GMask) + (pix1 & GMask) + (pix2 & GMask) + (pix3 & GMask); gSum = (pix0 & GMask) + (pix1 & GMask) + (pix2 & GMask) + (pix3 & GMask);
gSum = ((gSum + 0x40) >> 2) & GMask; // for rounding towards 1 gSum = ((gSum + 0x40) >> 2) & GMask; // for rounding towards 1
rbSum = (pix0 & RBMask) + (pix1 & RBMask) + (pix2 & RBMask) + (pix3 & RBMask); rbSum = (pix0 & RBMask) + (pix1 & RBMask) + (pix2 & RBMask) + (pix3 & RBMask);

View File

@@ -8,7 +8,6 @@
#include "lcd_api.h" #include "lcd_api.h"
static const char* TAG = "lcd_api"; static const char* TAG = "lcd_api";
static DMA2D_HandleTypeDef hDma2dHandler2; static DMA2D_HandleTypeDef hDma2dHandler2;
@@ -85,7 +84,12 @@ void lcd_task(void) {
} }
} }
void lcd_display_text(const char* text, uint32_t x_pos, uint32_t y_pos, uint32_t color, uint32_t bg_color, sFONT* font) { void lcd_display_text(const char* text,
uint32_t x_pos,
uint32_t y_pos,
uint32_t color,
uint32_t bg_color,
sFONT* font) {
BSP_LCD_SelectLayer(1); BSP_LCD_SelectLayer(1);
LOG_INFO(TAG, "Display text: %s @x=%d,y=%d", text, x_pos, y_pos); LOG_INFO(TAG, "Display text: %s @x=%d,y=%d", text, x_pos, y_pos);
@@ -118,7 +122,12 @@ void lcd_display_text(const char* text, uint32_t x_pos, uint32_t y_pos, uint32_t
BSP_LCD_DisplayStringAt(x_pos, y_pos, (uint8_t*)text, LEFT_MODE); BSP_LCD_DisplayStringAt(x_pos, y_pos, (uint8_t*)text, LEFT_MODE);
} }
void lcd_draw_raw_img(const void* p_src, uint32_t x_pos, uint32_t y_pos, uint32_t x_size, uint32_t y_size, uint32_t color_mode) { void lcd_draw_raw_img(const void* p_src,
uint32_t x_pos,
uint32_t y_pos,
uint32_t x_size,
uint32_t y_size,
uint32_t color_mode) {
LOG_INFO(TAG, "Displaying raw image: @x=%lu, @y=%lu, width=%lu, height=%lu", x_pos, y_pos, x_size, y_size); LOG_INFO(TAG, "Displaying raw image: @x=%lu, @y=%lu, width=%lu, height=%lu", x_pos, y_pos, x_size, y_size);
BSP_LCD_SelectLayer(0); BSP_LCD_SelectLayer(0);
uint32_t address = hLtdcHandler.LayerCfg[1].FBStartAdress + (((BSP_LCD_GetXSize() * y_pos) + x_pos) * (4)); uint32_t address = hLtdcHandler.LayerCfg[1].FBStartAdress + (((BSP_LCD_GetXSize() * y_pos) + x_pos) * (4));

View File

@@ -10,8 +10,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#define LOGGER_LEVEL_WARN #define LOGGER_LEVEL_WARN
#include "log.h"
#include "llfs.h" #include "llfs.h"
#include "log.h"
/** /**
* @brief The maximum number of files that can be opened concurrently using the POSIX API * @brief The maximum number of files that can be opened concurrently using the POSIX API
@@ -442,4 +442,3 @@ static uint8_t file_ext_cmp(const char* const filename, const char* const ext) {
} }
return 1; return 1;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -7,8 +7,8 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include "stm32f7xx_hal.h"
#include "log.h" #include "log.h"
#include "stm32f7xx_hal.h"
extern UART_HandleTypeDef huart1; extern UART_HandleTypeDef huart1;

View File

@@ -33,6 +33,7 @@
#include "modbus_tcp.h" #include "modbus_tcp.h"
#include "UDP_broadcast.h" #include "UDP_broadcast.h"
#include "tcp_cmd.h" #include "tcp_cmd.h"
#include "website_backend.h"
/* USER CODE END Includes */ /* USER CODE END Includes */
@@ -88,8 +89,7 @@ static void MX_QUADSPI_Init(void);
* @brief The application entry point. * @brief The application entry point.
* @retval int * @retval int
*/ */
int main(void) int main(void) {
{
/* USER CODE BEGIN 1 */ /* USER CODE BEGIN 1 */
/* USER CODE END 1 */ /* USER CODE END 1 */
@@ -149,18 +149,21 @@ int main(void)
// Initialize the UDP broadcast service // Initialize the UDP broadcast service
if (udp_broadcast_init(10, 255) != ERR_OK) { if (udp_broadcast_init(10, 255) != ERR_OK) {
LOG_WARN(TAG,"error initializing udp connection, check warnings from udp_broadcast_init() or udp_broadcast_connection_init()"); LOG_WARN(TAG, "error initializing udp connection, check warnings from udp_broadcast_init() or "
"udp_broadcast_connection_init()");
} }
if (udp_broadcast_set_owner_details("Joran", "Van Nieuwenhoven") != ERR_OK) { if (udp_broadcast_set_owner_details("Joran", "Van Nieuwenhoven") != ERR_OK) {
LOG_WARN(TAG, "error setting owner's details"); LOG_WARN(TAG, "error setting owner's details");
} }
/* Initialize website backend */
wbe_init();
/* USER CODE END 2 */ /* USER CODE END 2 */
/* Infinite loop */ /* Infinite loop */
/* USER CODE BEGIN WHILE */ /* USER CODE BEGIN WHILE */
while (1) while (1) {
{
/* USER CODE END WHILE */ /* USER CODE END WHILE */
/* USER CODE BEGIN 3 */ /* USER CODE BEGIN 3 */
@@ -174,8 +177,7 @@ int main(void)
* @brief System Clock Configuration * @brief System Clock Configuration
* @retval None * @retval None
*/ */
void SystemClock_Config(void) void SystemClock_Config(void) {
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
@@ -199,29 +201,25 @@ void SystemClock_Config(void)
RCC_OscInitStruct.PLL.PLLN = 400; RCC_OscInitStruct.PLL.PLLN = 400;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2; RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 2; RCC_OscInitStruct.PLL.PLLQ = 2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
{
Error_Handler(); Error_Handler();
} }
/** Activate the Over-Drive mode /** Activate the Over-Drive mode
*/ */
if (HAL_PWREx_EnableOverDrive() != HAL_OK) if (HAL_PWREx_EnableOverDrive() != HAL_OK) {
{
Error_Handler(); Error_Handler();
} }
/** Initializes the CPU, AHB and APB buses clocks /** Initializes the CPU, AHB and APB buses clocks
*/ */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6) != HAL_OK) if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_6) != HAL_OK) {
{
Error_Handler(); Error_Handler();
} }
} }
@@ -231,8 +229,7 @@ void SystemClock_Config(void)
* @param None * @param None
* @retval None * @retval None
*/ */
static void MX_DMA2D_Init(void) static void MX_DMA2D_Init(void) {
{
/* USER CODE BEGIN DMA2D_Init 0 */ /* USER CODE BEGIN DMA2D_Init 0 */
@@ -249,12 +246,10 @@ static void MX_DMA2D_Init(void)
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888; hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA; hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
hdma2d.LayerCfg[1].InputAlpha = 0; hdma2d.LayerCfg[1].InputAlpha = 0;
if (HAL_DMA2D_Init(&hdma2d) != HAL_OK) if (HAL_DMA2D_Init(&hdma2d) != HAL_OK) {
{
Error_Handler(); Error_Handler();
} }
if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) != HAL_OK) if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) != HAL_OK) {
{
Error_Handler(); Error_Handler();
} }
/* USER CODE BEGIN DMA2D_Init 2 */ /* USER CODE BEGIN DMA2D_Init 2 */
@@ -268,8 +263,7 @@ static void MX_DMA2D_Init(void)
* @param None * @param None
* @retval None * @retval None
*/ */
static void MX_LTDC_Init(void) static void MX_LTDC_Init(void) {
{
/* USER CODE BEGIN LTDC_Init 0 */ /* USER CODE BEGIN LTDC_Init 0 */
@@ -297,8 +291,7 @@ static void MX_LTDC_Init(void)
hltdc.Init.Backcolor.Blue = 0; hltdc.Init.Backcolor.Blue = 0;
hltdc.Init.Backcolor.Green = 255; hltdc.Init.Backcolor.Green = 255;
hltdc.Init.Backcolor.Red = 0; hltdc.Init.Backcolor.Red = 0;
if (HAL_LTDC_Init(&hltdc) != HAL_OK) if (HAL_LTDC_Init(&hltdc) != HAL_OK) {
{
Error_Handler(); Error_Handler();
} }
pLayerCfg.WindowX0 = 0; pLayerCfg.WindowX0 = 0;
@@ -316,8 +309,7 @@ static void MX_LTDC_Init(void)
pLayerCfg.Backcolor.Blue = 0; pLayerCfg.Backcolor.Blue = 0;
pLayerCfg.Backcolor.Green = 0; pLayerCfg.Backcolor.Green = 0;
pLayerCfg.Backcolor.Red = 0; pLayerCfg.Backcolor.Red = 0;
if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK) if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK) {
{
Error_Handler(); Error_Handler();
} }
pLayerCfg1.WindowX0 = 0; pLayerCfg1.WindowX0 = 0;
@@ -335,8 +327,7 @@ static void MX_LTDC_Init(void)
pLayerCfg1.Backcolor.Blue = 0; pLayerCfg1.Backcolor.Blue = 0;
pLayerCfg1.Backcolor.Green = 0; pLayerCfg1.Backcolor.Green = 0;
pLayerCfg1.Backcolor.Red = 0; pLayerCfg1.Backcolor.Red = 0;
if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg1, 1) != HAL_OK) if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg1, 1) != HAL_OK) {
{
Error_Handler(); Error_Handler();
} }
/* USER CODE BEGIN LTDC_Init 2 */ /* USER CODE BEGIN LTDC_Init 2 */
@@ -350,8 +341,7 @@ static void MX_LTDC_Init(void)
* @param None * @param None
* @retval None * @retval None
*/ */
static void MX_QUADSPI_Init(void) static void MX_QUADSPI_Init(void) {
{
/* USER CODE BEGIN QUADSPI_Init 0 */ /* USER CODE BEGIN QUADSPI_Init 0 */
@@ -370,8 +360,7 @@ static void MX_QUADSPI_Init(void)
hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0; hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
hqspi.Init.FlashID = QSPI_FLASH_ID_1; hqspi.Init.FlashID = QSPI_FLASH_ID_1;
hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE; hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
if (HAL_QSPI_Init(&hqspi) != HAL_OK) if (HAL_QSPI_Init(&hqspi) != HAL_OK) {
{
Error_Handler(); Error_Handler();
} }
/* USER CODE BEGIN QUADSPI_Init 2 */ /* USER CODE BEGIN QUADSPI_Init 2 */
@@ -385,8 +374,7 @@ static void MX_QUADSPI_Init(void)
* @param None * @param None
* @retval None * @retval None
*/ */
static void MX_USART1_UART_Init(void) static void MX_USART1_UART_Init(void) {
{
/* USER CODE BEGIN USART1_Init 0 */ /* USER CODE BEGIN USART1_Init 0 */
@@ -405,8 +393,7 @@ static void MX_USART1_UART_Init(void)
huart1.Init.OverSampling = UART_OVERSAMPLING_16; huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE; huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT; huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK) if (HAL_UART_Init(&huart1) != HAL_OK) {
{
Error_Handler(); Error_Handler();
} }
/* USER CODE BEGIN USART1_Init 2 */ /* USER CODE BEGIN USART1_Init 2 */
@@ -416,8 +403,7 @@ static void MX_USART1_UART_Init(void)
} }
/* FMC initialization function */ /* FMC initialization function */
static void MX_FMC_Init(void) static void MX_FMC_Init(void) {
{
/* USER CODE BEGIN FMC_Init 0 */ /* USER CODE BEGIN FMC_Init 0 */
@@ -452,8 +438,7 @@ static void MX_FMC_Init(void)
SdramTiming.RPDelay = 16; SdramTiming.RPDelay = 16;
SdramTiming.RCDDelay = 16; SdramTiming.RCDDelay = 16;
if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK) if (HAL_SDRAM_Init(&hsdram1, &SdramTiming) != HAL_OK) {
{
Error_Handler(); Error_Handler();
} }
@@ -467,8 +452,7 @@ static void MX_FMC_Init(void)
* @param None * @param None
* @retval None * @retval None
*/ */
static void MX_GPIO_Init(void) static void MX_GPIO_Init(void) {
{
GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */ /* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */ /* USER CODE END MX_GPIO_Init_1 */
@@ -523,13 +507,11 @@ static void MX_GPIO_Init(void)
* @brief This function is executed in case of error occurrence. * @brief This function is executed in case of error occurrence.
* @retval None * @retval None
*/ */
void Error_Handler(void) void Error_Handler(void) {
{
/* USER CODE BEGIN Error_Handler_Debug */ /* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */ /* User can add his own implementation to report the HAL error return state */
__disable_irq(); __disable_irq();
while (1) while (1) {
{
} }
/* USER CODE END Error_Handler_Debug */ /* USER CODE END Error_Handler_Debug */
} }

View File

@@ -28,13 +28,7 @@
#define SERVER_IP4_D 11 #define SERVER_IP4_D 11
#define SERVER_PORT 1883 #define SERVER_PORT 1883
typedef enum input_topic { typedef enum input_topic { set_text, set_text_color, set_color, set_image, other_topic } input_topic_t;
set_text,
set_text_color,
set_color,
set_image,
other_topic
} input_topic_t;
// Function prototypes // Function prototypes
static void mqtt_pub_request_cb(void*, err_t); static void mqtt_pub_request_cb(void*, err_t);
@@ -47,7 +41,8 @@ static void mosquitto_connect(mqtt_client_t*);
static uint32_t color_picker(char*); static uint32_t color_picker(char*);
static void create_publish_string(char*, char*, size_t); static void create_publish_string(char*, char*, size_t);
// Global variables used in mqtt_incoming_publish_cb and mqtt_incoming_data_cb to give an easy to use ID to the subscribed topics // Global variables used in mqtt_incoming_publish_cb and mqtt_incoming_data_cb to give an easy to use ID to the
// subscribed topics
static sFONT* font; static sFONT* font;
static uint16_t xpos; static uint16_t xpos;
static uint16_t ypos; static uint16_t ypos;
@@ -82,7 +77,8 @@ static void publish_data(mqtt_client_t* client, void* arg) {
create_publish_string("*.bmp", pub_payload, sizeof(pub_payload)); create_publish_string("*.bmp", pub_payload, sizeof(pub_payload));
err = mqtt_publish(client, "getImageList", pub_payload, strlen(pub_payload), PUBLISH_QOS, PUBLISH_RETAIN, mqtt_pub_request_cb, arg); err = mqtt_publish(client, "getImageList", pub_payload, strlen(pub_payload), PUBLISH_QOS, PUBLISH_RETAIN,
mqtt_pub_request_cb, arg);
if (err != ERR_OK) { if (err != ERR_OK) {
LOG_DEBUG(TAG, "Publish err: %d", err); LOG_DEBUG(TAG, "Publish err: %d", err);
} }
@@ -90,7 +86,8 @@ static void publish_data(mqtt_client_t* client, void* arg) {
pub_payload[0] = '\0'; pub_payload[0] = '\0';
create_publish_string("*.gif", pub_payload, sizeof(pub_payload)); create_publish_string("*.gif", pub_payload, sizeof(pub_payload));
err = mqtt_publish(client, "getGifList", pub_payload, strlen(pub_payload), PUBLISH_QOS, PUBLISH_RETAIN, mqtt_pub_request_cb, arg); err = mqtt_publish(client, "getGifList", pub_payload, strlen(pub_payload), PUBLISH_QOS, PUBLISH_RETAIN,
mqtt_pub_request_cb, arg);
if (err != ERR_OK) { if (err != ERR_OK) {
LOG_DEBUG(TAG, "Publish err: %d", err); LOG_DEBUG(TAG, "Publish err: %d", err);
} }

View File

@@ -36,7 +36,6 @@ static err_t tcp_cmd_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t
char* endptr; char* endptr;
if (err == ERR_OK && p != NULL) { if (err == ERR_OK && p != NULL) {
tcp_recved(pcb, p->tot_len); tcp_recved(pcb, p->tot_len);
pc = (char*)p->payload; pc = (char*)p->payload;
@@ -48,13 +47,15 @@ static err_t tcp_cmd_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t
if (!strncmp(tcp_buffer, "help", 4)) { if (!strncmp(tcp_buffer, "help", 4)) {
check = 1; check = 1;
tcp_write(pcb, "help : laat lijst zien met alle commando's\r\n" tcp_write(pcb,
"help : laat lijst zien met alle commando's\r\n"
"text : geeft tekst mee die op LCD komt (uw_text)\r\n" "text : geeft tekst mee die op LCD komt (uw_text)\r\n"
"color : kleur achtergrond van scherm (255 255 255)\r\n" "color : kleur achtergrond van scherm (255 255 255)\r\n"
"textColor : kleur van tekst (255 255 255)\r\n" "textColor : kleur van tekst (255 255 255)\r\n"
"listImages: laat een lijst zien van de mogelijke afbeeldingen\r\n" "listImages: laat een lijst zien van de mogelijke afbeeldingen\r\n"
"setImage : veranderd te afbeelding (naam_afbeelding)\r\n" "setImage : veranderd te afbeelding (naam_afbeelding)\r\n"
"exit : sluit de verbinding\r\n", 354, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); "exit : sluit de verbinding\r\n",
354, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
} else if (!strncmp(tcp_buffer, "text ", 5)) { } else if (!strncmp(tcp_buffer, "text ", 5)) {
size_t i; size_t i;
for (i = 0; i < len - 4; i++) { for (i = 0; i < len - 4; i++) {
@@ -64,7 +65,6 @@ static err_t tcp_cmd_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t
lcd_clear_text(); lcd_clear_text();
lcd_display_text(text, 10, 10, result_txt, result_bg, LCD_FONT24); lcd_display_text(text, 10, 10, result_txt, result_bg, LCD_FONT24);
check = 1; check = 1;
} else if (!strncmp(tcp_buffer, "color", 5)) { } else if (!strncmp(tcp_buffer, "color", 5)) {
for (size_t i = 0; i < 3; i++) { for (size_t i = 0; i < 3; i++) {
@@ -96,7 +96,8 @@ static err_t tcp_cmd_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t
number_of_files = llfs_file_list(file_list, number_of_files, NULL); number_of_files = llfs_file_list(file_list, number_of_files, NULL);
for (size_t i = 0; i < number_of_files; i++) { for (size_t i = 0; i < number_of_files; i++) {
tcp_write(pcb, file_list[i].name, strlen(file_list[i].name), TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); tcp_write(pcb, file_list[i].name, strlen(file_list[i].name),
TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
tcp_write(pcb, "\r\n", 2, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); tcp_write(pcb, "\r\n", 2, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
} }
} else { } else {
@@ -154,7 +155,8 @@ static err_t tcp_cmd_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t
} }
if (!check && (strncmp(tcp_buffer, "\r\n", 2) != 0)) { if (!check && (strncmp(tcp_buffer, "\r\n", 2) != 0)) {
tcp_write(pcb, "Onbestaand commando: help voor lijst van commando's\r\n", 53, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); tcp_write(pcb, "Onbestaand commando: help voor lijst van commando's\r\n", 53,
TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
} }
pbuf_free(p); pbuf_free(p);
@@ -184,10 +186,12 @@ static err_t tcp_cmd_accept(void* arg, struct tcp_pcb* pcb, err_t err) {
tcp_recv(pcb, tcp_cmd_recv); tcp_recv(pcb, tcp_cmd_recv);
tcp_err(pcb, NULL); tcp_err(pcb, NULL);
tcp_poll(pcb, NULL, 4); tcp_poll(pcb, NULL, 4);
tcp_write(pcb, " Welcom bij de TCP CMD Interface\r\n" tcp_write(pcb,
" Welcom bij de TCP CMD Interface\r\n"
"(Typ help voor een lijst van de commando's! X om te sluiten)\r\n" "(Typ help voor een lijst van de commando's! X om te sluiten)\r\n"
"============================================================\r\n" "============================================================\r\n"
"User: ", 168, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE); "User: ",
168, TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE);
tcp_sent(pcb, NULL); tcp_sent(pcb, NULL);
return ERR_OK; return ERR_OK;
} }
@@ -200,4 +204,3 @@ void tcp_cmd_init(void) {
tcp_pcb = tcp_listen(tcp_pcb); tcp_pcb = tcp_listen(tcp_pcb);
tcp_accept(tcp_pcb, tcp_cmd_accept); tcp_accept(tcp_pcb, tcp_cmd_accept);
} }

View File

@@ -28,7 +28,10 @@ static void* tftp_open(const char* fname, const char* mode, uint8_t write);
static void tftp_close(void* handle); static void tftp_close(void* handle);
static int tftp_read(void* handle, void* buf, int bytes); static int tftp_read(void* handle, void* buf, int bytes);
static int tftp_write(void* handle, struct pbuf* p); static int tftp_write(void* handle, struct pbuf* p);
static struct tftp_context tftpContext_s = {.open = tftp_open, .close = tftp_close, .read = tftp_read, .write = tftp_write}; static struct tftp_context tftpContext_s = {.open = tftp_open,
.close = tftp_close,
.read = tftp_read,
.write = tftp_write};
/** /**
* @brief tftp custom file functions to set the offset and read the data * @brief tftp custom file functions to set the offset and read the data
* @param[in,out] handle Custom file handles * @param[in,out] handle Custom file handles

View File

@@ -0,0 +1,301 @@
/**
* @file website_backend.h
* @brief Backend for the website to operate
* @author Toon B.
*/
// Includes
#include "website_backend.h"
// Static functions
static size_t wbe_get_images(char* images_string, size_t file_count_fs);
static inline void wbe_build_infostring(const llfs_file_t* file_list, char* info_string, const size_t cnt);
static void wbe_decoding_url(const char* encoded, char* decoded);
static uint32_t wbe_color_value(const char* rgb);
void wbe_init(void) {
httpd_init();
LOG_DEBUG("WBE", "Initialize webserver");
// Set starting LCD screen
wbe_display("Please Edit Me !", LCD_GREEN, LCD_BLACK, SD_IMG);
return;
}
int fs_open_custom(struct fs_file* file, const char* name) {
// Variables
llfs_file_t* wanted_file = llfs_file_open(name + 1);
size_t buffer_len = 0;
static char image_stringbuffer[STR_MAX] = "";
// The wanted file was found in the filesystem
if (wanted_file != NULL) {
// Debug info
LOG_DEBUG("WBE", "The file : %s was found", wanted_file->name);
// Give the information about the file to the client
file->data = (const char*)wanted_file->data;
file->len = (int)wanted_file->len;
file->index = (int)wanted_file->len;
file->is_custom_file = 1;
file->pextension = NULL;
file->flags = FS_FILE_FLAGS_HEADER_INCLUDED;
return 1;
}
/*
* The endpoint '/images.info' is called when the client wants to call for the
* information string that contains the names of the available images.
*/
if (strncmp(name, "/images.info", strlen("/images.info")) == 0) {
// Create the information string for the images in the filesystem
buffer_len = wbe_get_images(image_stringbuffer, llfs_file_count());
// Give the string back to the client
file->data = image_stringbuffer;
file->len = (int)buffer_len;
file->index = (int)buffer_len;
file->is_custom_file = 1;
file->pextension = NULL;
file->flags = FS_FILE_FLAGS_HEADER_INCLUDED;
return 1;
}
// Endpoint when client wants to send information to the backend
if (strncmp(name, "/cgi", 3) == 0) {
// Give the original index.html back to the client
wanted_file = llfs_file_open("index.html");
if (wanted_file != NULL) {
file->data = (const char*)wanted_file->data;
file->len = (int)wanted_file->len;
file->index = (int)wanted_file->len;
file->is_custom_file = 1;
file->pextension = NULL;
file->flags = FS_FILE_FLAGS_HEADER_INCLUDED;
return 1;
}
}
return 0;
}
void fs_close_custom(struct fs_file* file) {
}
/**
* @fn void wbe_get_images(char*, size_t)
* @brief Function searches filesystem for files with extention ".bmp" and ".gif" and put them
* combined in a string that needs to be send to the frontend.
*
* @param[in] images_string, string that will contain the image names
* @param[in] file_count_fs, the number of files in the filesystem
*/
static size_t wbe_get_images(char* images_string, size_t file_count_fs) {
// Allocate space for the files
llfs_file_t file_list[file_count_fs];
size_t file_count_bmp = 0;
size_t file_count_gif = 0;
// Reset string
strcpy(images_string, "");
// Get all the ".bmp" and ".gif" files
file_count_bmp = llfs_file_list(file_list, file_count_fs, ".bmp");
file_count_gif = llfs_file_list(file_list + file_count_bmp, file_count_fs, ".gif");
// Create the info string
wbe_build_infostring(file_list, images_string, file_count_gif + file_count_bmp);
// Debug info
LOG_DEBUG("WBE", "Images string : %s ", images_string);
// Return the length of the string
return strlen(images_string);
}
/**
* @fn void wbe_build_infostring(const llfs_file_t*, char*, const size_t)
* @brief Function adds the names of the files in "file_list" and adds them in "infoStr".
* The names are seperated by '|' characters.
*
* @param[in] file_list, list with files
* @param[in] info_string, string that will contain the filenames
* @param[in] cnt, the number of files
*/
static inline void wbe_build_infostring(const llfs_file_t* file_list, char* info_string, const size_t cnt) {
// Add the filenames to the info string
for (size_t i = 0; i < cnt; ++i) {
strncat(info_string, file_list[i].name, strlen(file_list[i].name));
strncat(info_string, "|", 2);
}
// Remove last seperator '|'
info_string[strlen(info_string) - 1] = '\0';
}
void httpd_cgi_handler(struct fs_file* file, const char* uri, int num_parm, char** pc_param, char** pc_value) {
// Variables
uint32_t vktxt = LCD_GREEN;
uint32_t vka = LCD_BLACK;
// Allocate space for parameters
char vtxt[STR_MAX]; // The sentence that we want to print on the LCD.
char vfo[STR_MAX]; // Name of the selected image on the website.
char s_vktxt[CLR_MAX]; // The color of the sentence. (in #RGB)
char s_vka[CLR_MAX]; // Color of the background. (also in #RGB)
if (strcmp("/cgi", uri) == 0) {
for (size_t i = 0; i < num_parm; ++i) {
// The given sentence
if (strcmp("vtxt", pc_param[i]) == 0) {
wbe_decoding_url(pc_value[i], vtxt);
}
// The color of the sentence
if (strcmp("vktxt", pc_param[i]) == 0) {
wbe_decoding_url(pc_value[i], s_vktxt);
// Convert to hex value
if (s_vktxt != NULL) {
vktxt = wbe_color_value(s_vktxt);
}
}
// Color of the background
if (strcmp("vka", pc_param[i]) == 0) {
wbe_decoding_url(pc_value[i], s_vka);
// convert to hex value
if (s_vka != NULL) {
vka = wbe_color_value(s_vka);
}
}
// Name of the image
if (strcmp("vfo", pc_param[i]) == 0) {
wbe_decoding_url(pc_value[i], vfo);
}
}
// Debug info
LOG_DEBUG("WBE", "CGI DATA : %s , %x , %x , %s", vtxt, vktxt, vka, vfo);
// Display on LCD
wbe_display(vtxt, vktxt, vka, vfo);
}
}
/**
* @fn void wbe_decoding_url(const char*, char*)
* @brief The given information from the CGI parameters are URL encoded.
* This function translates this encoded string in a readable
* decoded string. The lengthe of "char* decoded" is at least the
* length of "char* encoded" + 1.
*
* @param[in] encoded, the encoded URL string that needs to be decoded
* @param[in] decoded, string that will contain the decoded URL.
*/
static void wbe_decoding_url(const char* encoded, char* decoded) {
// Variables
char* endptr;
size_t decoded_index = 0;
size_t encoded_length = strlen(encoded);
uint32_t hex_val;
for (size_t i = 0; i < encoded_length; ++i) {
// If we encounter a %xx, decode it to ascii
if ((encoded[i] == '%') && (i + 2 < encoded_length)) {
// Decode %xx
hex_val = (uint32_t)strtoul(&encoded[i + 1], &endptr, 16);
// Check for conversion errors
if (endptr == &encoded[i + 1] || *endptr != '\0') {
LOG_DEBUG("WBE", "URL text conversion error");
}
decoded[decoded_index++] = (char)hex_val;
// Skip 2 characters
i += 2;
// If we encounter a +, add a space character
} else if (encoded[i] == '+') {
decoded[decoded_index++] = ' ';
// If no % or +, just put what stands in 'encoded'
} else {
decoded[decoded_index++] = encoded[i];
}
}
// Finish the string
decoded[decoded_index] = '\0';
}
static uint32_t wbe_color_value(const char* rgb) {
// Variables
char* endptr;
uint32_t color = LCD_BLACK;
char argb[11] = "0xff";
// Create argb string (also, skip the '#' char)
strncat(argb, rgb + 1, strlen(rgb + 1));
// Get argb value
color = (uint32_t)strtoul(argb, &endptr, 16);
// Check for conversion errors
if (*endptr != '\0') {
color = LCD_BLACK;
LOG_DEBUG("WBE", "URL color conversion error");
}
return color;
}
void wbe_display(const char* txt, const uint32_t txt_color, const uint32_t bg_color, const char* image) {
// Variables
lcd_gif_t* gif;
const char* extension;
// clear the screen
lcd_clear_text();
lcd_clear_images();
// Display the text and the background
lcd_set_bg_color_layer0(bg_color);
lcd_display_text(txt, 10, 10, txt_color, bg_color, LCD_FONT16);
// Get the extension of the file
extension = llfs_get_filename_ext(image);
// Check extension
if (extension != NULL) {
// Draw bmp
if (strcmp(extension, "bmp") == 0) {
lcd_draw_img_from_fs(image, IMG_X, IMG_Y);
// Draw gif
} else if (strcmp(extension, "gif") == 0) {
gif = lcd_draw_gif_from_fs(image, IMG_X, IMG_Y);
if (gif == NULL) {
LOG_DEBUG("WBE", "GIF could not be drawn");
}
// If nothing, then draw the standard image
} else {
lcd_draw_img_from_fs(SD_IMG, IMG_X, IMG_Y);
}
// If nothing, then draw the standard image
} else {
lcd_draw_img_from_fs(SD_IMG, IMG_X, IMG_Y);
}
}

View File

@@ -17,9 +17,10 @@ target_compile_definitions(tests
target_sources(tests target_sources(tests
PRIVATE PRIVATE
${TEST_SOURCES} ${TEST_SOURCES}
../project/Core/Src/tftp.c ${CMAKE_SOURCE_DIR}
../project/Core/Src/llfs_data.c ${CMAKE_SOURCE_DIR}/project/Core/Src/llfs_data.c
../project/Core/Src/llfs.c ${CMAKE_SOURCE_DIR}/project/Core/Src/llfs.c
${CMAKE_SOURCE_DIR}/project/Core/Src/tftp.c
) )
target_compile_options(tests PRIVATE $<$<CONFIG:Debug>: target_compile_options(tests PRIVATE $<$<CONFIG:Debug>:
@@ -35,7 +36,7 @@ target_include_directories(tests
PUBLIC PUBLIC
${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}
${PROJECT_BINARY_DIR} ${PROJECT_BINARY_DIR}
../project/Core/Inc/ ${CMAKE_SOURCE_DIR}/project/Core/Inc/
) )
include(GoogleTest) include(GoogleTest)

View File

@@ -12,7 +12,12 @@ int tftp_init(struct tftp_context* context) {
return 0; return 0;
} }
void lcd_display_text(const char* text, uint16_t x_pos, uint16_t y_pos, uint32_t color, uint32_t bg_color, sFONT* font) { void lcd_display_text(const char* text,
uint16_t x_pos,
uint16_t y_pos,
uint32_t color,
uint32_t bg_color,
sFONT* font) {
UNUSED(color); UNUSED(color);
UNUSED(bg_color); UNUSED(bg_color);
UNUSED(font); UNUSED(font);

View File

@@ -4,8 +4,8 @@
extern "C" { extern "C" {
#endif #endif
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#ifndef UNUSED #ifndef UNUSED
#define UNUSED(x) (void)(x) #define UNUSED(x) (void)(x)
@@ -86,8 +86,7 @@ typedef void sFONT;
#define TCP_PRIO_MAX 127 #define TCP_PRIO_MAX 127
#define IP_ADDR_ANY 0 #define IP_ADDR_ANY 0
typedef err_t (*tcp_recv_fn)(void *arg, struct tcp_pcb *tpcb, typedef err_t (*tcp_recv_fn)(void* arg, struct tcp_pcb* tpcb, struct pbuf* p, err_t err);
struct pbuf *p, err_t err);
typedef err_t (*tcp_accept_fn)(void* arg, struct tcp_pcb* newpcb, err_t err); typedef err_t (*tcp_accept_fn)(void* arg, struct tcp_pcb* newpcb, err_t err);

View File

@@ -1,47 +1,35 @@
#include <gtest/gtest.h> #include <gtest/gtest.h>
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "mocs.h" #include "mocs.h"
#include "tftp.h" #include "tftp.h"
tftp_custom_file_t file = { tftp_custom_file_t file = {.data = (char*)"1234567890", .len = 11, .name = (char*)"test.txt", .offset = 0};
.data = (char*)"1234567890", tftp_custom_file_t write_file = {.data = NULL, .len = 0, .name = (char*)"test.txt", .offset = 0};
.len = 11,
.name = (char*)"test.txt",
.offset = 0
};
tftp_custom_file_t write_file = {
.data = NULL,
.len = 0,
.name = (char*)"test.txt",
.offset = 0
};
TEST(TFTP, custom_fseek) TEST(TFTP, custom_fseek) {
{
tftp_custom_fseek(&file, 5, SEEK_SET); tftp_custom_fseek(&file, 5, SEEK_SET);
EXPECT_EQ(file.offset, 5); EXPECT_EQ(file.offset, 5);
tftp_custom_fseek(&file, 5, SEEK_CUR); tftp_custom_fseek(&file, 5, SEEK_CUR);
EXPECT_EQ(file.offset, 10); EXPECT_EQ(file.offset, 10);
} }
TEST(TFTP, custom_fread) TEST(TFTP, custom_fread) {
{
char buf[11]; char buf[11];
tftp_custom_fseek(&file, 0, SEEK_SET); tftp_custom_fseek(&file, 0, SEEK_SET);
size_t bytes = tftp_custom_fread(buf, 11, &file); size_t bytes = tftp_custom_fread(buf, 11, &file);
EXPECT_EQ(bytes, 10); EXPECT_EQ(bytes, 11);
EXPECT_EQ(file.offset, 10); EXPECT_EQ(file.offset, 11);
EXPECT_EQ(memcmp(buf, "1234567890", 10), 0); EXPECT_EQ(memcmp(buf, "1234567890", 10), 0);
memset(buf, 0, 11); memset(buf, 0, 11);
tftp_custom_fseek(&file, 0, SEEK_SET); tftp_custom_fseek(&file, 0, SEEK_SET);
bytes = tftp_custom_fread(buf, 11, &file); bytes = tftp_custom_fread(buf, 11, &file);
EXPECT_EQ(bytes, 10); EXPECT_EQ(bytes, 11);
EXPECT_EQ(memcmp(buf, "1234567890", 10), 0); EXPECT_EQ(memcmp(buf, "1234567890", 10), 0);
memset(buf, 0, 11); memset(buf, 0, 11);

View File

@@ -4,8 +4,8 @@
extern "C" { extern "C" {
#endif #endif
#include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "mocs.h" #include "mocs.h"
struct tftp_context { struct tftp_context {