diff --git a/0BUILD b/0BUILD
index f406ef5..b128842 100644
--- a/0BUILD
+++ b/0BUILD
@@ -2,7 +2,7 @@
-
+
$(project_name)
$(project_vmajor).$(project_vminor).$(project_vpatchlevel)
diff --git a/apps/aqhome-cgi/modules/devices/mdevices_page.c b/apps/aqhome-cgi/modules/devices/mdevices_page.c
index f6def1d..7d3b3bb 100644
--- a/apps/aqhome-cgi/modules/devices/mdevices_page.c
+++ b/apps/aqhome-cgi/modules/devices/mdevices_page.c
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
#include
@@ -75,6 +76,8 @@ static int _getColorComponent(GWEN_DB_NODE *dbPost, const char *sValueName, cons
static void _setOnOffData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue);
static void _setOnOffAutoData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *sValue);
+static void _sendPageList(AQH_MODULE *m, GWEN_BUFFER *dbuf);
+static GWEN_STRINGLIST *_listPageFiles(AQH_MODULE *m);
static GWEN_XMLNODE *_readPage(AQH_MODULE *m, const char *sPageName);
static GWEN_XMLNODE *_readPageFile(const char *sFilename);
static int _layoutFromString(const char *s);
@@ -93,7 +96,7 @@ void AQH_ModDevices_RunPageGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *se
DBG_INFO(NULL, "RunPageGet");
dbQuery=AQCGI_Request_GetDbQuery(rq);
- sPageId=GWEN_DB_GetCharValue(dbQuery, "page", 0, NULL);
+ sPageId=dbQuery?GWEN_DB_GetCharValue(dbQuery, "page", 0, NULL):NULL;
if (sPageId && *sPageId) {
GWEN_XMLNODE *fileNode;
@@ -115,6 +118,10 @@ void AQH_ModDevices_RunPageGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *se
DBG_INFO(NULL, "here");
}
}
+ else {
+ DBG_ERROR(NULL, "Reading page list");
+ _sendPageList(m, dbuf);
+ }
}
@@ -812,6 +819,86 @@ void _setOnOffAutoData(AQH_DATACLIENT *dc, const AQH_VALUE *value, const char *s
+void _sendPageList(AQH_MODULE *m, GWEN_BUFFER *dbuf)
+{
+ GWEN_STRINGLIST *sl;
+
+ GBAS(dbuf, "Page List
\n");
+ sl=_listPageFiles(m);
+ if (sl) {
+ GWEN_STRINGLISTENTRY *se;
+
+ GBAS(dbuf,
+ "\n"
+ "| Page | Title |
\n"
+ "\n");
+ se=GWEN_StringList_FirstEntry(sl);
+ while(se) {
+ const char *filename;
+
+ filename=GWEN_StringListEntry_Data(se);
+ if (filename && *filename) {
+ GWEN_XMLNODE *node;
+
+ DBG_ERROR(NULL, "Reading file \"%s\"", filename);
+ node=_readPageFile(filename);
+ if (node) {
+ GWEN_XMLNODE *nPage;
+
+ nPage=GWEN_XMLNode_FindFirstTag(node, "page", NULL, NULL);
+ if (nPage) {
+ const char *sId;
+ const char *sTitle;
+
+ sId=GWEN_XMLNode_GetProperty(nPage, "id", NULL);
+ sTitle=GWEN_XMLNode_GetProperty(nPage, "title", sId);
+ if (sId && *sId)
+ GBAA(dbuf, "| %s | %s |
\n", sId, sId, sTitle);
+ }
+ GWEN_XMLNode_free(node);
+ }
+ }
+ se=GWEN_StringListEntry_Next(se);
+ }
+ GBAS(dbuf, "
");
+ GWEN_StringList_free(sl);
+ }
+ else {
+ GBAS(dbuf, "No pages.");
+ }
+}
+
+
+
+GWEN_STRINGLIST *_listPageFiles(AQH_MODULE *m)
+{
+ GWEN_BUFFER *fbuf;
+ AQH_SERVICE *sv;
+ GWEN_STRINGLIST *sl;
+ int rv;
+
+ sv=AQH_ModService_GetService(m);
+ fbuf=GWEN_Buffer_new(0, 256, 0, 1);
+ GBAA(fbuf, "%s%spages", AQH_Service_GetRuntimeFolder(sv), GWEN_DIR_SEPARATOR_S);
+ sl=GWEN_StringList_new();
+ rv=GWEN_Directory_GetMatchingFilesRecursively(GWEN_Buffer_GetStart(fbuf), sl, "*.xml");
+ if (rv<0) {
+ DBG_INFO(NULL, "Error reading pages (%d)", rv);
+ GWEN_StringList_free(sl);
+ GWEN_Buffer_free(fbuf);
+ return NULL;
+ }
+ if (GWEN_StringList_Count(sl)<1) {
+ GWEN_StringList_free(sl);
+ GWEN_Buffer_free(fbuf);
+ return NULL;
+ }
+ GWEN_Buffer_free(fbuf);
+
+ return sl;
+}
+
+
GWEN_XMLNODE *_readPage(AQH_MODULE *m, const char *sPageName)
{
diff --git a/apps/aqhome-cgi/modules/static/en/header.html b/apps/aqhome-cgi/modules/static/en/header.html
index e1a740a..0f20969 100644
--- a/apps/aqhome-cgi/modules/static/en/header.html
+++ b/apps/aqhome-cgi/modules/static/en/header.html
@@ -16,6 +16,7 @@
- Devices
+ - Pages
- Admin
- News
- Contact
diff --git a/apps/aqhome-tool/image/readbmp.c b/apps/aqhome-tool/image/readbmp.c
index 18de34d..71cc656 100644
--- a/apps/aqhome-tool/image/readbmp.c
+++ b/apps/aqhome-tool/image/readbmp.c
@@ -67,6 +67,7 @@ static int AQH_Tool_ReadAndDumpBmpFile(const char *fname);
static int AQH_Tool_ExportBmpFile(const char *fname);
static int _exportBmp_1bpp(const BMP_FILE *bf);
+static int _exportBmp_gray8bpp(const BMP_FILE *bf);
static BMP_FILEHEADER *_fileHeader_new();
static void _fileHeader_free(BMP_FILEHEADER *fh);
@@ -166,6 +167,8 @@ int AQH_Tool_ExportBmpFile(const char *fname)
_dumpBmpImageHeader(bf->imageHeader);
if (bf->imageHeader->bitsPerPixel==1)
rv=_exportBmp_1bpp(bf);
+ else if (bf->imageHeader->bitsPerPixel==8)
+ rv=_exportBmp_gray8bpp(bf);
else {
fprintf(stderr, "Invalid bits per pixel (%d)", bf->imageHeader->bitsPerPixel);
rv=2;
@@ -220,6 +223,69 @@ int _exportBmp_1bpp(const BMP_FILE *bf)
+int _exportBmp_gray8bpp(const BMP_FILE *bf)
+{
+ const uint8_t *ptrBuffer;
+ uint32_t lenBuffer;
+ uint32_t offsPixels;
+ const uint8_t *ptrPixels;
+ int imageWidth;
+ int imageHeight;
+ int rowWidthInBytes;
+ int columns;
+ int y;
+
+ ptrBuffer=(const uint8_t *) GWEN_Buffer_GetStart(bf->buffer);
+ lenBuffer=GWEN_Buffer_GetUsedBytes(bf->buffer);
+ offsPixels=bf->fileHeader->offsPixels;
+ ptrPixels=ptrBuffer+offsPixels;
+ imageWidth=bf->imageHeader->imgWidth;
+ imageHeight=bf->imageHeader->imgHeight;
+ columns=imageWidth;
+ rowWidthInBytes=4*((columns+3)/4); /* BMPs have multiple of 4 bytes per row! */
+ fprintf(stdout, "imgData: \n");
+ fprintf(stdout, " .dw %d, %d\n", imageWidth, imageHeight);
+
+ for (y=imageHeight-1; y>=0; y--) {
+ const uint8_t *rowPtr;
+ int x;
+ uint8_t currentByte=0;
+ int writtenBytes=0;
+ int packedPixels=0;
+
+ fprintf(stdout, " .db ");
+ rowPtr=ptrPixels+(y*rowWidthInBytes);
+ for (x=0; x
diff --git a/avr/common/ressource.asm b/avr/common/ressource.asm
new file mode 100644
index 0000000..16e37da
--- /dev/null
+++ b/avr/common/ressource.asm
@@ -0,0 +1,64 @@
+; ***************************************************************************
+; copyright : (C) 2025 by Martin Preuss
+; email : martin@libchipcard.de
+;
+; ***************************************************************************
+; * This file is part of the project "AqHome". *
+; * Please see toplevel file COPYING of that project for license details. *
+; ***************************************************************************
+
+#ifndef AQH_AVR_COMMON_RESSOURCE_H
+#define AQH_AVR_COMMON_RESSOURCE_H
+
+
+; ***************************************************************************
+; defs
+
+
+
+; ***************************************************************************
+; code
+
+.cseg
+
+
+; ---------------------------------------------------------------------------
+; @routine RES_GetRessource
+;
+; The Ressource table has one entry for every ressource handled by this table.
+; The first entry contains the number of ressource entries in the table.
+; All following entries contain byte pointer addresses (for LPM) to ressources.
+; Ressource ids start with zero.
+;
+; @param r17:r16 ressource id (starting with 0)
+; @param Z pointer to start of ressources in FLASH (byte address)
+; @return CF set if ressource found, cleared otherwise
+; @return Z if CF set: pointer to ressource (byte address)
+; @clobbers r16, r17, r18
+
+RES_GetRessource:
+ lpm r18, Z+ ; first entry: number of entries in table
+ cp r16, r18 ; id must be < num entries
+ lpm r18, Z+ ; Z points to first entry now
+ cpc r17, r18
+ brcc RES_GetRessource_ret
+RES_GetRessource_getRessource:
+ lsl r16 ; byte address, so we need to add ressource id twice (i.e. *2)
+ rol r17
+ add zl, r16
+ add zh, r17
+ lpm r16, Z+
+ lpm r17, Z+
+ mov zl, r16
+ mov zh, r17
+ sec
+RES_GetRessource_ret:
+ ret
+; @end
+
+
+
+
+
+#endif
+
diff --git a/avr/devices/all/includes.asm b/avr/devices/all/includes.asm
index e981879..4d4d36e 100644
--- a/avr/devices/all/includes.asm
+++ b/avr/devices/all/includes.asm
@@ -248,6 +248,7 @@
#ifdef MODULES_ILI9341
.include "modules/lcd2/ili9341/defs.asm"
.include "modules/lcd2/ili9341/colors.asm"
+.include "modules/lcd2/ili9341/images.asm"
.include "modules/lcd2/ili9341/main.asm"
.include "modules/lcd2/ili9341/io_spi.asm"
.include "modules/lcd2/ili9341/graphops.asm"
diff --git a/avr/devices/c03/defs.asm b/avr/devices/c03/defs.asm
index d18e0ae..e45f6a9 100644
--- a/avr/devices/c03/defs.asm
+++ b/avr/devices/c03/defs.asm
@@ -40,6 +40,8 @@
.equ BOOTLOADER_ADDR = 0x7c00
+.equ RESSOURCE_ADDR = 0x4000
+
.equ FIRMWARE_VARIANT_BOOT = 0
.equ FIRMWARE_VARIANT_TEMP_WINDOW = 1
diff --git a/avr/devices/c03/main/0BUILD b/avr/devices/c03/main/0BUILD
index 725937d..72f56fe 100644
--- a/avr/devices/c03/main/0BUILD
+++ b/avr/devices/c03/main/0BUILD
@@ -20,6 +20,24 @@
+
+
+
+ -I $(builddir)
+ -I $(srcdir)
+ -I $(topsrcdir)/avr
+ -I $(topbuilddir)/avr
+
+
+
+
+ ressources.asm
+
+
+
+
+
+
diff --git a/avr/devices/c03/main/main.asm b/avr/devices/c03/main/main.asm
index f6fd8b4..26ecd02 100644
--- a/avr/devices/c03/main/main.asm
+++ b/avr/devices/c03/main/main.asm
@@ -253,9 +253,11 @@ test:
;.include "common/list_t.asm"
;.include "common/tree_t.asm"
.include "common/divide.asm"
+.include "common/ressource.asm"
.include "modules/lcd2/gui/style.asm"
.include "dlg_netstats.asm"
+ .include "ressources.inc"
; ---------------------------------------------------------------------------
diff --git a/avr/devices/c03/main/ressources.asm b/avr/devices/c03/main/ressources.asm
new file mode 100644
index 0000000..c0ba4e2
--- /dev/null
+++ b/avr/devices/c03/main/ressources.asm
@@ -0,0 +1,95 @@
+; ***************************************************************************
+; copyright : (C) 2025 by Martin Preuss
+; email : martin@libchipcard.de
+;
+; ***************************************************************************
+; * This file is part of the project "AqHome". *
+; * Please see toplevel file COPYING of that project for license details. *
+; ***************************************************************************
+
+#ifndef AQH_AVR_DEVICE_C03_RESSOURCES_ASM
+#define AQH_AVR_DEVICE_C03_RESSOURCES_ASM
+
+.nolist
+.include "include/m644Pdef.inc" ; Define device ATmega644P
+.list
+
+.include "../defs.asm"
+.include "modules/lcd2/ili9341/colors.asm"
+.include "modules/lcd2/ili9341/images.asm"
+
+
+.cseg
+
+.org RESSOURCE_ADDR
+
+RessourceTable:
+ .dw 1
+ .dw (resImageNetwork*2) ; RESSSOURCE_IMG_NETWORK
+
+
+
+
+resImageNetwork:
+ .dw DISPLAY_IMAGETYPE_IDX2
+ .dw 48, 48
+ .dw (resImageNetworkColorMap*2)
+ .dw (resImageNetworkPixels*2)
+resImageNetworkColorMap:
+ .dw 4
+ .dw 0, DISPLAY_COLOR_BLACK, DISPLAY_COLOR_LIGHTGREY, DISPLAY_COLOR_LIGHTGREY
+resImageNetworkPixels:
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x55, 0x40, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40
+ .db 0x00, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x40
+ .db 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x05, 0x55, 0x54, 0x00, 0x00, 0x05, 0x55, 0x54, 0x00, 0x00
+ .db 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00
+ .db 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00
+ .db 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00
+ .db 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00
+ .db 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00
+ .db 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00
+ .db 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00, 0x07, 0xff, 0xf4, 0x00, 0x00
+ .db 0x00, 0x00, 0x05, 0x55, 0x54, 0x00, 0x00, 0x05, 0x55, 0x54, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ .db 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+
+
+
+#endif
+
+
diff --git a/avr/devices/c03/main/ressources.inc b/avr/devices/c03/main/ressources.inc
new file mode 100644
index 0000000..8df3f86
--- /dev/null
+++ b/avr/devices/c03/main/ressources.inc
@@ -0,0 +1,18 @@
+; ***************************************************************************
+; copyright : (C) 2025 by Martin Preuss
+; email : martin@libchipcard.de
+;
+; ***************************************************************************
+; * This file is part of the project "AqHome". *
+; * Please see toplevel file COPYING of that project for license details. *
+; ***************************************************************************
+
+#ifndef AQH_AVR_DEVICE_C03_RESSOURCES_INC
+#define AQH_AVR_DEVICE_C03_RESSOURCES_INC
+
+
+.equ RESSSOURCE_IMG_NETWORK = 0
+
+
+
+#endif ; AQH_AVR_DEVICE_C03_RESSOURCES_INC
diff --git a/avr/modules/lcd2/ili9341/images.asm b/avr/modules/lcd2/ili9341/images.asm
new file mode 100644
index 0000000..618c43c
--- /dev/null
+++ b/avr/modules/lcd2/ili9341/images.asm
@@ -0,0 +1,19 @@
+; ***************************************************************************
+; copyright : (C) 2025 by Martin Preuss
+; email : martin@libchipcard.de
+;
+; ***************************************************************************
+; * This file is part of the project "AqHome". *
+; * Please see toplevel file COPYING of that project for license details. *
+; ***************************************************************************
+
+#ifndef AQH_AVR_ILI9341_IMAGES_ASM
+#define AQH_AVR_ILI9341_IMAGES_ASM
+
+
+
+.equ DISPLAY_IMAGETYPE_IDX2 = 1 ; 2 bit indexed image
+
+
+
+#endif