From 31dda624741ca0cc0b819a953ab1eb59dc64b3fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Ryb=C3=A1rsky?= Date: Sun, 28 Dec 2025 12:23:11 +0100 Subject: [PATCH] really still wip --- ...b8de1c376c1e7394fcaec2d3f2322ffc-.snapshot | 1 + User/FreeRTOSConfig.h | 15 +- User/lib/adc/temperature.c | 250 +++++++++++++ User/lib/adc/temperature.h | 113 ++++++ User/lib/config.h | 33 +- User/lib/ed25519/ed_25519.h | 31 +- User/lib/ed25519/seed.c | 40 -- User/lib/ed25519/sign.c | 33 ++ User/lib/ed25519/verify.c | 35 ++ User/lib/telemetry/telemetry.c | 0 User/lib/telemetry/telemetry.h | 93 +++++ User/main.c | 135 +++++-- User/meshcore/meshcore.c | 60 +-- User/meshcore/meshcore.h | 2 +- User/meshcore/meshframing.c | 344 +++++++++++++++--- User/meshcore/meshframing.h | 14 +- User/meshcore/packets/ack.c | 3 +- User/meshcore/packets/advert.c | 262 ++++++------- User/meshcore/packets/advert.h | 8 +- User/meshcore/packets/anonymous.c | 141 +++++-- User/meshcore/packets/anonymous.h | 4 +- User/meshcore/packets/control.c | 143 ++++++-- User/meshcore/packets/control.h | 10 +- User/meshcore/packets/encrypted.c | 222 ++++++----- User/meshcore/packets/encrypted.h | 4 +- User/meshcore/packets/group.c | 86 ++--- User/meshcore/packets/group.h | 6 +- User/meshcore/packetstructs.h | 28 ++ User/meshcore/stats.c | 5 +- User/meshcore/stats.h | 4 + User/sx1262.c | 138 ++++--- User/sx1262.h | 6 +- User/util/log.h | 41 ++- 33 files changed, 1721 insertions(+), 589 deletions(-) create mode 100644 .mrs/b8de1c376c1e7394fcaec2d3f2322ffc-.snapshot create mode 100644 User/lib/adc/temperature.c create mode 100644 User/lib/adc/temperature.h delete mode 100644 User/lib/ed25519/seed.c create mode 100644 User/lib/telemetry/telemetry.c create mode 100644 User/lib/telemetry/telemetry.h diff --git a/.mrs/b8de1c376c1e7394fcaec2d3f2322ffc-.snapshot b/.mrs/b8de1c376c1e7394fcaec2d3f2322ffc-.snapshot new file mode 100644 index 0000000..3917de6 --- /dev/null +++ b/.mrs/b8de1c376c1e7394fcaec2d3f2322ffc-.snapshot @@ -0,0 +1 @@ +{"partsEditor":{"editorpart.state":{"serializedGrid":{"root":{"type":"branch","data":[{"type":"leaf","data":{"id":1,"editors":[{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshcore.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshcore.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshcore.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/sx1262.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/sx1262.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/sx1262.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/Debug/debug.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/Debug/debug.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/Debug/debug.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/main.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/main.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/main.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/control.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/control.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/control.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/encrypted.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/encrypted.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/encrypted.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/anonymous.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/anonymous.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/anonymous.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packetstructs.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packetstructs.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packetstructs.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/log.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/log.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/log.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/anonymous.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/anonymous.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/anonymous.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/stats.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/stats.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/stats.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/rtc/rtc.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/rtc/rtc.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/rtc/rtc.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/portable/Common/mpu_wrappers.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/portable/Common/mpu_wrappers.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/portable/Common/mpu_wrappers.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/task.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/task.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/task.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/mpu_prototypes.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/mpu_prototypes.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/mpu_prototypes.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/croutine.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/croutine.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/croutine.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/mpu_wrappers.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/mpu_wrappers.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/mpu_wrappers.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/tasks.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/tasks.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/tasks.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/advert.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/advert.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/advert.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/advert.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/advert.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/advert.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshframing.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshframing.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshframing.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/hmac.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/hmac.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/hmac.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/sha256.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/sha256.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/sha256.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/ed25519/verify.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/ed25519/verify.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/ed25519/verify.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/ed25519/sign.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/ed25519/sign.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/ed25519/sign.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshframing.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshframing.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshframing.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/group.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/group.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/group.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/stats.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/stats.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/stats.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/sx1262.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/sx1262.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/sx1262.c\",\"scheme\":\"file\"},\"encoding\":\"utf8\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/ack.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/ack.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/ack.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/FreeRTOSConfig.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/FreeRTOSConfig.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/FreeRTOSConfig.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/FreeRTOS.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/FreeRTOS.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/FreeRTOS.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/system_ch32v30x.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/system_ch32v30x.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/system_ch32v30x.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/system_ch32v30x.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/system_ch32v30x.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/system_ch32v30x.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_conf.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_conf.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_conf.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_it.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_it.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_it.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_it.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_it.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_it.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/Peripheral/inc/ch32v30x_tim.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/Peripheral/inc/ch32v30x_tim.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/Peripheral/inc/ch32v30x_tim.h\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"}],"mru":[6,9,20,7,5,22,21,29,3,25,26,4,18,28,1,24,23,0,27,19,8,10,11,30,2,15,14,31,17,12,13,16,32,37,36,35,34,33],"preview":7},"size":1853}],"size":761},"orientation":1,"width":1853,"height":761},"activeGroup":1,"mostRecentActiveGroups":[1]}},"textFileEditor":{"textEditorViewState":[["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/Peripheral/src/ch32v30x_adc.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1099,"column":5},"position":{"lineNumber":1099,"column":5}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1086,"column":1},"firstPositionDeltaTop":-6},"contributionsState":{"editor.contrib.folding":{"lineCount":1183,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":20654}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/adc/temperature.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":105,"column":26},"position":{"lineNumber":105,"column":26}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":11,"column":1},"firstPositionDeltaTop":-8},"contributionsState":{"editor.contrib.folding":{"lineCount":107,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":231}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/adc/temperature.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":164,"column":1},"position":{"lineNumber":164,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":157,"column":1},"firstPositionDeltaTop":-7},"contributionsState":{"editor.contrib.folding":{"lineCount":250,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/ed25519/license.txt",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":17,"provider":"indent","foldedImports":false},"editor.contrib.wordHighlighter":false}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/base64.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":23,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/hexdump.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":5,"column":6},"position":{"lineNumber":5,"column":13}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":24,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/hexdump.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":7,"column":67},"position":{"lineNumber":7,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":9,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/telemetry/telemetry.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":1,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/telemetry/telemetry.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":88,"column":13},"position":{"lineNumber":88,"column":16}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":69,"column":1},"firstPositionDeltaTop":-15},"contributionsState":{"editor.contrib.folding":{"lineCount":93,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1340}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/config.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":6,"column":13},"position":{"lineNumber":6,"column":13}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":33},"contributionsState":{"editor.contrib.folding":{"lineCount":81,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":true,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/config.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":19,"column":22},"position":{"lineNumber":19,"column":22}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":37,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":33}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/custom.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":3,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/multipart.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":4,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/trace.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":4,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/ack.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":8,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/control.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":14,"column":44},"position":{"lineNumber":14,"column":44}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":16,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/custom.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":6,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/multipart.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":4,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/trace.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":6,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshcore.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":14,"column":39},"position":{"lineNumber":14,"column":39}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":16,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/ed25519/ed_25519.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":17,"column":6},"position":{"lineNumber":17,"column":21}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":29,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/encrypted.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":21,"column":54},"position":{"lineNumber":21,"column":54}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":25,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/group.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":11,"column":5},"position":{"lineNumber":11,"column":5}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":15,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/system_ch32v30x.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":28,"column":1},"position":{"lineNumber":28,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":33,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_conf.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":27,"column":27},"position":{"lineNumber":27,"column":27}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":46,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_it.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":23,"column":17},"position":{"lineNumber":23,"column":17}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":247,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":33}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/ch32v30x_it.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":20,"column":1},"position":{"lineNumber":20,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":21,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/Peripheral/inc/ch32v30x_tim.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":24,"column":2},"position":{"lineNumber":24,"column":2}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":9,"column":1},"firstPositionDeltaTop":-19},"contributionsState":{"editor.contrib.folding":{"lineCount":518,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":212}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/system_ch32v30x.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":693,"column":2},"position":{"lineNumber":621,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":610,"column":1},"firstPositionDeltaTop":-7},"contributionsState":{"editor.contrib.folding":{"lineCount":1037,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":12220}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/mpu_wrappers.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":77,"column":60},"position":{"lineNumber":77,"column":69}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":58,"column":1},"firstPositionDeltaTop":-4},"contributionsState":{"editor.contrib.folding":{"lineCount":218,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1177}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/task.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":1855,"column":6},"position":{"lineNumber":1855,"column":15}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1836,"column":1},"firstPositionDeltaTop":-4},"contributionsState":{"editor.contrib.folding":{"lineCount":3113,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":36737}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/portable/Common/mpu_wrappers.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":323,"column":15},"position":{"lineNumber":323,"column":15}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":304,"column":1},"firstPositionDeltaTop":-10},"contributionsState":{"editor.contrib.folding":{"lineCount":1483,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":6103}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/tasks.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":4440,"column":28},"position":{"lineNumber":4440,"column":41}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":4429,"column":1},"firstPositionDeltaTop":-9},"contributionsState":{"editor.contrib.folding":{"lineCount":5443,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":88602}}}}],["file:///usr/share/MRS2/MRS-linux-x64/resources/app/resources/linux/components/WCH/Toolchain/RISC-V%20Embedded%20GCC12/riscv-wch-elf/include/stdio.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":200,"column":5},"position":{"lineNumber":200,"column":11}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":188,"column":1},"firstPositionDeltaTop":-5},"contributionsState":{"editor.contrib.folding":{"lineCount":804,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":3745}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/FreeRTOS.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":1002,"column":43},"position":{"lineNumber":1002,"column":55}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":983,"column":1},"firstPositionDeltaTop":-4},"contributionsState":{"editor.contrib.folding":{"lineCount":1363,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":19644}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/mpu_prototypes.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":261,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/croutine.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":122,"column":4},"position":{"lineNumber":122,"column":16}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":113,"column":1},"firstPositionDeltaTop":-16},"contributionsState":{"editor.contrib.folding":{"lineCount":754,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":2256}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/Debug/debug.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":45,"column":12},"position":{"lineNumber":45,"column":18}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":26,"column":1},"firstPositionDeltaTop":-4},"contributionsState":{"editor.contrib.folding":{"lineCount":56,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":537}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/FreeRTOSConfig.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":102,"column":50},"position":{"lineNumber":102,"column":50}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":82,"column":1},"firstPositionDeltaTop":-13},"contributionsState":{"editor.contrib.folding":{"lineCount":157,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1666}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/rtc/rtc.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":205,"column":23},"position":{"lineNumber":205,"column":23}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":191,"column":1},"firstPositionDeltaTop":-10},"contributionsState":{"editor.contrib.folding":{"lineCount":293,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":3843}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/Peripheral/src/ch32v30x_rtc.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":73,"column":10},"position":{"lineNumber":73,"column":10}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":58,"column":1},"firstPositionDeltaTop":-12},"contributionsState":{"editor.contrib.folding":{"lineCount":316,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1185}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/FreeRTOS/include/projdefs.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":43,"column":7},"position":{"lineNumber":38,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":30,"column":1},"firstPositionDeltaTop":-5},"contributionsState":{"editor.contrib.folding":{"lineCount":123,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":618}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/stats.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":6,"column":26},"position":{"lineNumber":6,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":6,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/log.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":34,"column":1},"position":{"lineNumber":34,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":34,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":33}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/advert.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":6,"column":39},"position":{"lineNumber":6,"column":39}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":14,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/stats.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":5,"column":16},"position":{"lineNumber":5,"column":16}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":11,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshcore.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":65,"column":42},"position":{"lineNumber":65,"column":47}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":14,"column":1},"firstPositionDeltaTop":-5},"contributionsState":{"editor.contrib.folding":{"lineCount":79,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":298}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/ed25519/verify.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":59,"column":18},"position":{"lineNumber":59,"column":18}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":46,"column":1},"firstPositionDeltaTop":-6},"contributionsState":{"editor.contrib.folding":{"lineCount":112,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":939}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/ed25519/sign.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":63,"column":2},"position":{"lineNumber":63,"column":2}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":38,"column":1},"firstPositionDeltaTop":-2},"contributionsState":{"editor.contrib.folding":{"lineCount":65,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":775}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/sx1262.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":435,"column":8},"position":{"lineNumber":435,"column":8}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":390,"column":1},"firstPositionDeltaTop":-12},"contributionsState":{"editor.contrib.folding":{"lineCount":438,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":7403}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/sx1262.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":159,"column":42},"position":{"lineNumber":134,"column":5}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":120,"column":1},"firstPositionDeltaTop":-12},"contributionsState":{"editor.contrib.folding":{"lineCount":919,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":2273}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/advert.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":95,"column":17},"position":{"lineNumber":95,"column":17}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":68,"column":1},"firstPositionDeltaTop":-8},"contributionsState":{"editor.contrib.folding":{"lineCount":209,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1281}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/control.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":71,"column":17},"position":{"lineNumber":71,"column":17}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":44,"column":1},"firstPositionDeltaTop":-8},"contributionsState":{"editor.contrib.folding":{"lineCount":145,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":825}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/group.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":48,"column":17},"position":{"lineNumber":48,"column":17}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":21,"column":1},"firstPositionDeltaTop":-8},"contributionsState":{"editor.contrib.folding":{"lineCount":112,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":388}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshframing.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":28,"column":45},"position":{"lineNumber":28,"column":45}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":37,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/main.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":204,"column":22},"position":{"lineNumber":204,"column":22}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":121,"column":1},"firstPositionDeltaTop":-12},"contributionsState":{"editor.contrib.folding":{"lineCount":304,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":2292}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/ack.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":21,"column":7},"position":{"lineNumber":21,"column":7}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":12,"column":1},"firstPositionDeltaTop":-3},"contributionsState":{"editor.contrib.folding":{"lineCount":43,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":212}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/hmac.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":113,"column":30},"position":{"lineNumber":113,"column":30}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":93,"column":1},"firstPositionDeltaTop":-15},"contributionsState":{"editor.contrib.folding":{"lineCount":118,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1796}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/sha256.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":224,"column":20},"position":{"lineNumber":224,"column":20}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":211,"column":1},"firstPositionDeltaTop":-11},"contributionsState":{"editor.contrib.folding":{"lineCount":232,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":4034}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/sha2.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":127,"column":23},"position":{"lineNumber":127,"column":23}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":114,"column":1},"firstPositionDeltaTop":-11},"contributionsState":{"editor.contrib.folding":{"lineCount":236,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":2191}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/encrypted.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":52,"column":17},"position":{"lineNumber":52,"column":17}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":25,"column":1},"firstPositionDeltaTop":-8},"contributionsState":{"editor.contrib.folding":{"lineCount":359,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":497}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packetstructs.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":67,"column":26},"position":{"lineNumber":67,"column":26}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":55,"column":1},"firstPositionDeltaTop":-11},"contributionsState":{"editor.contrib.folding":{"lineCount":232,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1070}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshframing.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":465,"column":7},"position":{"lineNumber":465,"column":7}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":436,"column":1},"firstPositionDeltaTop":-9},"contributionsState":{"editor.contrib.folding":{"lineCount":472,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":8274}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/anonymous.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":7,"column":8},"position":{"lineNumber":7,"column":8}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":11,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/anonymous.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":180,"column":69},"position":{"lineNumber":180,"column":69}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":171,"column":1},"firstPositionDeltaTop":-9},"contributionsState":{"editor.contrib.folding":{"lineCount":211,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":3239}}}}]]},"labeledBookmarks":{"vscLabeledBookmarks.groups":[{"name":"bookmark","color":"865fc5ff","shape":"bookmark","iconText":"bookmark"}],"vscLabeledBookmarks.bookmarks":[],"vscLabeledBookmarks.activeGroup":"bookmark","vscLabeledBookmarks.hideInactiveGroups":false,"vscLabeledBookmarks.hideAll":false}} \ No newline at end of file diff --git a/User/FreeRTOSConfig.h b/User/FreeRTOSConfig.h index 4500086..79e07ff 100644 --- a/User/FreeRTOSConfig.h +++ b/User/FreeRTOSConfig.h @@ -90,26 +90,28 @@ #define configMTIME_BASE_ADDRESS ( 0 ) #define configMTIMECMP_BASE_ADDRESS ( 0 ) +#define INCLUDE_uxTaskGetStackHighWaterMark 1 + #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 #define configUSE_TICK_HOOK 0 #define configCPU_CLOCK_HZ SystemCoreClock #define configTICK_RATE_HZ ( ( TickType_t ) 500 ) #define configMAX_PRIORITIES ( 15 ) -#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 1024 ) /* Can be as low as 60 but some of the demo tasks that use this constant require it to be higher. */ -#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 32 * 1024 ) ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 512 ) /* Can be as low as 60 but some of the demo tasks that use this constant require it to be higher. */ +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 24* 1024 ) ) #define configMAX_TASK_NAME_LEN ( 16 ) -#define configUSE_TRACE_FACILITY 0 +#define configUSE_TRACE_FACILITY 1 #define configUSE_16_BIT_TICKS 0 #define configIDLE_SHOULD_YIELD 0 #define configUSE_MUTEXES 1 #define configQUEUE_REGISTRY_SIZE 8 -#define configCHECK_FOR_STACK_OVERFLOW 1 +#define configCHECK_FOR_STACK_OVERFLOW 2 #define configUSE_RECURSIVE_MUTEXES 1 #define configUSE_MALLOC_FAILED_HOOK 0 #define configUSE_APPLICATION_TASK_TAG 0 #define configUSE_COUNTING_SEMAPHORES 1 -#define configGENERATE_RUN_TIME_STATS 0 +#define configGENERATE_RUN_TIME_STATS 1 #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 /* Co-routine definitions. */ @@ -139,6 +141,7 @@ to exclude the API function. */ #define INCLUDE_xTaskGetHandle 1 #define INCLUDE_xSemaphoreGetMutexHolder 1 +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 /* Normal assert() semantics without relying on the provision of an assert.h header file. */ @@ -147,5 +150,7 @@ header file. */ /* Map to the platform printf function. */ #define configPRINT_STRING( pcString ) printf( pcString ) +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats() +#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() #endif /* FREERTOS_CONFIG_H */ diff --git a/User/lib/adc/temperature.c b/User/lib/adc/temperature.c new file mode 100644 index 0000000..cc0d4ce --- /dev/null +++ b/User/lib/adc/temperature.c @@ -0,0 +1,250 @@ +/********************************** (C) COPYRIGHT ******************************* +* File Name : temperature.c +* Author : WCH +* Version : V1.0.0 +* Date : 2023/11/17 +* Description : Temperature program body. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ + +/* + *@Note + *Internal temperature sensor routine: + *Through the ADC channel 16, the output voltage value and temperature value of the internal + *temperature sensor are collected. + * + */ + +#include "debug.h" +#include "lib/telemetry/telemetry.h" + +/* Global Variable */ +s16 Calibrattion_Val = 0; + +/********************************************************************* + * @fn ADC_Function_Init + * + * @brief Initializes ADC collection. + * + * @return none + */ +void ADC_Function_Init(void) +{ + ADC_InitTypeDef ADC_InitStructure={0}; + + RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE ); + RCC_ADCCLKConfig(RCC_PCLK2_Div8); + + ADC_DeInit(ADC1); + ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; + ADC_InitStructure.ADC_ScanConvMode = DISABLE; + ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; + ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; + ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; + ADC_InitStructure.ADC_NbrOfChannel = 1; + ADC_Init(ADC1, &ADC_InitStructure); + + ADC_Cmd(ADC1, ENABLE); + + ADC_BufferCmd(ADC1, DISABLE); //disable buffer + ADC_ResetCalibration(ADC1); + while(ADC_GetResetCalibrationStatus(ADC1)); + ADC_StartCalibration(ADC1); + while(ADC_GetCalibrationStatus(ADC1)); + Calibrattion_Val = Get_CalibrationValue(ADC1); + + ADC_BufferCmd(ADC1, ENABLE); //enable buffer + + ADC_TempSensorVrefintCmd(ENABLE); +} + +/********************************************************************* + * @fn Get_ADC_Val + * + * @brief Returns ADCx conversion result data. + * + * @param ch - ADC channel. + * ADC_Channel_0 - ADC Channel0 selected. + * ADC_Channel_1 - ADC Channel1 selected. + * ADC_Channel_2 - ADC Channel2 selected. + * ADC_Channel_3 - ADC Channel3 selected. + * ADC_Channel_4 - ADC Channel4 selected. + * ADC_Channel_5 - ADC Channel5 selected. + * ADC_Channel_6 - ADC Channel6 selected. + * ADC_Channel_7 - ADC Channel7 selected. + * ADC_Channel_8 - ADC Channel8 selected. + * ADC_Channel_9 - ADC Channel9 selected. + * ADC_Channel_10 - ADC Channel10 selected. + * ADC_Channel_11 - ADC Channel11 selected. + * ADC_Channel_12 - ADC Channel12 selected. + * ADC_Channel_13 - ADC Channel13 selected. + * ADC_Channel_14 - ADC Channel14 selected. + * ADC_Channel_15 - ADC Channel15 selected. + * ADC_Channel_16 - ADC Channel16 selected. + * ADC_Channel_17 - ADC Channel17 selected. + * + * @return none + */ +u16 Get_ADC_Val(u8 ch) +{ + u16 val; + + ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); + ADC_SoftwareStartConvCmd(ADC1, ENABLE); + + while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC )); + + val = ADC_GetConversionValue(ADC1); + + return val; +} + +/********************************************************************* + * @fn Get_ADC_Average + * + * @brief Returns ADCx conversion result average data. + * + * @param ch - ADC channel. + * ADC_Channel_0 - ADC Channel0 selected. + * ADC_Channel_1 - ADC Channel1 selected. + * ADC_Channel_2 - ADC Channel2 selected. + * ADC_Channel_3 - ADC Channel3 selected. + * ADC_Channel_4 - ADC Channel4 selected. + * ADC_Channel_5 - ADC Channel5 selected. + * ADC_Channel_6 - ADC Channel6 selected. + * ADC_Channel_7 - ADC Channel7 selected. + * ADC_Channel_8 - ADC Channel8 selected. + * ADC_Channel_9 - ADC Channel9 selected. + * ADC_Channel_10 - ADC Channel10 selected. + * ADC_Channel_11 - ADC Channel11 selected. + * ADC_Channel_12 - ADC Channel12 selected. + * ADC_Channel_13 - ADC Channel13 selected. + * ADC_Channel_14 - ADC Channel14 selected. + * ADC_Channel_15 - ADC Channel15 selected. + * ADC_Channel_16 - ADC Channel16 selected. + * ADC_Channel_17 - ADC Channel17 selected. + * + * @return val - The Data conversion value. + */ +u16 Get_ADC_Average(u8 ch,u8 times) +{ + u32 temp_val=0; + u8 t; + u16 val; + + for(t=0;t4095||val==4095) return 4095; + return (val+Calibrattion_Val); +} + +s32 TempSensor_Volt_To_Temper_x10(s32 Value) +{ + s32 Temper_x10; + s32 Refer_Volt, Refer_Temper; + s32 k = 43; // slope in mV/ˇăC + + // Read factory calibration values + Refer_Volt = (s32)((*(u32 *)0x1FFFF720) & 0x0000FFFF); // mV at reference temp + Refer_Temper = (s32)(((*(u32 *)0x1FFFF720) >> 16) & 0x0000FFFF); // ˇăC + + // Compute temperature in decicelsius + // Formula: T_x10 = Tref*10 - ((V - Vref)*100 + k/2) / k + // Multiply (V - Vref) by 100 to get tenths of ˇăC + Temper_x10 = Refer_Temper * 10 - ((Value - Refer_Volt) * 100 + (k / 2)) / k; + + return Temper_x10; +} + + +s32 getTemperature(void) +{ + u16 ADC_val; + s32 val_mv; + + ADC_val = Get_ADC_Average( ADC_Channel_TempSensor, 10 ); + + ADC_val = Get_ConversionVal(ADC_val); + + val_mv = (ADC_val*3300/4096); + + return TempSensor_Volt_To_Temper(val_mv); +} + +s16 getDeciTemperature(void) +{ + u16 ADC_val; + s32 val_mv; + + ADC_val = Get_ADC_Average( ADC_Channel_TempSensor, 10 ); + + ADC_val = Get_ConversionVal(ADC_val); + + val_mv = (ADC_val*3300/4096); + + s32 temp_x10 = TempSensor_Volt_To_Temper_x10(val_mv); + + int16_t temp16 = (int16_t)temp_x10; // store in 2 bytes + return temp16; +} + +s32 getVoltage(void) +{ + u16 ADC_val; + s32 val_mv; + + ADC_val = Get_ADC_Average( ADC_Channel_0, 10 ); + + ADC_val = Get_ConversionVal(ADC_val); + + + val_mv = (ADC_val*3300/4096); + + return val_mv; +} + +// Helper: convert signed 24-bit int to 3 bytes (big-endian) +void int24_to_bytes(int32_t value, uint8_t *bytes) { + if (value < 0) value += 0x1000000; // 2's complement for 24-bit + bytes[0] = (value >> 16) & 0xFF; + bytes[1] = (value >> 8) & 0xFF; + bytes[2] = value & 0xFF; +} + +// Encode GPS into CayenneLPP payload +void encode_gps(uint8_t channel, float lat, float lon, float alt, uint8_t *payload) { + payload[0] = channel; + payload[1] = LPP_GPS; // GPS type + + int32_t latInt = lat * 10000; + int32_t lonInt = lon * 10000; + int32_t altInt = alt * 100; + + int24_to_bytes(latInt, &payload[2]); + int24_to_bytes(lonInt, &payload[5]); + int24_to_bytes(altInt, &payload[8]); +} \ No newline at end of file diff --git a/User/lib/adc/temperature.h b/User/lib/adc/temperature.h new file mode 100644 index 0000000..c8af627 --- /dev/null +++ b/User/lib/adc/temperature.h @@ -0,0 +1,113 @@ +#ifndef TEMPERATURE_HEADER +#define TEMPERATURE_HEADER + +/********************************** (C) COPYRIGHT ******************************* +* File Name : temperature.c +* Author : WCH +* Version : V1.0.0 +* Date : 2023/11/17 +* Description : Temperature program body. +********************************************************************************* +* Copyright (c) 2021 Nanjing Qinheng Microelectronics Co., Ltd. +* Attention: This software (modified or not) and binary are used for +* microcontroller manufactured by Nanjing Qinheng Microelectronics. +*******************************************************************************/ + +/* + *@Note + *Internal temperature sensor routine: + *Through the ADC channel 16, the output voltage value and temperature value of the internal + *temperature sensor are collected. + * + */ + +/* Global Variable */ +extern s16 Calibrattion_Val; + +/********************************************************************* + * @fn ADC_Function_Init + * + * @brief Initializes ADC collection. + * + * @return none + */ +void ADC_Function_Init(void); + +/********************************************************************* + * @fn Get_ADC_Val + * + * @brief Returns ADCx conversion result data. + * + * @param ch - ADC channel. + * ADC_Channel_0 - ADC Channel0 selected. + * ADC_Channel_1 - ADC Channel1 selected. + * ADC_Channel_2 - ADC Channel2 selected. + * ADC_Channel_3 - ADC Channel3 selected. + * ADC_Channel_4 - ADC Channel4 selected. + * ADC_Channel_5 - ADC Channel5 selected. + * ADC_Channel_6 - ADC Channel6 selected. + * ADC_Channel_7 - ADC Channel7 selected. + * ADC_Channel_8 - ADC Channel8 selected. + * ADC_Channel_9 - ADC Channel9 selected. + * ADC_Channel_10 - ADC Channel10 selected. + * ADC_Channel_11 - ADC Channel11 selected. + * ADC_Channel_12 - ADC Channel12 selected. + * ADC_Channel_13 - ADC Channel13 selected. + * ADC_Channel_14 - ADC Channel14 selected. + * ADC_Channel_15 - ADC Channel15 selected. + * ADC_Channel_16 - ADC Channel16 selected. + * ADC_Channel_17 - ADC Channel17 selected. + * + * @return none + */ +u16 Get_ADC_Val(u8 ch); + +/********************************************************************* + * @fn Get_ADC_Average + * + * @brief Returns ADCx conversion result average data. + * + * @param ch - ADC channel. + * ADC_Channel_0 - ADC Channel0 selected. + * ADC_Channel_1 - ADC Channel1 selected. + * ADC_Channel_2 - ADC Channel2 selected. + * ADC_Channel_3 - ADC Channel3 selected. + * ADC_Channel_4 - ADC Channel4 selected. + * ADC_Channel_5 - ADC Channel5 selected. + * ADC_Channel_6 - ADC Channel6 selected. + * ADC_Channel_7 - ADC Channel7 selected. + * ADC_Channel_8 - ADC Channel8 selected. + * ADC_Channel_9 - ADC Channel9 selected. + * ADC_Channel_10 - ADC Channel10 selected. + * ADC_Channel_11 - ADC Channel11 selected. + * ADC_Channel_12 - ADC Channel12 selected. + * ADC_Channel_13 - ADC Channel13 selected. + * ADC_Channel_14 - ADC Channel14 selected. + * ADC_Channel_15 - ADC Channel15 selected. + * ADC_Channel_16 - ADC Channel16 selected. + * ADC_Channel_17 - ADC Channel17 selected. + * + * @return val - The Data conversion value. + */ +u16 Get_ADC_Average(u8 ch,u8 times); + +/********************************************************************* + * @fn Get_ConversionVal + * + * @brief Get Conversion Value. + * + * @param val - Sampling value + * + * @return val+Calibrattion_Val - Conversion Value. + */ +u16 Get_ConversionVal(s16 val); + +s32 getTemperature(void); + +s16 getDeciTemperature(void); + +s32 getVoltage(void); + +void encode_gps(uint8_t channel, float lat, float lon, float alt, uint8_t *payload); + +#endif \ No newline at end of file diff --git a/User/lib/config.h b/User/lib/config.h index 7efe9d2..cce2714 100644 --- a/User/lib/config.h +++ b/User/lib/config.h @@ -9,32 +9,23 @@ #define AESKeyCount 8 #define CONTACT_COUNT 100 -typedef struct { - char name[32]; - unsigned char pubKey[32]; - unsigned char secret[32]; - - int32_t gps_latitude; - int32_t gps_longitude; - - Path path; - - uint8_t flags; - uint8_t type; - - uint8_t authenticated; - - uint32_t last_seen_rt; //remote timestamp - uint32_t last_seen_lt; //local timestamp - - uint32_t sync_timestamp; -} NodeEntry; - typedef struct { uint32_t magic; // e.g. 0xDEADBEEF uint8_t privkey[32]; // Ed25519 private uint8_t pubkey[32]; // Ed25519 public uint8_t nodeType; + int32_t latitude; + int32_t longitude; + int32_t altitude; + + int8_t txPowerInDbm; + uint32_t frequencyInHz; + uint8_t spreadingFactor; + uint8_t bandwidth; + uint8_t codingRate; + uint16_t preambleLength; + float tcxoVoltage; + uint8_t aesKeys[AESKeyCount][17]; uint8_t password[16]; char nodeName[32]; diff --git a/User/lib/ed25519/ed_25519.h b/User/lib/ed25519/ed_25519.h index 5ac015e..39f6415 100644 --- a/User/lib/ed25519/ed_25519.h +++ b/User/lib/ed25519/ed_25519.h @@ -4,34 +4,21 @@ // Nightcracker's Ed25519 - https://github.com/orlp/ed25519 #include - -#if defined(_WIN32) - #if defined(ED25519_BUILD_DLL) - #define ED25519_DECLSPEC __declspec(dllexport) - #elif defined(ED25519_DLL) - #define ED25519_DECLSPEC __declspec(dllimport) - #else - #define ED25519_DECLSPEC - #endif -#else - #define ED25519_DECLSPEC -#endif - +#include "meshcore/packetstructs.h" #ifdef __cplusplus extern "C" { #endif -#ifndef ED25519_NO_SEED -int ED25519_DECLSPEC ed25519_create_seed(unsigned char *seed); -#endif -void ED25519_DECLSPEC ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed); -void ED25519_DECLSPEC ed25519_derive_pub(unsigned char *public_key, const unsigned char *private_key); -void ED25519_DECLSPEC ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key); -int ED25519_DECLSPEC ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key); -void ED25519_DECLSPEC ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); -void ED25519_DECLSPEC ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key); +void ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed); +void ed25519_derive_pub(unsigned char *public_key, const unsigned char *private_key); +void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key); +void ed25519_sign_ad(FrameStruct *frame); +int ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key); +int ed25519_verify_ad(const FrameStruct *frame); +void ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar); +void ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key); #ifdef __cplusplus diff --git a/User/lib/ed25519/seed.c b/User/lib/ed25519/seed.c deleted file mode 100644 index 95ddc98..0000000 --- a/User/lib/ed25519/seed.c +++ /dev/null @@ -1,40 +0,0 @@ -#include "ed_25519.h" - -#ifndef ED25519_NO_SEED - -#ifdef _WIN32 -#include -#include -#else -#include -#endif - -int ed25519_create_seed(unsigned char *seed) { -#ifdef _WIN32 - HCRYPTPROV prov; - - if (!CryptAcquireContext(&prov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - return 1; - } - - if (!CryptGenRandom(prov, 32, seed)) { - CryptReleaseContext(prov, 0); - return 1; - } - - CryptReleaseContext(prov, 0); -#else - FILE *f = fopen("/dev/urandom", "rb"); - - if (f == NULL) { - return 1; - } - - fread(seed, 1, 32, f); - fclose(f); -#endif - - return 0; -} - -#endif diff --git a/User/lib/ed25519/sign.c b/User/lib/ed25519/sign.c index 463b02b..f897846 100644 --- a/User/lib/ed25519/sign.c +++ b/User/lib/ed25519/sign.c @@ -1,4 +1,5 @@ #include "ed_25519.h" +#include "lib/config.h" #include "sha512.h" #include "ge.h" #include "sc.h" @@ -29,3 +30,35 @@ void ed25519_sign(unsigned char *signature, const unsigned char *message, size_t sc_reduce(hram); sc_muladd(signature + 32, hram, private_key, r); } + +void ed25519_sign_ad(FrameStruct *frame) { + sha512_context hash; + unsigned char hram[64]; + unsigned char r[64]; + ge_p3 R; + + unsigned char *signature = &(frame->payload[36]); + + + sha512_init(&hash); + sha512_update(&hash, persistent.privkey + 32, 32); + sha512_update(&hash, frame->payload, 32); + sha512_update(&hash, frame->payload, 36); // pubkey and timestamp combined (32 bytes pubkey, 4 bytes timestamp) + sha512_update(&hash, &(frame->payload[100]), frame->payloadLen - 100); + sha512_final(&hash, r); + + sc_reduce(r); + ge_scalarmult_base(&R, r); + ge_p3_tobytes(signature, &R); + + sha512_init(&hash); + sha512_update(&hash, signature, 32); + sha512_update(&hash, frame->payload, 32); + sha512_update(&hash, frame->payload, 36); // pubkey and timestamp combined (32 bytes pubkey, 4 bytes timestamp) + sha512_update(&hash, &(frame->payload[100]), frame->payloadLen - 100); + sha512_final(&hash, hram); + + sc_reduce(hram); + sc_muladd(signature + 32, hram, persistent.privkey, r); +} + diff --git a/User/lib/ed25519/verify.c b/User/lib/ed25519/verify.c index 4d8de25..b02a0c7 100644 --- a/User/lib/ed25519/verify.c +++ b/User/lib/ed25519/verify.c @@ -75,3 +75,38 @@ int ed25519_verify(const unsigned char *signature, const unsigned char *message, return 1; } + + +int ed25519_verify_ad(const FrameStruct *frame) { + unsigned char h[64]; + unsigned char checker[32]; + sha512_context hash; + ge_p3 A; + ge_p2 R; + const unsigned char *signature = &(frame->payload[36]); + + if (signature[63] & 224) { + return 0; + } + + if (ge_frombytes_negate_vartime(&A, frame->payload) != 0) { //pubkey is at start + return 0; + } + + sha512_init(&hash); + sha512_update(&hash, signature, 32); + sha512_update(&hash, frame->payload, 32); + sha512_update(&hash, frame->payload, 36); // pubkey and timestamp combined (32 bytes pubkey, 4 bytes timestamp) + sha512_update(&hash, &(frame->payload[100]), frame->payloadLen - 100); + sha512_final(&hash, h); + + sc_reduce(h); + ge_double_scalarmult_vartime(&R, h, &A, signature + 32); + ge_tobytes(checker, &R); + + if (!consttime_equal(checker, signature)) { + return 0; + } + + return 1; +} \ No newline at end of file diff --git a/User/lib/telemetry/telemetry.c b/User/lib/telemetry/telemetry.c new file mode 100644 index 0000000..e69de29 diff --git a/User/lib/telemetry/telemetry.h b/User/lib/telemetry/telemetry.h new file mode 100644 index 0000000..447093b --- /dev/null +++ b/User/lib/telemetry/telemetry.h @@ -0,0 +1,93 @@ +#ifndef TELEMETRY_HEADER +#define TELEMETRY_HEADER + +#define TELEM_CHANNEL_SELF 1 // LPP data channel for 'self' device + +#define LPP_DIGITAL_INPUT 0 // 1 byte +#define LPP_DIGITAL_OUTPUT 1 // 1 byte +#define LPP_ANALOG_INPUT 2 // 2 bytes, 0.01 signed +#define LPP_ANALOG_OUTPUT 3 // 2 bytes, 0.01 signed +#define LPP_GENERIC_SENSOR 100 // 4 bytes, unsigned +#define LPP_LUMINOSITY 101 // 2 bytes, 1 lux unsigned +#define LPP_PRESENCE 102 // 1 byte, bool +#define LPP_TEMPERATURE 103 // 2 bytes, 0.1ˇăC signed +#define LPP_RELATIVE_HUMIDITY 104 // 1 byte, 0.5% unsigned +#define LPP_ACCELEROMETER 113 // 2 bytes per axis, 0.001G +#define LPP_BAROMETRIC_PRESSURE 115 // 2 bytes 0.1hPa unsigned +#define LPP_VOLTAGE 116 // 2 bytes 0.01V unsigned +#define LPP_CURRENT 117 // 2 bytes 0.001A unsigned +#define LPP_FREQUENCY 118 // 4 bytes 1Hz unsigned +#define LPP_PERCENTAGE 120 // 1 byte 1-100% unsigned +#define LPP_ALTITUDE 121 // 2 byte 1m signed +#define LPP_CONCENTRATION 125 // 2 bytes, 1 ppm unsigned +#define LPP_POWER 128 // 2 byte, 1W, unsigned +#define LPP_DISTANCE 130 // 4 byte, 0.001m, unsigned +#define LPP_ENERGY 131 // 4 byte, 0.001kWh, unsigned +#define LPP_DIRECTION 132 // 2 bytes, 1deg, unsigned +#define LPP_UNIXTIME 133 // 4 bytes, unsigned +#define LPP_GYROMETER 134 // 2 bytes per axis, 0.01 ˇă/s +#define LPP_COLOUR 135 // 1 byte per RGB Color +#define LPP_GPS 136 // 3 byte lon/lat 0.0001 ˇă, 3 bytes alt 0.01 meter +#define LPP_SWITCH 142 // 1 byte, 0/1 +#define LPP_POLYLINE 240 // 1 byte size, 1 byte delta factor, 3 byte lon/lat 0.0001ˇă * factor, n (size-8) bytes deltas + +// Only Data Size +#define LPP_DIGITAL_INPUT_SIZE 1 +#define LPP_DIGITAL_OUTPUT_SIZE 1 +#define LPP_ANALOG_INPUT_SIZE 2 +#define LPP_ANALOG_OUTPUT_SIZE 2 +#define LPP_GENERIC_SENSOR_SIZE 4 +#define LPP_LUMINOSITY_SIZE 2 +#define LPP_PRESENCE_SIZE 1 +#define LPP_TEMPERATURE_SIZE 2 +#define LPP_RELATIVE_HUMIDITY_SIZE 1 +#define LPP_ACCELEROMETER_SIZE 6 +#define LPP_BAROMETRIC_PRESSURE_SIZE 2 +#define LPP_VOLTAGE_SIZE 2 +#define LPP_CURRENT_SIZE 2 +#define LPP_FREQUENCY_SIZE 4 +#define LPP_PERCENTAGE_SIZE 1 +#define LPP_ALTITUDE_SIZE 2 +#define LPP_POWER_SIZE 2 +#define LPP_DISTANCE_SIZE 4 +#define LPP_ENERGY_SIZE 4 +#define LPP_DIRECTION_SIZE 2 +#define LPP_UNIXTIME_SIZE 4 +#define LPP_GYROMETER_SIZE 6 +#define LPP_GPS_SIZE 9 +#define LPP_SWITCH_SIZE 1 +#define LPP_CONCENTRATION_SIZE 2 +#define LPP_COLOUR_SIZE 3 +#define LPP_MIN_POLYLINE_SIZE 8 + + +// Multipliers +#define LPP_DIGITAL_INPUT_MULT 1 +#define LPP_DIGITAL_OUTPUT_MULT 1 +#define LPP_ANALOG_INPUT_MULT 100 +#define LPP_ANALOG_OUTPUT_MULT 100 +#define LPP_GENERIC_SENSOR_MULT 1 +#define LPP_LUMINOSITY_MULT 1 +#define LPP_PRESENCE_MULT 1 +#define LPP_TEMPERATURE_MULT 10 +#define LPP_RELATIVE_HUMIDITY_MULT 2 +#define LPP_ACCELEROMETER_MULT 1000 +#define LPP_BAROMETRIC_PRESSURE_MULT 10 +#define LPP_VOLTAGE_MULT 100 +#define LPP_CURRENT_MULT 1000 +#define LPP_FREQUENCY_MULT 1 +#define LPP_PERCENTAGE_MULT 1 +#define LPP_ALTITUDE_MULT 1 +#define LPP_POWER_MULT 1 +#define LPP_DISTANCE_MULT 1000 +#define LPP_ENERGY_MULT 1000 +#define LPP_DIRECTION_MULT 1 +#define LPP_UNIXTIME_MULT 1 +#define LPP_GYROMETER_MULT 100 +#define LPP_GPS_LAT_LON_MULT 10000 +#define LPP_GPS_ALT_MULT 100 +#define LPP_SWITCH_MULT 1 +#define LPP_CONCENTRATION_MULT 1 +#define LPP_COLOUR_MULT 1 + +#endif \ No newline at end of file diff --git a/User/main.c b/User/main.c index db6157a..d462973 100644 --- a/User/main.c +++ b/User/main.c @@ -18,24 +18,52 @@ #include "FreeRTOS.h" #include "meshcore/meshframing.h" #include "meshcore/packets/advert.h" +#include "meshcore/packets/control.h" #include "meshcore/packets/encrypted.h" #include "meshcore/packets/group.h" #include "task.h" #include "meshcore/packetstructs.h" #include "sx1262.h" +#include "util/hexdump.h" #include "util/log.h" #include "string.h" #include "meshcore/meshcore.h" #include "lib/config.h" #include "lib/rtc/rtc.h" #include "lib/ed25519/ed_25519.h" +#include "meshcore/stats.h" +#include "lib/adc/temperature.h" #define TAG "MeshCore" + +static TIM_TypeDef *runtimeTIM = TIM2; // use TIM2 for example + +void vConfigureTimerForRunTimeStats (void) { + TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; + + // Reset the timer + TIM_DeInit (runtimeTIM); + + // Set timer for max period, upcounting + TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; // Assuming 72 MHz clock -> 1 MHz timer tick (1 ?s) + TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; + TIM_TimeBaseStructure.TIM_Period = 0xFFFF; // Max 16-bit value + TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; + TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; + + TIM_TimeBaseInit (runtimeTIM, &TIM_TimeBaseStructure); + TIM_Cmd (runtimeTIM, ENABLE); +} + +uint32_t ulGetRunTimeCounterValue (void) { + return TIM_GetCounter (runtimeTIM); +} + /* Global define */ #define TASK1_TASK_PRIO 5 -#define TASK1_STK_SIZE 2048 +#define TASK1_STK_SIZE 1024 /* Global Variable */ TaskHandle_t Task1Task_Handler; @@ -51,13 +79,21 @@ TaskHandle_t Task2Task_Handler; * @return none */ -uint8_t bufIn[256]; +// uint8_t bufIn[260]; void task2_task (void *pvParameters) { + MESH_LOGD (TAG, "Task2 boot0"); RTC_Init(); - //ed25519_create_keypair (persistent.pubkey, persistent.privkey, "vFt0FRugSOeqnkshImMCVfgHM5vBxz4"); + startupTime = RTC_GetCounter(); + memset (&stats, 0, sizeof (stats)); + MESH_LOGD (TAG, "Task2 boot1"); + + ADC_Function_Init(); + MESH_LOGD (TAG, "Task2 boot2"); + // ed25519_create_keypair (persistent.pubkey, persistent.privkey, "vFt0FRugSOeqnkshImMCVfgHM5vBxz4"); ed25519_create_keypair (persistent.pubkey, persistent.privkey, "vFt0FRugSOeqnkshImMCVfgHM5vBxz3"); -// persistent.nodeType = NODE_TYPE_CHAT_NODE; + MESH_LOGD (TAG, "Task2 boot3"); + // persistent.nodeType = NODE_TYPE_CHAT_NODE; persistent.nodeType = NODE_TYPE_REPEATER; memset (persistent.password, 0, sizeof (persistent.password)); strcpy (persistent.password, "hesielko"); @@ -75,21 +111,38 @@ void task2_task (void *pvParameters) { memcpy (persistent.aesKeys, aesKeysDefault, sizeof (persistent.aesKeys)); - sendAdvert(); + // sendAdvert(); + + DiscoverRequestPayload discReq; + discReq.prefixOnly = 0; + discReq.since = 0; + discReq.tag = RTC_GetCounter(); + discReq.typeFilter = 0xFF; + sendDiscoverRequest (&discReq); + + persistent.latitude = 48190900; + persistent.longitude = 17030300; + persistent.altitude = 23400; + char x; + MESH_LOGD (TAG, "Task2 boot"); while (1) { if (USART_GetFlagStatus (USART1, USART_FLAG_RXNE) == SET) { x = USART_ReceiveData (USART1); if (x == 'M') { - printf ("Sending message\n"); + MESH_LOGI (TAG, "Sending message\n"); char tempBuf[180]; snprintf (tempBuf, 180, "SySTick is %d", xTaskGetTickCount()); makeSendGroupMessage (tempBuf, 1); } - if (x == 'A') { - printf ("Sending advert\n"); - sendAdvert(); + if (x == '0') { + MESH_LOGI (TAG, "Sending zero hop advert\n"); + sendAdvert (0); + } + if (x == 'F') { + MESH_LOGI (TAG, "Sending flood advert\n"); + sendAdvert (1); } if (x == 'N') { printNodeDB(); @@ -99,9 +152,9 @@ void task2_task (void *pvParameters) { plainTextMessage.timestamp = RTC_GetCounter(); plainTextMessage.textType = 0; plainTextMessage.attempt = 0; - snprintf(plainTextMessage.message, sizeof(plainTextMessage.message), "Sending message at SySTick is %d", xTaskGetTickCount()); + snprintf (plainTextMessage.message, sizeof (plainTextMessage.message), "Sending message at SySTick is %d", xTaskGetTickCount()); printf ("Sending a direct message to the first node\n"); - sendEncryptedTextMessage(&(persistent.contacts[0]), &plainTextMessage); + sendEncryptedTextMessage (&(persistent.contacts[0]), &plainTextMessage); } } vTaskDelay (pdMS_TO_TICKS (2000)); @@ -113,30 +166,31 @@ void task1_task (void *pvParameters) { const int64_t interval_ms = 10; // 10 ms int64_t start_time, end_time, elapsed; - ESP_LOGW (TAG, "LoraInit"); + MESH_LOGW (TAG, "LoraInit"); LoRaInit(); int8_t txPowerInDbm = 20; uint32_t frequencyInHz = 869554000; - - ESP_LOGW (TAG, "Enable TCXO"); + uint8_t spreadingFactor = 8; + uint8_t bandwidth = SX126X_LORA_BW_62_5; + uint8_t codingRate = SX126X_LORA_CR_4_8; + uint16_t preambleLength = 16; float tcxoVoltage = 2.2; // ebyte // float tcxoVoltage = 1.8; // heltec + + MESH_LOGW (TAG, "Enable TCXO"); char useRegulatorLDO = 1; LoRaDebugPrint (0); - ESP_LOGW (TAG, "Starting lora"); + MESH_LOGW (TAG, "Starting lora"); uint16_t loraBeginStat = LoRaBegin (frequencyInHz, txPowerInDbm, tcxoVoltage, useRegulatorLDO); if (loraBeginStat != 0) { - ESP_LOGE (TAG, "Does not recognize the module"); + MESH_LOGE (TAG, "Does not recognize the module"); while (1) { vTaskDelay (pdMS_TO_TICKS (1000)); } } - uint8_t spreadingFactor = 8; - uint8_t bandwidth = SX126X_LORA_BW_62_5; - uint8_t codingRate = SX126X_LORA_CR_4_8; - uint16_t preambleLength = 16; + char crcOn = 1; char invertIrq = 0; @@ -146,22 +200,25 @@ void task1_task (void *pvParameters) { while (1) { start_time = xTaskGetTickCount(); - - uint8_t rxLen = LoRaReceive (bufIn, sizeof (bufIn)); - if (rxLen > 0) { - // ESP_LOGI (TAG, "%d byte packet received", rxLen); - - int8_t rssi, snr; - GetPacketStatus (&rssi, &snr); - ESP_LOGI (TAG, "rssi=%d[dBm] snr=%d[dB]", rssi, snr); - FrameStruct frame; - frame = decodeFrame (bufIn, rxLen); - processFrame (frame); + int8_t rssi, snr, rawsnr; + FrameStruct frame; + if (ReadFrame (&frame, &rssi, &snr, &rawsnr)) { + hexdump ("Whole frame", frame.payload, frame.payloadLen); + stats.lastSNR = rawsnr; + // stats.lastSNR = snr; //TODO figure out which to use + stats.lastRSSI = rssi; + MESH_LOGI (TAG, "rssi=%d[dBm] snr=%d[dB] rawsnr=%d[quarter dB]", rssi, snr, rawsnr); + // frame = decodeFrame (bufIn, rxLen); + MESH_LOGD (TAG, "Free stack before processFrame: %u bytes", uxTaskGetStackHighWaterMark (NULL) * 4); + processFrame (&frame); + MESH_LOGD (TAG, "Free stack before retransmitFrame: %u bytes", uxTaskGetStackHighWaterMark (NULL) * 4); + retransmitFrame (&frame); + memset (&frame, 0, sizeof (FrameStruct)); // prepare for the next round } int lost = GetPacketLost(); if (lost != 0) { - ESP_LOGW (TAG, "%d packets lost", lost); + MESH_LOGW (TAG, "%d packets lost", lost); } end_time = xTaskGetTickCount(); @@ -174,7 +231,9 @@ void task1_task (void *pvParameters) { } void vApplicationStackOverflowHook (TaskHandle_t xTask, char *pcTaskName) { - printf ("stackoverflow"); + UBaseType_t minFree = uxTaskGetStackHighWaterMark (xTask); + MESH_LOGE (TAG, "Stack overflow in task '%s' (%p)! Minimum free stack: %u words (%u bytes)", + pcTaskName, xTask, minFree, minFree * 4); } /********************************************************************* @@ -218,9 +277,9 @@ int main (void) { USART_Cmd (USART1, ENABLE); - printf ("SystemClk:%d\r\n", SystemCoreClock); - printf ("ChipID:%08x\r\n", DBGMCU_GetCHIPID()); - printf ("FreeRTOS Kernel Version:%s\r\n", tskKERNEL_VERSION_NUMBER); + MESH_LOGD (TAG, "SystemClk:%d\r\n", SystemCoreClock); + MESH_LOGD (TAG, "ChipID:%08x\r\n", DBGMCU_GetCHIPID()); + MESH_LOGD (TAG, "FreeRTOS Kernel Version:%s\r\n", tskKERNEL_VERSION_NUMBER); xTaskCreate ((TaskFunction_t)task1_task, (const char *)"task1", @@ -231,7 +290,7 @@ int main (void) { xTaskCreate ((TaskFunction_t)task2_task, (const char *)"task2", - (uint16_t)1024, + (uint16_t)TASK1_STK_SIZE, (void *)NULL, (UBaseType_t)TASK1_TASK_PRIO, (TaskHandle_t *)&Task2Task_Handler); @@ -240,6 +299,6 @@ int main (void) { vTaskStartScheduler(); while (1) { - printf ("shouldn't run at here!!\n"); + MESH_LOGE (TAG, "shouldn't run at here!!\n"); } } diff --git a/User/meshcore/meshcore.c b/User/meshcore/meshcore.c index 8d9d994..3539ea5 100644 --- a/User/meshcore/meshcore.c +++ b/User/meshcore/meshcore.c @@ -6,6 +6,7 @@ #include "meshcore/packets/control.h" #include "meshcore/packets/encrypted.h" #include "meshcore/packets/group.h" +#include "meshcore/stats.h" #include "task.h" #include "lib/base64.h" #include "lib/cifra/aes.h" @@ -13,52 +14,54 @@ #include "lib/cifra/hmac.h" #include "lib/config.h" #include "meshframing.h" +#include "meshcore/packetstructs.h" #define TAG "MeshCore" // requires at least a 256 byte data -void processFrame (FrameStruct frame) { +void processFrame (const FrameStruct *frame) { printFrameHeader (frame); - if (frame.header & PAYLOAD_VERSION_3) { // more than the version 0 - ESP_LOGW (TAG, "Frame too new, got version %d instead of 0", (frame.header & PAYLOAD_VERSION_3) >> 6); + if (frame->header & PAYLOAD_VERSION_3) { // more than the version 0 + MESH_LOGW (TAG, "Frame too new, got version %d instead of 0", (frame->header & PAYLOAD_VERSION_3) >> 6); } - - unsigned char checkSumBuf[10]; - AdvertisementPayload advert; - GroupTextMessage msg; - - unsigned char frameType = frame.header & PAYLOAD_TYPE_MASK; + + unsigned char frameType = frame->header & PAYLOAD_TYPE_MASK; unsigned char index = 0; + stats.packetsReceivedCount++; + + if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD || + (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) { + stats.receivedFloodCount++; + } + + if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_DIRECT || + (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT) { + stats.receivedDirectCount++; + } + + if (frameType == PAYLOAD_TYPE_ANON_REQ) { decodeAnonReq (frame); } else if (frameType == PAYLOAD_TYPE_PATH || frameType == PAYLOAD_TYPE_REQ || frameType == PAYLOAD_TYPE_RESPONSE || frameType == PAYLOAD_TYPE_TXT_MSG) { printf (" Typexd: 0x%02X\n", frameType); - EncryptedPayloadStruct enc = decodeEncryptedPayload (frame); - printf (" Typexdd: 0x%02X\n", enc.type); - if (enc.payloadLen > 0) { - parseEncryptedPayload (enc); - } + decodeEncryptedPayload (frame); + } else if (frameType == PAYLOAD_TYPE_ACK) { - memset (checkSumBuf, 0, sizeof (checkSumBuf)); - base64_encode (frame.payload, 4, checkSumBuf); - printf ("Checksum: %s\n", checkSumBuf); - } else if (frameType == PAYLOAD_TYPE_ACK) { - uint32_t checkSum = frame.payload[index++]; - checkSum |= frame.payload[index++] << 8; - checkSum |= frame.payload[index++] << 16; - checkSum |= frame.payload[index++] << 24; + uint32_t checkSum = frame->payload[index++]; + checkSum |= frame->payload[index++] << 8; + checkSum |= frame->payload[index++] << 16; + checkSum |= frame->payload[index++] << 24; + // TODO add checking } else if (frameType == PAYLOAD_TYPE_ADVERT) { - advert = decodeAdvertisement (frame); - printAdvertisement (advert); + decodeAdvertisement (frame); } else if (frameType == PAYLOAD_TYPE_GRP_TXT || frameType == PAYLOAD_TYPE_GRP_DATA) { - msg = decodeGroupMessage (frame); - printGroupMessage (msg); + decodeGroupMessage (frame); } else if (frameType == PAYLOAD_TYPE_TRACE) { } else if (frameType == PAYLOAD_TYPE_MULTIPART) { @@ -68,7 +71,8 @@ void processFrame (FrameStruct frame) { } else if (frameType == PAYLOAD_TYPE_RAW_CUSTOM) { // not implemented + } else { + stats.packetsReceivedCount--; } - - retransmitFrame (frame); + MESH_LOGD(TAG, "Processed frame"); } diff --git a/User/meshcore/meshcore.h b/User/meshcore/meshcore.h index 608733e..805d31b 100644 --- a/User/meshcore/meshcore.h +++ b/User/meshcore/meshcore.h @@ -11,6 +11,6 @@ #include #include "stdio.h" -void processFrame (FrameStruct frame); +void processFrame (const FrameStruct * frame); #endif \ No newline at end of file diff --git a/User/meshcore/meshframing.c b/User/meshcore/meshframing.c index 5ed5fa5..8f97733 100644 --- a/User/meshcore/meshframing.c +++ b/User/meshcore/meshframing.c @@ -1,12 +1,110 @@ #include "meshframing.h" +#include "ch32v30x_gpio.h" #include "lib/config.h" +#include "meshcore/stats.h" #include "string.h" #include "stdio.h" #include "sx1262.h" #include "util/hexdump.h" +#include "util/log.h" +#include "FreeRTOS.h" +#include "task.h" +#include "lib/cifra/sha2.h" +#define TAG "Meshframing" + +int ReadFrame (FrameStruct *frame, int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr) { + uint16_t irqRegs = GetIrqStatus(); + // uint8_t status = GetStatus(); + + if (irqRegs & SX126X_IRQ_RX_DONE) { + // ClearIrqStatus(SX126X_IRQ_RX_DONE); + ClearIrqStatus (SX126X_IRQ_ALL); + + uint8_t offset = 0; + uint8_t payloadLength = 0; + GetRxBufferStatus (&payloadLength, &offset); + + if (payloadLength == 0) { + return 0; + } + + GetPacketStatus (rssiPacket, snrPacket, rawSnr); + + memset (frame, 0, sizeof (FrameStruct)); + WaitForIdle (BUSY_WAIT, "start ReadBuffer", 1); + + uint8_t cmd[3] = {SX126X_CMD_READ_BUFFER, offset, SX126X_CMD_NOP}; + + GPIO_WriteBit (GPIOA, GPIO_Pin_4, 0); + + uint16_t curPayloadIndex = 0; + uint8_t pathIndex = 0; + uint8_t transportIndex = 0; + uint8_t state = 0; // 0=header, 1=transport, 2=pathLen, 3=path, 4=payload + + for (uint16_t i = 0; i < payloadLength + sizeof (cmd); i++) { + uint8_t out = (i < sizeof (cmd)) ? cmd[i] : 0xFF; + + // Wait TX ready + while (!SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_TXE)); + SPI_I2S_SendData (SPI1, out); + + // Wait RX ready + while (!SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_RXNE)); + uint8_t in = (uint8_t)SPI_I2S_ReceiveData (SPI1); + + // Only process payload bytes + if (i >= sizeof (cmd)) { + switch (state) { + case 0: // header + frame->header = in; + state = ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT || + (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) + ? 1 + : 2; + break; + + case 1: // transportCodes[4] + frame->transportCodes[transportIndex++] = in; + if (transportIndex >= 4) + state = 2; + break; + + case 2: // pathLen + frame->path.pathLen = in; + if (frame->path.pathLen > 64) { + frame->path.pathLen = 64; + } + pathIndex = 0; + state = (frame->path.pathLen > 0) ? 3 : 4; + break; + + case 3: // path + frame->path.path[pathIndex++] = in; + if (pathIndex >= frame->path.pathLen) + state = 4; + break; + + case 4: // payload + frame->payload[curPayloadIndex++] = in; + break; + } + } + } + + frame->payloadLen = curPayloadIndex; + + GPIO_WriteBit (GPIOA, GPIO_Pin_4, 1); + + WaitForIdle (BUSY_WAIT, "end ReadBuffer", 0); + return payloadLength; + } + return 0; +} + +/* FrameStruct decodeFrame (unsigned char *data, unsigned char dataLen) { - hexdump ("RxDump", data, dataLen); FrameStruct frame; memset (&frame, 0, sizeof (frame)); unsigned char index = 0; @@ -25,9 +123,9 @@ FrameStruct decodeFrame (unsigned char *data, unsigned char dataLen) { return frame; } - -void printFrameHeader (FrameStruct frame) { - switch (frame.header & ROUTE_TYPE_MASK) { +*/ +void printFrameHeader (const FrameStruct *frame) { + switch (frame->header & ROUTE_TYPE_MASK) { case ROUTE_TYPE_TRANSPORT_FLOOD: printf ("transport flood"); break; @@ -47,7 +145,7 @@ void printFrameHeader (FrameStruct frame) { printf (", payload type is "); - switch (frame.header & PAYLOAD_TYPE_MASK) { + switch (frame->header & PAYLOAD_TYPE_MASK) { case PAYLOAD_TYPE_REQ: printf ("request"); break; @@ -101,67 +199,204 @@ void printFrameHeader (FrameStruct frame) { break; } char version[2]; - version[0] = (frame.header >> 6) + '0'; + version[0] = (frame->header >> 6) + '0'; version[1] = 0; printf (", payload version is %s ", version); - if ((frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT || - (frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) { - printf ("Transport codes: %d %d\n", *((uint16_t *)frame.transportCodes), - *((uint16_t *)&(frame.transportCodes[2]))); + if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT || + (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) { + printf ("Transport codes: %d %d\n", *((uint16_t *)frame->transportCodes), + *((uint16_t *)&(frame->transportCodes[2]))); } - printf ("Path is %d nodes long", frame.path.pathLen); + printf ("Path is %d nodes long", frame->path.pathLen); - for (uint8_t pathIndex = 0; pathIndex < frame.path.pathLen; pathIndex++) { - printf ("node %d - %02X, ", pathIndex, frame.path.path[pathIndex]); + for (uint8_t pathIndex = 0; pathIndex < frame->path.pathLen; pathIndex++) { + printf ("node %d - %02X, ", pathIndex, frame->path.path[pathIndex]); } putchar ('\n'); } -void sendFrame (FrameStruct frame) { - uint8_t txBuf[256]; - size_t offset = 0; +void LoRaTransmit (const FrameStruct *frame) { + uint8_t len = 2; // header + path_len - txBuf[offset++] = frame.header; - - if ((frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT || - (frame.header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) { - memcpy (txBuf + offset, frame.transportCodes, 4); - offset += 4; + if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT || + (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) { + len += 4; } - if (frame.path.pathLen > 64) { - frame.path.pathLen = 64; - } + len += frame->path.pathLen; + len += frame->payloadLen; - txBuf[offset++] = frame.path.pathLen; + uint16_t irqStatus; + char rv = 0; - memcpy (txBuf + offset, frame.path.path, frame.path.pathLen); - offset += frame.path.pathLen; + if (txActive == 0) { + txActive = 1; - uint16_t maxPayloadLen = 256 - offset; + if (PacketParams[2] == 0x00) { // explicit header, variable length + PacketParams[3] = len; + } - uint16_t payloadLen = frame.payloadLen > maxPayloadLen ? maxPayloadLen : frame.payloadLen; + WriteCommand (SX126X_CMD_SET_PACKET_PARAMS, PacketParams, 6); + ClearIrqStatus (SX126X_IRQ_ALL); - memcpy (txBuf + offset, frame.payload, payloadLen); - offset += payloadLen; + WaitForIdle (BUSY_WAIT, "start WriteBuffer", 1); - hexdump ("TxDump", txBuf, offset); - LoRaSend (txBuf, offset, SX126x_TXMODE_SYNC); -} + uint8_t cmdBuf[2] = {SX126X_CMD_WRITE_BUFFER, 0x00}; + uint8_t cmdLen = sizeof (cmdBuf); -void retransmitFrame (FrameStruct frame) { - if (frame.header & ROUTE_TYPE_FLOOD || frame.header & ROUTE_TYPE_TRANSPORT_FLOOD) { - if (frame.header != DONT_RETRANSMIT_HEADER && frame.path.pathLen + 1 < MAX_FLOOD_TTL) { - frame.path.path[frame.path.pathLen++] = persistent.pubkey[0]; + GPIO_WriteBit (GPIOA, GPIO_Pin_4, 0); + + uint16_t payloadIndex = 0; + uint8_t state = 0; + uint8_t pathIndex = 0; + uint8_t transportIndex = 0; + + for (uint16_t i = 0; i < len + cmdLen; i++) { + uint8_t out = 0xFF; + + if (i < cmdLen) { + out = cmdBuf[i]; + } else { + switch (state) { + case 0: // header + out = frame->header; + state = ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT || + (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) + ? 1 + : 2; + break; + + case 1: // transport codes + out = frame->transportCodes[transportIndex++]; + if (transportIndex >= 4) + state = 2; + break; + + case 2: // path length + out = frame->path.pathLen; + pathIndex = 0; + state = (frame->path.pathLen > 0) ? 3 : 4; + break; + + case 3: // path + out = frame->path.path[pathIndex++]; + if (pathIndex >= frame->path.pathLen) + state = 4; + break; + + case 4: // payload + out = frame->payload[payloadIndex++]; + break; + } + } + + while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_TXE) == RESET); + SPI_I2S_SendData (SPI1, out); + + while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_RXNE) == RESET); + (void)SPI_I2S_ReceiveData (SPI1); // discard + } + + GPIO_WriteBit (GPIOA, GPIO_Pin_4, 1); + + WaitForIdle (BUSY_WAIT, "end WriteBuffer", 0); + + SetTx (5000); + + irqStatus = GetIrqStatus(); + while (!(irqStatus & (SX126X_IRQ_TX_DONE | SX126X_IRQ_TIMEOUT))) { + vTaskDelay (1); + irqStatus = GetIrqStatus(); + } + + txActive = 0; + SetRx (0xFFFFFF); + + if (irqStatus & SX126X_IRQ_TX_DONE) { + rv = 1; } } - if (frame.header & ROUTE_TYPE_DIRECT || frame.header & ROUTE_TYPE_TRANSPORT_DIRECT) { + if (rv == 0) { + txLost++; } } +/* +void sendFrame (const FrameStruct *frame) { + uint8_t txBuf[256]; + size_t offset = 0; + + txBuf[offset++] = frame->header; + + if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT || + (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) { + memcpy (txBuf + offset, frame->transportCodes, 4); + offset += 4; + } + + if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD || + (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) { + stats.sentFloodCount++; + } + + if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_DIRECT || + (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_DIRECT) { + stats.sentDirectCount++; + } + + stats.packetsSentCount++; + + uint8_t pathLen = frame->path.pathLen; + + + if (pathLen > 64) { + pathLen = 64; + } + + txBuf[offset++] = pathLen; + + memcpy (txBuf + offset, frame->path.path, pathLen); + hexdump ("TxDump Path", frame->path.path, frame->path.pathLen); + offset += pathLen; + + uint16_t maxPayloadLen = 256 - offset; + + uint16_t payloadLen = frame->payloadLen > maxPayloadLen ? maxPayloadLen : frame->payloadLen; + + memcpy (txBuf + offset, frame->payload, payloadLen); + offset += payloadLen; + + + hexdump ("TxDump", txBuf, offset); + hexdump ("TxDumpPayload", frame->payload, frame->payloadLen); + TickType_t start, end; + start = xTaskGetTickCount(); + LoRaSend (txBuf, offset, SX126x_TXMODE_SYNC); + end = xTaskGetTickCount(); + tickAirtime += end - start; +} +*/ + +void retransmitFrame (FrameStruct *frame) { + MESH_LOGD (TAG, "Going to check ReTx"); + if (frame->header & ROUTE_TYPE_FLOOD || frame->header & ROUTE_TYPE_TRANSPORT_FLOOD) { + MESH_LOGD (TAG, "Header is flood"); + if (frame->header != DONT_RETRANSMIT_HEADER && frame->path.pathLen + 1 < MAX_FLOOD_TTL) { + MESH_LOGD (TAG, "Writing pubkey"); + frame->path.path[frame->path.pathLen++] = persistent.pubkey[0]; + MESH_LOGD (TAG, "Flooding"); + vTaskDelay (10); + LoRaTransmit (frame); // TODO check if correct + MESH_LOGD (TAG, "Flooded"); + } + } + + if (frame->header & ROUTE_TYPE_DIRECT || frame->header & ROUTE_TYPE_TRANSPORT_DIRECT) { + } +} // Verify MAC + Decrypt @@ -173,8 +408,8 @@ int encrypt_then_mac (const uint8_t *aes_key, const uint8_t keySize, const uint8 // prepare padded buffer uint8_t padded[padded_len]; - memset(padded, 0, padded_len); // zero padding - memcpy(padded, plaintext, plen); // copy plaintext + memset (padded, 0, padded_len); // zero padding + memcpy (padded, plaintext, plen); // copy plaintext // ciphertext will go right after HMAC uint8_t *ciphertext = output + HMAC_SIZE; @@ -202,7 +437,8 @@ int mac_then_decrypt (const uint8_t *aes_key, const uint8_t keySize, const uint8 const uint8_t *ciphertext = input + HMAC_SIZE; size_t clen = ilen - HMAC_SIZE; - if (clen % 16 != 0) return -2; // must be multiple of block size + if (clen % 16 != 0) + return -2; // must be multiple of block size uint8_t calc_mac[32]; // full SHA-256 hmac_sha256 (aes_key, keySize, ciphertext, clen, calc_mac); @@ -211,4 +447,26 @@ int mac_then_decrypt (const uint8_t *aes_key, const uint8_t keySize, const uint8 return -2; return aes_decrypt_ecb (aes_key, 16, ciphertext, clen, plaintext); +} + +uint16_t getTransportCode (const FrameStruct *frame) { + uint16_t code; + /* + // compute HMAC over ciphertext + uint8_t mac[32]; // full SHA-256 + cf_hmac_ctx ctx; + cf_hmac_init (&ctx, &cf_sha256, key, sizeof(key)); + cf_hmac_update (&ctx, &(frame->header), sizeof (frame->header)); + cf_hmac_update (&ctx, frame->payload, frame->payloadLen); + cf_hmac_finish (&ctx, mac); + + // copy only HMAC_SIZE bytes of MAC + memcpy (&code, mac, HMAC_SIZE); + */ + if (code == 0) { // reserve codes 0000 and FFFF + code++; + } else if (code == 0xFFFF) { + code--; + } + return code; } \ No newline at end of file diff --git a/User/meshcore/meshframing.h b/User/meshcore/meshframing.h index c7318f6..ae050dd 100644 --- a/User/meshcore/meshframing.h +++ b/User/meshcore/meshframing.h @@ -12,13 +12,20 @@ #define HMAC_SIZE 2 // meshcore size #define MAX_FLOOD_TTL 64 +int ReadFrame(FrameStruct *frame, int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr); + +void LoRaTransmit (const FrameStruct *frame); + +/* FrameStruct decodeFrame (unsigned char *data, unsigned char dataLen); -void printFrameHeader (FrameStruct frame) ; +void sendFrame (const FrameStruct * frame); +*/ -void sendFrame (FrameStruct frame); +void printFrameHeader (const FrameStruct * frame) ; -void retransmitFrame (FrameStruct frame) ; +//CALL LAST, PATH GETS MODIFIED +void retransmitFrame (FrameStruct * frame) ; // Verify MAC + Decrypt @@ -26,4 +33,5 @@ int encrypt_then_mac (const uint8_t *aes_key, const uint8_t keySize, const uint8 int mac_then_decrypt (const uint8_t *aes_key, const uint8_t keySize, const uint8_t *input, size_t ilen, uint8_t *plaintext); + #endif \ No newline at end of file diff --git a/User/meshcore/packets/ack.c b/User/meshcore/packets/ack.c index 34cb55a..2aff951 100644 --- a/User/meshcore/packets/ack.c +++ b/User/meshcore/packets/ack.c @@ -8,6 +8,7 @@ void sendDiscreteAck (uint8_t *data, const uint8_t len, uint8_t *senderPubKey) { FrameStruct frame; + frame.path.pathLen = 0; memset (&frame, 0, sizeof (frame)); // 1. Header @@ -38,5 +39,5 @@ void sendDiscreteAck (uint8_t *data, const uint8_t len, uint8_t *senderPubKey) { frame.payloadLen = 4; - sendFrame (frame); + LoRaTransmit (&frame); } \ No newline at end of file diff --git a/User/meshcore/packets/advert.c b/User/meshcore/packets/advert.c index 01e9443..e808e45 100644 --- a/User/meshcore/packets/advert.c +++ b/User/meshcore/packets/advert.c @@ -7,186 +7,202 @@ #include "advert.h" #include "util/hexdump.h" #include "lib/base64.h" +#include "util/log.h" +#include "FreeRTOS.h" +#include "task.h" #define TAG "Advert" -void sendAdvert() { - AdvertisementPayload ad; - memcpy (ad.pubKey, persistent.pubkey, sizeof (ad.pubKey)); - ad.dataFlags = ADVERTISEMENT_FLAG_HAS_NAME; - if (persistent.nodeType == NODE_TYPE_CHAT_NODE) { - ad.dataFlags |= ADVERTISEMENT_FLAG_IS_CHAT_NODE; - } else if (persistent.nodeType == NODE_TYPE_REPEATER) { - ad.dataFlags |= ADVERTISEMENT_FLAG_IS_REAPEATER; - } else if (persistent.nodeType == NODE_TYPE_ROOM_SERVER) { - ad.dataFlags |= ADVERTISEMENT_FLAG_IS_ROOM_SERVER; - } else if (persistent.nodeType == NODE_TYPE_SENSOR) { - ad.dataFlags |= ADVERTISEMENT_FLAG_IS_SENSOR; - } - strcpy (ad.nodeName, persistent.nodeName); - ad.timestamp = RTC_GetCounter(); - - uint8_t app_data[40]; - size_t app_len = 0; - - app_data[app_len++] = ad.dataFlags; - - if (ad.dataFlags & ADVERTISEMENT_FLAG_HAS_LOCATION) { - memcpy (app_data + app_len, &ad.latitude, sizeof (ad.latitude)); - app_len += sizeof (ad.latitude); - memcpy (app_data + app_len, &ad.longitude, sizeof (ad.longitude)); - app_len += sizeof (ad.longitude); - } - - if (ad.dataFlags & ADVERTISEMENT_FLAG_RFU1) { - memcpy (app_data + app_len, &ad.rfu1, sizeof (ad.rfu1)); - app_len += sizeof (ad.rfu1); - } - - if (ad.dataFlags & ADVERTISEMENT_FLAG_RFU2) { - memcpy (app_data + app_len, &ad.rfu2, sizeof (ad.rfu2)); - app_len += sizeof (ad.rfu2); - } - - if (ad.dataFlags & ADVERTISEMENT_FLAG_HAS_NAME) { - size_t nodenameLen = strlen (ad.nodeName); - memcpy (app_data + app_len, ad.nodeName, nodenameLen); - app_len += nodenameLen; - } - - // 2. Reserve frame and build payload header +void sendAdvert (uint8_t shouldFlood) { + printf ("High-water mark before preparing advert: %u\n", uxTaskGetStackHighWaterMark (NULL)); FrameStruct frame; - frame.header = ROUTE_TYPE_FLOOD | PAYLOAD_TYPE_ADVERT | PAYLOAD_VERSION_0; - size_t offset = 0; - memcpy (frame.payload + offset, ad.pubKey, sizeof (ad.pubKey)); - offset += sizeof (ad.pubKey); - memcpy (frame.payload + offset, &ad.timestamp, sizeof (ad.timestamp)); - offset += sizeof (ad.timestamp); + frame.header = (shouldFlood ? ROUTE_TYPE_FLOOD : ROUTE_TYPE_DIRECT) | PAYLOAD_TYPE_ADVERT | PAYLOAD_VERSION_0; - // reserve signature space + /* ---- public key ---- */ + memcpy (frame.payload + offset, persistent.pubkey, 32); + offset += 32; + + /* ---- timestamp ---- */ + uint32_t timestamp = RTC_GetCounter(); + memcpy (frame.payload + offset, ×tamp, sizeof (timestamp)); + offset += sizeof (timestamp); + + /* ---- reserve signature ---- */ uint8_t *signature_pos = frame.payload + offset; offset += 64; - // append app_data after signature - memcpy (frame.payload + offset, app_data, app_len); - offset += app_len; + /* ---- build app data directly into payload ---- */ + size_t app_start = offset; - // 3. Sign pubKey + timestamp + app_data - uint8_t message[76]; - size_t msg_len = 0; - memcpy (message + msg_len, ad.pubKey, sizeof (ad.pubKey)); - msg_len += sizeof (ad.pubKey); - memcpy (message + msg_len, &ad.timestamp, sizeof (ad.timestamp)); - msg_len += sizeof (ad.timestamp); - memcpy (message + msg_len, app_data, app_len); - msg_len += app_len; + uint8_t dataFlags = ADVERTISEMENT_FLAG_HAS_NAME; + if (persistent.nodeType == NODE_TYPE_CHAT_NODE) + dataFlags |= ADVERTISEMENT_FLAG_IS_CHAT_NODE; + else if (persistent.nodeType == NODE_TYPE_REPEATER) + dataFlags |= ADVERTISEMENT_FLAG_IS_REAPEATER; + else if (persistent.nodeType == NODE_TYPE_ROOM_SERVER) + dataFlags |= ADVERTISEMENT_FLAG_IS_ROOM_SERVER; + else if (persistent.nodeType == NODE_TYPE_SENSOR) + dataFlags |= ADVERTISEMENT_FLAG_IS_SENSOR; - ed25519_sign (signature_pos, message, msg_len, persistent.pubkey, persistent.privkey); + frame.payload[offset++] = dataFlags; - hexdump ("Complete advert", frame.payload, offset); + if (dataFlags & ADVERTISEMENT_FLAG_HAS_LOCATION) { + memcpy (frame.payload + offset, &persistent.latitude, sizeof (persistent.latitude)); + offset += sizeof (persistent.latitude); - hexdump ("Public key", ad.pubKey, 32); + memcpy (frame.payload + offset, &persistent.longitude, sizeof (persistent.longitude)); + offset += sizeof (persistent.longitude); + } + /* + if (dataFlags & ADVERTISEMENT_FLAG_RFU1) { + memcpy(frame.payload + offset, &persistent.rfu1, sizeof(persistent.rfu1)); + offset += sizeof(persistent.rfu1); + } + + if (dataFlags & ADVERTISEMENT_FLAG_RFU2) { + memcpy(frame.payload + offset, &persistent.rfu2, sizeof(persistent.rfu2)); + offset += sizeof(persistent.rfu2); + } + */ + + if (dataFlags & ADVERTISEMENT_FLAG_HAS_NAME) { + size_t nameLen = strlen (persistent.nodeName); + memcpy (frame.payload + offset, persistent.nodeName, nameLen); + offset += nameLen; + } + + size_t app_len = offset - app_start; + + frame.payloadLen = offset; + /* ---- sign directly over payload ---- */ + printf ("High-water mark before signing: %u\n", uxTaskGetStackHighWaterMark (NULL)); + ed25519_sign_ad (&frame); + printf ("High-water mark after signing: %u\n", uxTaskGetStackHighWaterMark (NULL)); + + /* ---- debug ---- */ + hexdump ("Public key", frame.payload, 32); hexdump ("Signature", signature_pos, 64); + hexdump ("Appdata", frame.payload + app_start, app_len); + printf ("Timestamp is %lu\n", timestamp); + printf ("NodeName %s\n", persistent.nodeName); - printf ("Timestamp is %d\n", ad.timestamp); - - printf ("NodeName %s\n", ad.nodeName); - - hexdump ("Appdata", app_data, app_len); - - // 5. Set payload length and send + /* ---- send ---- */ frame.payloadLen = offset; frame.path.pathLen = 0; - sendFrame (frame); + LoRaTransmit (&frame); } -AdvertisementPayload decodeAdvertisement (FrameStruct frame) { +void decodeAdvertisement (const FrameStruct *frame) { AdvertisementPayload advert; memset (&advert, 0, sizeof (advert)); - if ((frame.header & PAYLOAD_TYPE_MASK) != PAYLOAD_TYPE_ADVERT) { - return advert; + advert.valid = 0; + if (frame->payloadLen < 101) { + MESH_LOGW (TAG, "Advertisement frame too short (%d < 101)", frame->payloadLen); + return; } + if (ed25519_verify_ad (frame) != 1) { + MESH_LOGW (TAG, "Incorrect signature"); + return; + } + advert.valid = 1; + unsigned char index = 0; - memcpy (advert.pubKey, frame.payload + index, 32); + memcpy (advert.pubKey, frame->payload + index, 32); index += 32; - memcpy (&advert.timestamp, frame.payload + index, 4); + memcpy (&advert.timestamp, frame->payload + index, 4); index += 4; - memcpy (advert.signature, frame.payload + index, 64); + memcpy (advert.signature, frame->payload + index, 64); index += 64; - advert.dataFlags = frame.payload[index++]; + advert.dataFlags = frame->payload[index++]; + + uint8_t expectedLen = 101; if (advert.dataFlags & ADVERTISEMENT_FLAG_HAS_LOCATION) { - memcpy (&advert.latitude, frame.payload + index, 4); + expectedLen += 8; + } + + if (advert.dataFlags & ADVERTISEMENT_FLAG_RFU1) { + expectedLen += 2; + } + if (advert.dataFlags & ADVERTISEMENT_FLAG_RFU2) { + expectedLen += 2; + } + + if (frame->payloadLen < expectedLen) { + MESH_LOGW (TAG, "Advertisement frame with data too short (%d < %d)", frame->payloadLen, expectedLen); + return; + } + + if (advert.dataFlags & ADVERTISEMENT_FLAG_HAS_LOCATION) { + memcpy (&advert.latitude, frame->payload + index, 4); index += 4; - memcpy (&advert.longitude, frame.payload + index, 4); + memcpy (&advert.longitude, frame->payload + index, 4); index += 4; } if (advert.dataFlags & ADVERTISEMENT_FLAG_RFU1) { - memcpy (&advert.rfu1, frame.payload + index, 2); + memcpy (&advert.rfu1, frame->payload + index, 2); index += 2; } if (advert.dataFlags & ADVERTISEMENT_FLAG_RFU2) { - memcpy (&advert.rfu2, frame.payload + index, 2); + memcpy (&advert.rfu2, frame->payload + index, 2); index += 2; } - unsigned char nameLen = frame.payloadLen - index; - if (nameLen > 32) { - nameLen = 32; + unsigned char nameLen = frame->payloadLen - index; + + if (nameLen > 31) { + nameLen = 31; // leave space for null } - memcpy (advert.nodeName, frame.payload + index, nameLen); - advert.nodeName[frame.payloadLen - index] = 0; + memcpy (advert.nodeName, frame->payload + index, nameLen); + advert.nodeName[nameLen] = 0; - NodeEntry *node = getNode (advert.pubKey[0]); + printAdvertisement (&advert); + saveAdvert (&advert); +} +void saveAdvert (const AdvertisementPayload *advert) { + NodeEntry *node = getNode (advert->pubKey[0]); if (node == NULL) { node = getNextNode(); memset (node, 0, sizeof (NodeEntry)); } - memcpy (node->name, advert.nodeName, sizeof (node->name)); - memcpy (node->pubKey, advert.pubKey, sizeof (node->pubKey)); - ed25519_key_exchange ((unsigned char *)node->secret, advert.pubKey, persistent.privkey); - node->gps_latitude = advert.latitude; - node->gps_longitude = advert.longitude; + memcpy (node->name, advert->nodeName, sizeof (node->name)); + memcpy (node->pubKey, advert->pubKey, sizeof (node->pubKey)); + ed25519_key_exchange ((unsigned char *)node->secret, advert->pubKey, persistent.privkey); + node->gps_latitude = advert->latitude; + node->gps_longitude = advert->longitude; // ADD PATH - node->type = advert.dataFlags & 0x0F; + node->type = advert->dataFlags & 0x0F; node->last_seen_lt = RTC_GetCounter(); - node->last_seen_rt = advert.timestamp; - - - return advert; + node->last_seen_rt = advert->timestamp; } -void printAdvertisement (AdvertisementPayload advert) { - unsigned char keyBuf[50]; - unsigned char sigBuf[90]; - memset (keyBuf, 0, sizeof (keyBuf)); - memset (sigBuf, 0, sizeof (sigBuf)); - base64_encode (advert.pubKey, 32, keyBuf); - base64_encode (advert.signature, 64, sigBuf); +void printAdvertisement (const AdvertisementPayload *advert) { + printf ( + "%s on %ld with type %s on %s location %ld %ld\n", + advert->dataFlags & ADVERTISEMENT_FLAG_HAS_NAME + ? advert->nodeName + : "nameless node", + advert->timestamp, + (advert->dataFlags & 0x07) == 0x04 ? "sensor" + : (advert->dataFlags & 0x07) == 0x03 ? "room server" + : (advert->dataFlags & 0x07) == 0x02 ? "repeater" + : "chat node", + advert->dataFlags & 0x80 ? "known" : "unknown", + advert->latitude, + advert->longitude); - printf ("%s on %ld with type %s on %s location %ld %ld, public key %s and " - "signature %s\n", - advert.dataFlags & ADVERTISEMENT_FLAG_HAS_NAME ? advert.nodeName - : "nameless node", - advert.timestamp, - (advert.dataFlags & 0x07) == 0x04 - ? "sensor" - : ((advert.dataFlags & 0x07) == 0x03 - ? "room server" - : ((advert.dataFlags & 0x07) == 0x02 ? "repeater" - : "chat node")), - advert.dataFlags & 0x80 ? "known" : "unknown", advert.latitude, - advert.longitude, keyBuf, sigBuf); -} \ No newline at end of file + hexdump ("Public key", advert->pubKey, 32); + hexdump ("Signature", advert->signature, 64); +} diff --git a/User/meshcore/packets/advert.h b/User/meshcore/packets/advert.h index 8758556..383282f 100644 --- a/User/meshcore/packets/advert.h +++ b/User/meshcore/packets/advert.h @@ -3,10 +3,12 @@ #include "meshcore/packetstructs.h" -void sendAdvert(); +void sendAdvert (uint8_t shouldFlood); -AdvertisementPayload decodeAdvertisement (FrameStruct frame); +void decodeAdvertisement (const FrameStruct * frame); -void printAdvertisement (AdvertisementPayload advert); +void printAdvertisement (const AdvertisementPayload * advert); + +void saveAdvert(const AdvertisementPayload * advert); #endif \ No newline at end of file diff --git a/User/meshcore/packets/anonymous.c b/User/meshcore/packets/anonymous.c index ea155f2..0d1e517 100644 --- a/User/meshcore/packets/anonymous.c +++ b/User/meshcore/packets/anonymous.c @@ -10,9 +10,10 @@ #define TAG "Anonymous" -void sendAnonymousRequest (NodeEntry *targetNode, const uint8_t *password, uint32_t sync) { +void sendAnonymousRequest (const NodeEntry *targetNode, const uint8_t *password, uint32_t sync) { uint8_t passwordLen = strlen ((const char *)password); FrameStruct frame; + frame.path.pathLen = 0; uint8_t offset = 0; // 1. Frame header @@ -61,36 +62,103 @@ void sendAnonymousRequest (NodeEntry *targetNode, const uint8_t *password, uint3 // 5. Finalize and send frame.payloadLen = offset; - memcpy(&(frame.path), &(targetNode->path), sizeof(frame.path)); + memcpy (&(frame.path), &(targetNode->path), sizeof (frame.path)); hexdump ("Anon payload", frame.payload, frame.payloadLen); - sendFrame (frame); + LoRaTransmit (&frame); } -AnonymousRequestPayload decodeAnonReq (FrameStruct frame) { +void printAnonRequest (const AnonymousRequestPayload *req, int isRoomServer) { + if (!req) + return; + + printf ("AnonymousRequestPayload at %p\n", (void *)req); + printf (" destination hash: 0x%02X\n", req->destinationHash); + + printf (" sender pubKey: "); + for (int i = 0; i < sizeof (req->pubKey); i++) { + printf ("%02X", req->pubKey[i]); + } + printf ("\n"); + + printf (" cipher MAC: 0x%04X\n", req->cipherMAC); + + printf (" decrypted payload (%u bytes):\n", req->payloadLen); + uint8_t index = 0; + + // timestamp (first 4 bytes) + if (req->payloadLen >= 4) { + uint32_t timestamp = req->payload[index++]; + timestamp |= req->payload[index++] << 8; + timestamp |= req->payload[index++] << 16; + timestamp |= req->payload[index++] << 24; + printf (" timestamp: %u\n", timestamp); + } + + // room server sync timestamp + if (isRoomServer && req->payloadLen >= index + 4) { + uint32_t syncTimestamp = req->payload[index++]; + syncTimestamp |= req->payload[index++] << 8; + syncTimestamp |= req->payload[index++] << 16; + syncTimestamp |= req->payload[index++] << 24; + printf (" sync timestamp: %u\n", syncTimestamp); + } + + + // remaining bytes = password + if (index < req->payloadLen) { + uint8_t passwordLen = req->payloadLen - index; + if (passwordLen > 16) + passwordLen = 16; + passwordLen = strnlen (&(req->payload[index]), passwordLen); + printf (" password: "); + for (uint8_t i = 0; i < passwordLen; i++) { + printf ("%c", req->payload[i + index]); + } + printf ("\n"); + } +} + +size_t strnlen (const char *s, size_t maxLen) { + size_t len = 0; + while (len < maxLen && s[len] != '\0') { + len++; + } + return len; +} + +void decodeAnonReq (const FrameStruct *frame) { uint8_t index = 0; AnonymousRequestPayload anonReq; - anonReq.destinationHash = frame.payload[index++]; - memcpy (anonReq.pubKey, &(frame.payload[index]), sizeof (anonReq.pubKey)); + + anonReq.destinationHash = frame->payload[index++]; + memcpy (anonReq.pubKey, &(frame->payload[index]), sizeof (anonReq.pubKey)); index += sizeof (anonReq.pubKey); - anonReq.cipherMAC = frame.payload[index]; - anonReq.cipherMAC |= frame.payload[index + 1] << 8; + anonReq.cipherMAC = frame->payload[index]; + anonReq.cipherMAC |= frame->payload[index + 1] << 8; + NodeEntry *foundNode = getNode (anonReq.pubKey[0]); if (foundNode == NULL) { foundNode = getNextNode(); - strcpy (foundNode->name, "Anonymous node"); memcpy (foundNode->pubKey, anonReq.pubKey, sizeof (foundNode->pubKey)); ed25519_key_exchange ((unsigned char *)foundNode->secret, anonReq.pubKey, persistent.privkey); foundNode->gps_latitude = 0; foundNode->gps_longitude = 0; - // ADD PATH foundNode->type = 0; foundNode->last_seen_lt = RTC_GetCounter(); + + MESH_LOGI (TAG, "New anonymous node created: %s", foundNode->name); + } else { + MESH_LOGD (TAG, "Existing node found for pubKey[0]=0x%02X", anonReq.pubKey[0]); } - mac_then_decrypt (foundNode->secret, 32, &(frame.payload[index]), frame.payloadLen - index, anonReq.payload); - anonReq.payloadLen = frame.payloadLen - index - 2; + + mac_then_decrypt (foundNode->secret, 32, &(frame->payload[index]), frame->payloadLen - index, anonReq.payload); + anonReq.payloadLen = frame->payloadLen - index - 2; + + hexdump ("AnonReq payload", anonReq.payload, anonReq.payloadLen); + uint8_t index2 = 0; foundNode->last_seen_rt = anonReq.payload[index2++]; foundNode->last_seen_rt |= anonReq.payload[index2++] << 8; @@ -104,30 +172,39 @@ AnonymousRequestPayload decodeAnonReq (FrameStruct frame) { foundNode->sync_timestamp |= anonReq.payload[index2++] << 24; } + printAnonRequest (&anonReq, persistent.nodeType == NODE_TYPE_ROOM_SERVER); + uint8_t passwordLen = anonReq.payloadLen - index2; - if (passwordLen > 16) { + if (passwordLen > 16) passwordLen = 16; - } + passwordLen = strnlen (&(anonReq.payload[index2]), passwordLen); + + MESH_LOGI (TAG, "Password len is %d.", passwordLen); uint8_t passwordBuf[16]; memcpy (passwordBuf, &(anonReq.payload[index2]), passwordLen); - if (memcmp (passwordBuf, persistent.password, sizeof (persistent.password)) == 0) { + + if (memcmp (passwordBuf, persistent.password, passwordLen) == 0) { foundNode->authenticated = 1; - Response resp; - resp.tag = RTC_GetCounter(); - uint8_t index3 = 0; - uint32_t randOut = rand(); - resp.data[index3++] = RESP_SERVER_LOGIN_OK; - resp.data[index3++] = 0;//legacy - resp.data[index3++] = 1;//isadmin - resp.data[index3++] = PERM_ACL_ADMIN;//permissions - resp.data[index3++] = randOut & 0xFF;//rng - resp.data[index3++] = (randOut >> 8) & 0xFF; - resp.data[index3++] = (randOut >> 16) & 0xFF; - resp.data[index3++] = (randOut >> 24) & 0xFF; - resp.data[index3++] = FIRMWARE_VER_LEVEL; - resp.dataLen = index3; - sendEncryptedResponse(foundNode, &resp); + MESH_LOGI (TAG, "Password correct, node %s authenticated.", foundNode->name); + + MESH_LOGI (TAG, "Login response sent to node %s.", foundNode->name); + } else { + MESH_LOGW (TAG, "Password incorrect for node %s.", foundNode->name); } - return anonReq; -} \ No newline at end of file + Response resp; + resp.tag = RTC_GetCounter(); + uint8_t index3 = 0; + uint32_t randOut = rand(); + resp.data[index3++] = RESP_SERVER_LOGIN_OK; + resp.data[index3++] = 0; // legacy + resp.data[index3++] = foundNode->authenticated; // isadmin + resp.data[index3++] = foundNode->authenticated ? PERM_ACL_ADMIN : PERM_ACL_GUEST; // permissions + resp.data[index3++] = randOut & 0xFF; + resp.data[index3++] = (randOut >> 8) & 0xFF; + resp.data[index3++] = (randOut >> 16) & 0xFF; + resp.data[index3++] = (randOut >> 24) & 0xFF; + resp.data[index3++] = FIRMWARE_VER_LEVEL; + resp.dataLen = index3; + sendEncryptedResponse (foundNode, &resp); +} diff --git a/User/meshcore/packets/anonymous.h b/User/meshcore/packets/anonymous.h index f8223aa..c7afb55 100644 --- a/User/meshcore/packets/anonymous.h +++ b/User/meshcore/packets/anonymous.h @@ -4,8 +4,8 @@ #include "meshcore/packetstructs.h" #include "lib/config.h" -AnonymousRequestPayload decodeAnonReq (FrameStruct frame); +void decodeAnonReq (const FrameStruct * frame); -void sendAnonymousRequest (NodeEntry *targetNode, const uint8_t *password, uint32_t sync); +void sendAnonymousRequest (const NodeEntry *targetNode, const uint8_t *password, uint32_t sync); #endif \ No newline at end of file diff --git a/User/meshcore/packets/control.c b/User/meshcore/packets/control.c index 07af4c2..62c9149 100644 --- a/User/meshcore/packets/control.c +++ b/User/meshcore/packets/control.c @@ -1,13 +1,19 @@ +#include "lib/config.h" #include "meshcore/meshframing.h" #include "meshcore/packetstructs.h" #include "control.h" +#include "meshcore/stats.h" #include "string.h" +#include "util/hexdump.h" +#include "util/log.h" +#include #define TAG "Control" -void sendDiscoverRequest(const DiscoverRequestPayload *discReq) { +void sendDiscoverRequest (const DiscoverRequestPayload *discReq) { FrameStruct frame; + frame.path.pathLen = 0; uint8_t offset = 0; // Build payload @@ -21,7 +27,7 @@ void sendDiscoverRequest(const DiscoverRequestPayload *discReq) { frame.payload[offset++] = (discReq->tag >> 24) & 0xFF; // optional `since` - if (discReq->since != 0) { // or another condition if you want to always include + if (discReq->since != 0) { // or another condition if you want to always include frame.payload[offset++] = (discReq->since >> 0) & 0xFF; frame.payload[offset++] = (discReq->since >> 8) & 0xFF; frame.payload[offset++] = (discReq->since >> 16) & 0xFF; @@ -30,47 +36,110 @@ void sendDiscoverRequest(const DiscoverRequestPayload *discReq) { frame.payloadLen = offset; - sendFrame(frame); + LoRaTransmit (&frame); } +void sendDiscoverResponse (const DiscoverResponsePayload *discResp) { + FrameStruct frame; + frame.path.pathLen = 0; + uint8_t offset = 0; -void decodeControlFrame(FrameStruct frame) { + /* Control type + node type (lower nibble) */ + frame.payload[offset++] = + (discResp->nodeType & 0x0F) | + CONTROL_DATA_FLAG_DISCOVER_RESP; + + /* SNR */ + frame.payload[offset++] = (uint8_t)discResp->snr; + + /* Tag (LE) */ + frame.payload[offset++] = (discResp->tag >> 0) & 0xFF; + frame.payload[offset++] = (discResp->tag >> 8) & 0xFF; + frame.payload[offset++] = (discResp->tag >> 16) & 0xFF; + frame.payload[offset++] = (discResp->tag >> 24) & 0xFF; + + /* Pubkey */ + if (discResp->pubkeyLen > 0) { + memcpy (&frame.payload[offset], + discResp->pubkey, + discResp->pubkeyLen); + offset += discResp->pubkeyLen; + } + + frame.payloadLen = offset; + + LoRaTransmit (&frame); +} + +void printDiscoverRequest (const DiscoverRequestPayload *p) { + printf ("=== Discover Request ===\n"); + printf ("prefixOnly : %u\n", p->prefixOnly); + printf ("typeFilter : 0x%02X\n", p->typeFilter); + printf ("tag : 0x%08lX\n", (unsigned long)p->tag); + printf ("since : 0x%08lX\n", (unsigned long)p->since); +} + +void printDiscoverResponse (const DiscoverResponsePayload *p) { + printf ("=== Discover Response ===\n"); + printf ("nodeType : %u\n", p->nodeType); + printf ("snr : %u\n", p->snr); + printf ("tag : 0x%08lX\n", (unsigned long)p->tag); + + hexdump ("pubkey : ", p->pubkey, p->pubkeyLen); + printf ("\n"); +} + +void decodeControlFrame (const FrameStruct * frame) { uint8_t index = 0; - uint8_t type = frame.payload[index] & 0xF0; - if (type == CONTROL_DATA_FLAG_TYPE_NODE_DISCOVER_REQ) { - DiscoverRequestPayload discReq; - discReq.prefixOnly = frame.payload[index++] & 0x01; + uint8_t type = frame->payload[index] & 0xF0; + if (type == CONTROL_DATA_FLAG_TYPE_NODE_DISCOVER_REQ) { + DiscoverRequestPayload discReq; + discReq.prefixOnly = frame->payload[index++] & 0x01; - discReq.typeFilter = frame.payload[index++]; + discReq.typeFilter = frame->payload[index++]; - discReq.tag = frame.payload[index++]; - discReq.tag |= frame.payload[index++] << 8; - discReq.tag |= frame.payload[index++] << 16; - discReq.tag |= frame.payload[index++] << 24; - - if (index < frame.payloadLen) { - discReq.since = frame.payload[index++]; - discReq.since |= frame.payload[index++] << 8; - discReq.since |= frame.payload[index++] << 16; - discReq.since |= frame.payload[index++] << 24; - } - - } else if (type == CONTROL_DATA_FLAG_DISCOVER_RESP) { - DiscoverResponsePayload discResp; - discResp.nodeType = frame.payload[index++] & 0x0F; - - discResp.snr = frame.payload[index++]; - - discResp.tag = frame.payload[index++]; - discResp.tag |= frame.payload[index++] << 8; - discResp.tag |= frame.payload[index++] << 16; - discResp.tag |= frame.payload[index++] << 24; - - uint8_t remainingLen = frame.payloadLen - index; - - uint8_t pubKeyLen = (remainingLen > 8) ? sizeof(discResp.pubkey) : 8; - memcpy(discResp.pubkey, &(frame.payload[index]), pubKeyLen); - index += pubKeyLen; + discReq.tag = frame->payload[index++]; + discReq.tag |= frame->payload[index++] << 8; + discReq.tag |= frame->payload[index++] << 16; + discReq.tag |= frame->payload[index++] << 24; + if (index < frame->payloadLen) { + discReq.since = frame->payload[index++]; + discReq.since |= frame->payload[index++] << 8; + discReq.since |= frame->payload[index++] << 16; + discReq.since |= frame->payload[index++] << 24; } + printDiscoverRequest (&discReq); + if ((discReq.typeFilter >> 2) & persistent.nodeType) { + DiscoverResponsePayload discResp; + + discResp.tag = discReq.tag; + discResp.nodeType = persistent.nodeType; + discResp.pubkeyLen = sizeof (persistent.pubkey); + memcpy (discResp.pubkey, persistent.pubkey, discResp.pubkeyLen); + discResp.snr = stats.lastSNR; // hopefully the correct one + + sendDiscoverResponse (&discResp); + MESH_LOGD(TAG, "Replying to a discover request with tag %d", discResp.tag); + } + + } else if (type == CONTROL_DATA_FLAG_DISCOVER_RESP) { + DiscoverResponsePayload discResp; + discResp.nodeType = frame->payload[index++] & 0x0F; + + discResp.snr = frame->payload[index++]; + + discResp.tag = frame->payload[index++]; + discResp.tag |= frame->payload[index++] << 8; + discResp.tag |= frame->payload[index++] << 16; + discResp.tag |= frame->payload[index++] << 24; + + uint8_t remainingLen = frame->payloadLen - index; + + uint8_t pubKeyLen = (remainingLen > 8) ? sizeof (discResp.pubkey) : 8; + discResp.pubkeyLen = pubKeyLen; + memcpy (discResp.pubkey, &(frame->payload[index]), discResp.pubkeyLen); + index += pubKeyLen; + printDiscoverResponse (&discResp); + } } \ No newline at end of file diff --git a/User/meshcore/packets/control.h b/User/meshcore/packets/control.h index 449a211..191cb1b 100644 --- a/User/meshcore/packets/control.h +++ b/User/meshcore/packets/control.h @@ -3,6 +3,14 @@ #include "meshcore/packetstructs.h" -void decodeControlFrame(FrameStruct frame); +void sendDiscoverRequest(const DiscoverRequestPayload *discReq); + +void sendDiscoverResponse(const DiscoverResponsePayload *discResp); + +void printDiscoverRequest(const DiscoverRequestPayload *p); + +void printDiscoverResponse(const DiscoverResponsePayload *p); + +void decodeControlFrame(const FrameStruct * frame); #endif \ No newline at end of file diff --git a/User/meshcore/packets/encrypted.c b/User/meshcore/packets/encrypted.c index bfc50ee..7c59ed2 100644 --- a/User/meshcore/packets/encrypted.c +++ b/User/meshcore/packets/encrypted.c @@ -1,4 +1,5 @@ #include "lib/config.h" +#include "lib/telemetry/telemetry.h" #include "meshcore/meshframing.h" #include "meshcore/packets/ack.h" #include "meshcore/packetstructs.h" @@ -10,6 +11,9 @@ #include "encrypted.h" #include "FreeRTOS.h" #include "task.h" +#include "lib/adc/temperature.h" + +#define TICKS_TO_MS(xTicks) (((uint32_t)(xTicks)*1000U) / (uint32_t)configTICK_RATE_HZ) #define TAG "EncryptedMessage" @@ -20,7 +24,7 @@ void sendEncryptedFrame (NodeEntry *targetNode, uint8_t payloadType, const uint8 // 1. Header frame.header = - ROUTE_TYPE_FLOOD | //currently flood + (targetNode->path.pathLen > 0 ? ROUTE_TYPE_DIRECT : ROUTE_TYPE_FLOOD) | // currently flood payloadType | PAYLOAD_VERSION_0; @@ -45,22 +49,22 @@ void sendEncryptedFrame (NodeEntry *targetNode, uint8_t payloadType, const uint8 memcpy (&frame.path, &targetNode->path, sizeof (frame.path)); hexdump ("Encrypted frame", frame.payload, frame.payloadLen); - sendFrame (frame); + LoRaTransmit (&frame); } void sendEncryptedTextMessage (NodeEntry *targetNode, const PlainTextMessagePayload *msg) { if (targetNode == NULL) { - ESP_LOGW(TAG, "Node is null"); + MESH_LOGW (TAG, "Node is null"); return; } if (targetNode->last_seen_lt == 0) { - ESP_LOGW(TAG, "Node is not populated"); + MESH_LOGW (TAG, "Node is not populated"); return; } uint8_t buf[256]; uint8_t index = 0; - uint8_t msgLen = strlen(msg->message) + 1; + uint8_t msgLen = strlen (msg->message) + 1; buf[index++] = msg->timestamp; buf[index++] = msg->timestamp >> 8; buf[index++] = msg->timestamp >> 16; @@ -80,12 +84,13 @@ void sendEncryptedResponse (NodeEntry *targetNode, const Response *resp) { uint8_t buf[256]; uint8_t index = 0; - buf[index++] = resp->tag; - buf[index++] = resp->tag >> 8; - buf[index++] = resp->tag >> 16; - buf[index++] = resp->tag >> 24; + buf[index++] = (resp->tag) & 0xFF; + buf[index++] = (resp->tag >> 8) & 0xFF; + buf[index++] = (resp->tag >> 16) & 0xFF; + buf[index++] = (resp->tag >> 24) & 0xFF; - memcpy (&buf[index], resp->data, resp->dataLen); + memcpy (&(buf[index]), resp->data, resp->dataLen); + index += resp->dataLen; sendEncryptedFrame ( targetNode, @@ -104,7 +109,8 @@ void sendEncryptedRequest (NodeEntry *targetNode, const Request *req) { buf[index++] = req->timestamp >> 24; buf[index++] = req->requestType; - memcpy (&buf[index], req->data, req->dataLen); + memcpy (&(buf[index]), req->data, req->dataLen); + index += req->dataLen; sendEncryptedFrame ( targetNode, @@ -123,7 +129,7 @@ void sendEncryptedPathPayload (NodeEntry *targetNode, const ReturnedPathPayload buf[index++] = path->extra.type; memcpy (&buf[index], path->extra.data, - sizeof (path->extra.data)); + path->extra.dataLen); sendEncryptedFrame ( targetNode, @@ -137,20 +143,14 @@ void printRequest (const Request *req) { printf (" Timestamp: %u\n", req->timestamp); printf (" Type: 0x%02X\n", req->requestType); printf (" Data: "); - for (int i = 0; i < req->dataLen; i++) { - printf ("%02X ", req->data[i]); - } - printf ("\n"); + hexdump (" Data", req->data, req->dataLen); } void printResponse (const Response *resp) { printf ("Response:\n"); printf (" Tag: %u\n", resp->tag); printf (" Data: "); - for (int i = 0; i < resp->dataLen; i++) { - printf ("%02X ", resp->data[i]); - } - printf ("\n"); + hexdump (" Data", resp->data, resp->dataLen); } void printPlainTextMessage (const PlainTextMessagePayload *msg) { @@ -165,16 +165,10 @@ void printReturnedPathPayload (const ReturnedPathPayload *path) { printf ("ReturnedPathPayload:\n"); printf (" Path Length: %u\n", path->path.pathLen); printf (" Path: "); - for (int i = 0; i < path->path.pathLen; i++) { - printf ("%02X ", path->path.path[i]); - } - printf ("\n"); + hexdump (" Path:", path->path.path, path->path.pathLen); printf (" Extra Type: %u\n", path->extra.type); printf (" Extra Data: "); - for (int i = 0; i < sizeof (path->extra.data); i++) { - printf ("%02X ", path->extra.data[i]); - } - printf ("\n"); + hexdump (" Extra data:", path->extra.data, path->extra.dataLen); } void printEncryptedPayload (const EncryptedPayloadStruct *enc) { @@ -191,22 +185,22 @@ void printEncryptedPayload (const EncryptedPayloadStruct *enc) { printf ("\n"); } -EncryptedPayloadStruct decodeEncryptedPayload (FrameStruct frame) { +void decodeEncryptedPayload (const FrameStruct *frame) { EncryptedPayloadStruct enc; memset (&enc, 0, sizeof (enc)); - enc.type = frame.header & PAYLOAD_TYPE_MASK; + enc.type = frame->header & PAYLOAD_TYPE_MASK; unsigned char index = 0; - enc.destinationHash = frame.payload[index++]; - enc.sourceHash = frame.payload[index++]; - enc.cipherMAC = frame.payload[index]; - enc.cipherMAC |= frame.payload[index + 1] << 8; + enc.destinationHash = frame->payload[index++]; + enc.sourceHash = frame->payload[index++]; + enc.cipherMAC = frame->payload[index]; + enc.cipherMAC |= frame->payload[index + 1] << 8; if (enc.destinationHash != persistent.pubkey[0]) { - return enc; + return; } - ESP_LOGI(TAG, "Finding remote node, sourceHash is %d", enc.sourceHash); + MESH_LOGI (TAG, "Finding remote node, sourceHash is %d", enc.sourceHash); NodeEntry *remNode = getNode (enc.sourceHash); @@ -214,96 +208,152 @@ EncryptedPayloadStruct decodeEncryptedPayload (FrameStruct frame) { if (remNode == NULL) { - ESP_LOGW(TAG, "Node not in DB"); - return enc; + MESH_LOGW (TAG, "Node not in DB"); + return; } - ESP_LOGI(TAG, "Found node with index %d", remNode - persistent.contacts); + MESH_LOGI (TAG, "Found node with index %d", remNode - persistent.contacts); - if (mac_then_decrypt (remNode->secret, 32, &(frame.payload[index]), frame.payloadLen - index, enc.payload) != 0) { - ESP_LOGW (TAG, "HMAC failed on encrypted message %s", remNode->name); + if (mac_then_decrypt (remNode->secret, 32, &(frame->payload[index]), frame->payloadLen - index, enc.payload) != 0) { + MESH_LOGW (TAG, "HMAC failed on encrypted message %s", remNode->name); } else { - enc.payloadLen = frame.payloadLen - HMAC_SIZE; - ESP_LOGI(TAG, "HMAC success from %s, %u bytes long", remNode->name, enc.payloadLen); - sendDiscreteAck(enc.payload, 5 + strlen((char *)&enc.payload[5]), remNode->pubKey); + enc.payloadLen = frame->payloadLen - HMAC_SIZE; + MESH_LOGI (TAG, "HMAC success from %s, %u bytes long", remNode->name, enc.payloadLen); + sendDiscreteAck (enc.payload, 5 + strlen ((char *)&enc.payload[5]), remNode->pubKey); } - return enc; + printf (" Typexdd: 0x%02X\n", enc.type); + if (enc.payloadLen > 0) { + parseEncryptedPayload (&enc); + } } -void parseEncryptedPayload (EncryptedPayloadStruct enc) { +void parseEncryptedPayload (const EncryptedPayloadStruct *enc) { // printEncryptedPayload(&enc); printf ("EncryptedPayload:\n"); - printf (" Type: 0x%02X\n", enc.type); - printf (" DestinationHash: 0x%02X\n", enc.destinationHash); - printf (" SourceHash: 0x%02X\n", enc.sourceHash); - printf (" CipherMAC: 0x%04X\n", enc.cipherMAC); - printf (" PayloadLen: %u\n", enc.payloadLen); - printf (" Payload: "); - hexdump("Full payload buffer", enc.payload, sizeof(enc.payload)); + printf (" Type: 0x%02X\n", enc->type); + printf (" DestinationHash: 0x%02X\n", enc->destinationHash); + printf (" SourceHash: 0x%02X\n", enc->sourceHash); + printf (" CipherMAC: 0x%04X\n", enc->cipherMAC); + printf (" PayloadLen: %u\n", enc->payloadLen); + hexdump (" Payload: ", enc->payload, enc->payloadLen); printf ("\n"); uint8_t index = 0; - if (enc.type == PAYLOAD_TYPE_PATH) { + if (enc->type == PAYLOAD_TYPE_PATH) { ReturnedPathPayload retPath; - retPath.path.pathLen = enc.payload[index++]; + retPath.path.pathLen = enc->payload[index++]; if (retPath.path.pathLen > 64) { - ESP_LOGW (TAG, "Path too long\n"); + MESH_LOGW (TAG, "Path too long\n"); return; } - memcpy (retPath.path.path, &(enc.payload[index]), retPath.path.pathLen); + memcpy (retPath.path.path, &(enc->payload[index]), retPath.path.pathLen); index += retPath.path.pathLen; - retPath.extra.type = enc.payload[index++]; - memcpy (retPath.extra.data, &(enc.payload[index]), enc.payloadLen - index); + retPath.extra.type = enc->payload[index++]; + retPath.extra.dataLen = enc->payloadLen - index; + memcpy (retPath.extra.data, &(enc->payload[index]), retPath.extra.dataLen); - } else if (enc.type == PAYLOAD_TYPE_REQ) { + } else if (enc->type == PAYLOAD_TYPE_REQ) { Request req; - req.timestamp = enc.payload[index++]; - req.timestamp |= enc.payload[index++] << 8; - req.timestamp |= enc.payload[index++] << 16; - req.timestamp |= enc.payload[index++] << 24; - req.requestType = enc.payload[index++]; - req.dataLen = enc.payloadLen - index; - memcpy (req.data, &(enc.payload[index]), req.dataLen); + req.timestamp = enc->payload[index++]; + req.timestamp |= enc->payload[index++] << 8; + req.timestamp |= enc->payload[index++] << 16; + req.timestamp |= enc->payload[index++] << 24; + req.requestType = enc->payload[index++]; + req.dataLen = enc->payloadLen - index; + memcpy (req.data, &(enc->payload[index]), req.dataLen); printRequest (&req); switch (req.requestType) { + case REQUEST_GET_STATS: { Response resp; resp.tag = RTC_GetCounter(); - memcpy(resp.data, &stats, sizeof(stats)); - resp.dataLen = sizeof(stats); - sendEncryptedResponse(enc.remNode, &resp); + stats.totalUpTimeSeconds = RTC_GetCounter() - startupTime; + stats.totalAirTimeSeconds = TICKS_TO_MS (tickAirtime / 1000); + memcpy (resp.data, &stats, sizeof (stats)); + resp.dataLen = sizeof (stats); + sendEncryptedResponse (enc->remNode, &resp); break; + } case REQUEST_KEEPALIVE: break; - case REQUEST_GET_TELEMETRY_DATA: + case REQUEST_GET_TELEMETRY_DATA: { + Response resp; + resp.tag = req.timestamp; + uint8_t index2 = 0; + resp.data[index2++] = TELEM_CHANNEL_SELF; + resp.data[index2++] = LPP_TEMPERATURE; + + int16_t dataTemp = getDeciTemperature(); + + printf ("The temperature is %d decicelsius\n", dataTemp); + + resp.data[index2++] = (dataTemp >> 8) & 0xFF; + + resp.data[index2++] = dataTemp & 0xFF; + + + resp.data[index2++] = TELEM_CHANNEL_SELF; + resp.data[index2++] = LPP_VOLTAGE; + + int16_t dataVolt = stats.millivolts / 10; + + resp.data[index2++] = (dataVolt >> 8) & 0xFF; + + resp.data[index2++] = dataVolt & 0xFF; + + if (enc->remNode->authenticated) { + + encode_gps (TELEM_CHANNEL_SELF, persistent.latitude / 1000000.0f, persistent.longitude / 1000000.0f, persistent.altitude / 100.0f, &(resp.data[index2])); + // encode_gps(TELEM_CHANNEL_SELF, 48.1909f, 17.0303f, 234.0f, &(resp.data[index2])); + + index2 += LPP_GPS_SIZE; + } + + if (enc->remNode->authenticated) { + + resp.data[index2++] = 2; + resp.data[index2++] = LPP_TEMPERATURE; + + int16_t jokeTemp = 6942; + + resp.data[index2++] = (jokeTemp >> 8) & 0xFF; + + resp.data[index2++] = jokeTemp & 0xFF; + + resp.dataLen = index2; + } + + sendEncryptedResponse (enc->remNode, &resp); + break; + } case REQUEST_GET_MIN_MAX_AVG: break; case REQUEST_GET_ACCESS_LIST: break; } - } else if (enc.type == PAYLOAD_TYPE_RESPONSE) { + } else if (enc->type == PAYLOAD_TYPE_RESPONSE) { Response resp; - resp.tag = enc.payload[index++]; - resp.tag |= enc.payload[index++] << 8; - resp.tag |= enc.payload[index++] << 16; - resp.tag |= enc.payload[index++] << 24; - resp.dataLen = enc.payloadLen - index; - memcpy (resp.data, &(enc.payload[index]), resp.dataLen); + resp.tag = enc->payload[index++]; + resp.tag |= enc->payload[index++] << 8; + resp.tag |= enc->payload[index++] << 16; + resp.tag |= enc->payload[index++] << 24; + resp.dataLen = enc->payloadLen - index; + memcpy (resp.data, &(enc->payload[index]), resp.dataLen); printResponse (&resp); - } else if (enc.type == PAYLOAD_TYPE_TXT_MSG) { + } else if (enc->type == PAYLOAD_TYPE_TXT_MSG) { PlainTextMessagePayload plaintext; - plaintext.timestamp = enc.payload[index++]; - plaintext.timestamp |= enc.payload[index++] << 8; - plaintext.timestamp |= enc.payload[index++] << 16; - plaintext.timestamp |= enc.payload[index++] << 24; - plaintext.attempt = enc.payload[index] & 0x03; - plaintext.textType = enc.payload[index++] >> 2; - memcpy (plaintext.message, &(enc.payload[index]), enc.payloadLen - index); + plaintext.timestamp = enc->payload[index++]; + plaintext.timestamp |= enc->payload[index++] << 8; + plaintext.timestamp |= enc->payload[index++] << 16; + plaintext.timestamp |= enc->payload[index++] << 24; + plaintext.attempt = enc->payload[index] & 0x03; + plaintext.textType = enc->payload[index++] >> 2; + memcpy (plaintext.message, &(enc->payload[index]), enc->payloadLen - index); printPlainTextMessage (&plaintext); } } \ No newline at end of file diff --git a/User/meshcore/packets/encrypted.h b/User/meshcore/packets/encrypted.h index 342754b..1954450 100644 --- a/User/meshcore/packets/encrypted.h +++ b/User/meshcore/packets/encrypted.h @@ -18,8 +18,8 @@ void sendEncryptedRequest (NodeEntry *targetNode, const Request *req); void sendEncryptedPathPayload (NodeEntry *targetNode, const ReturnedPathPayload *path); -EncryptedPayloadStruct decodeEncryptedPayload (FrameStruct frame); +void decodeEncryptedPayload (const FrameStruct *frame); -void parseEncryptedPayload (EncryptedPayloadStruct enc); +void parseEncryptedPayload (const EncryptedPayloadStruct * enc); #endif \ No newline at end of file diff --git a/User/meshcore/packets/group.c b/User/meshcore/packets/group.c index 446f043..2ab8bae 100644 --- a/User/meshcore/packets/group.c +++ b/User/meshcore/packets/group.c @@ -9,61 +9,64 @@ #define TAG "GroupMessage" -void sendGroupMessage (GroupTextMessage msg) { - - msg.channelHash = persistent.aesKeys[msg.keyIndex][0]; - - msg.flags = 0; - msg.timestamp = RTC_GetCounter(); +void sendGroupMessage (const GroupTextMessage *msg) { + // Prepare values locally instead of modifying msg + uint8_t channelHash = persistent.aesKeys[msg->keyIndex][0]; + uint8_t flags = 0; + int32_t timestamp = RTC_GetCounter(); FrameStruct frame; frame.header = ROUTE_TYPE_FLOOD | PAYLOAD_TYPE_GRP_TXT | PAYLOAD_VERSION_0; frame.path.pathLen = 0; size_t offset = 0; - memset (frame.payload, 0, sizeof (frame.payload)); - frame.payload[offset++] = msg.channelHash; + frame.payload[offset++] = channelHash; - uint8_t cipherBuf[176]; - size_t offset2 = 0; - memcpy (cipherBuf, (const void *)&(msg.timestamp), 4); - offset2 += 4; - cipherBuf[offset2++] = msg.flags; - size_t textSize = offset2 + strlen ((const char *)msg.text); - if (textSize > 175) { - textSize = 175; + // Build encryption buffer directly on stack (no extra large buffer) + uint8_t buf[180]; // enough for timestamp + flags + text + size_t buf_offset = 0; + + memcpy (buf + buf_offset, ×tamp, sizeof (timestamp)); + buf_offset += sizeof (timestamp); + + buf[buf_offset++] = flags; + + size_t textLen = strlen ((const char *)msg->text); + if (buf_offset + textLen > sizeof (buf)) { + textLen = sizeof (buf) - buf_offset; } - memcpy (cipherBuf + offset2, msg.text, textSize); - offset2 += textSize; + memcpy (buf + buf_offset, msg->text, textLen); + buf_offset += textLen; + hexdump ("TxDumpDec", buf, buf_offset); + + // Encrypt and MAC directly into frame payload after channelHash size_t olen = 0; - hexdump ("TxDumpDec", cipherBuf, offset2); - encrypt_then_mac (&(persistent.aesKeys[msg.keyIndex][1]), 16, cipherBuf, offset2, &(frame.payload[offset]), &olen); + encrypt_then_mac (&persistent.aesKeys[msg->keyIndex][1], 16, buf, buf_offset, &frame.payload[offset], &olen); - frame.payloadLen = olen + 1; + frame.payloadLen = olen + 1; // +1 for channelHash - sendFrame (frame); - return; + LoRaTransmit (&frame); } void makeSendGroupMessage (char *txt, uint8_t keyIndex) { GroupTextMessage msg; - strcpy((char *) msg.text, persistent.nodeName); + strcpy ((char *)msg.text, persistent.nodeName); strcat ((char *)msg.text, ": "); strcat ((char *)msg.text, txt); msg.keyIndex = keyIndex; - sendGroupMessage (msg); + sendGroupMessage (&msg); return; } -GroupTextMessage decodeGroupMessage (FrameStruct frame) { +void decodeGroupMessage (const FrameStruct *frame) { GroupTextMessage msg; memset (&msg, 0, sizeof (msg)); - if ((frame.header & PAYLOAD_TYPE_MASK) != PAYLOAD_TYPE_GRP_TXT) { - ESP_LOGW (TAG, "Not a group text"); - return msg; + if ((frame->header & PAYLOAD_TYPE_MASK) != PAYLOAD_TYPE_GRP_TXT) { + MESH_LOGW (TAG, "Not a group text"); + return; } unsigned char index = 0; - msg.channelHash = frame.payload[index++]; + msg.channelHash = frame->payload[index++]; unsigned char tmp[184]; @@ -71,27 +74,27 @@ GroupTextMessage decodeGroupMessage (FrameStruct frame) { for (unsigned char i = 0; i < AESKeyCount; i++) { if (msg.channelHash != persistent.aesKeys[i][0]) { - ESP_LOGW (TAG, "Hash %d does not equal %d", persistent.aesKeys[i][0], msg.channelHash); + MESH_LOGW (TAG, "Hash %d does not equal %d", persistent.aesKeys[i][0], msg.channelHash); continue; } - ESP_LOGW (TAG, "Hash does equal %d", msg.channelHash); + MESH_LOGW (TAG, "Hash does equal %d", msg.channelHash); - if (mac_then_decrypt (persistent.aesKeys[i] + 1, 16, frame.payload + index, frame.payloadLen - index, tmp) != 0) { - ESP_LOGW (TAG, "HMAC failed on grouphash key %d not matching %d", persistent.aesKeys[i][0], msg.channelHash); + if (mac_then_decrypt (persistent.aesKeys[i] + 1, 16, frame->payload + index, frame->payloadLen - index, tmp) != 0) { + MESH_LOGW (TAG, "HMAC failed on grouphash key %d not matching %d", persistent.aesKeys[i][0], msg.channelHash); continue; } - hexdump ("RxDumpDec", tmp, frame.payloadLen - index); + hexdump ("RxDumpDec", tmp, frame->payloadLen - index); decrypted = 1; break; } if (!decrypted) { - return msg; + return; } - unsigned char plaintextLen = frame.payloadLen - index; + unsigned char plaintextLen = frame->payloadLen - index; index = 0; memcpy (&msg.timestamp, tmp + index, 4); @@ -99,10 +102,11 @@ GroupTextMessage decodeGroupMessage (FrameStruct frame) { msg.flags = tmp[index++]; memcpy (msg.text, tmp + index, plaintextLen - index); - return msg; + + printGroupMessage (&msg); } -void printGroupMessage (GroupTextMessage msg) { - printf ("Message with channel hash %d, flags %d: %s\n", msg.channelHash, - msg.flags, msg.text); +void printGroupMessage (const GroupTextMessage *msg) { + printf ("Message with channel hash %d, flags %d: %s\n", msg->channelHash, + msg->flags, msg->text); } \ No newline at end of file diff --git a/User/meshcore/packets/group.h b/User/meshcore/packets/group.h index 714a985..7e97381 100644 --- a/User/meshcore/packets/group.h +++ b/User/meshcore/packets/group.h @@ -4,12 +4,12 @@ #include "stdint.h" #include "meshcore/packetstructs.h" -void sendGroupMessage (GroupTextMessage msg); +void sendGroupMessage (const GroupTextMessage * msg); void makeSendGroupMessage (char *txt, uint8_t keyIndex); -GroupTextMessage decodeGroupMessage (FrameStruct frame); +void decodeGroupMessage (const FrameStruct * frame); -void printGroupMessage (GroupTextMessage msg); +void printGroupMessage (const GroupTextMessage * msg); #endif \ No newline at end of file diff --git a/User/meshcore/packetstructs.h b/User/meshcore/packetstructs.h index 24a2fe1..688c555 100644 --- a/User/meshcore/packetstructs.h +++ b/User/meshcore/packetstructs.h @@ -56,6 +56,7 @@ typedef struct DiscoverResponsePayload { int8_t snr; uint32_t tag; uint8_t pubkey[32]; + uint8_t pubkeyLen; } DiscoverResponsePayload; typedef struct AnonymousRequestPayload { @@ -116,6 +117,27 @@ typedef struct Node { char flags; } Node; +typedef struct { + char name[32]; + unsigned char pubKey[32]; + unsigned char secret[32]; + + int32_t gps_latitude; + int32_t gps_longitude; + + Path path; + + uint8_t flags; + uint8_t type; + + uint8_t authenticated; + + uint32_t last_seen_rt; //remote timestamp + uint32_t last_seen_lt; //local timestamp + + uint32_t sync_timestamp; +} NodeEntry; + typedef struct EncryptedPayloadStruct { uint8_t destinationHash; uint8_t sourceHash; @@ -153,6 +175,7 @@ typedef struct AdvertisementPayload { uint8_t pubKey[32]; int32_t timestamp; uint8_t signature[64]; + uint8_t valid; uint8_t dataFlags; int32_t latitude; int32_t longitude; @@ -164,6 +187,7 @@ typedef struct AdvertisementPayload { typedef struct Extra { uint8_t type; + uint8_t dataLen; uint8_t data[180]; // hopefully long enough } Extra; @@ -204,4 +228,8 @@ typedef struct RepeaterStats { uint32_t total_rx_air_time_secs; } RepeaterStats; +typedef struct Channel { + +} Channel; + #endif diff --git a/User/meshcore/stats.c b/User/meshcore/stats.c index 735ab0c..44f0ad5 100644 --- a/User/meshcore/stats.c +++ b/User/meshcore/stats.c @@ -1,3 +1,6 @@ #include "stats.h" -RepeaterStats stats; \ No newline at end of file +RepeaterStats stats; + +uint32_t startupTime = 0; +uint32_t tickAirtime = 0; \ No newline at end of file diff --git a/User/meshcore/stats.h b/User/meshcore/stats.h index f8fe80d..6d30224 100644 --- a/User/meshcore/stats.h +++ b/User/meshcore/stats.h @@ -4,4 +4,8 @@ extern RepeaterStats stats; +extern uint32_t startupTime; + +extern uint32_t tickAirtime; + #endif \ No newline at end of file diff --git a/User/sx1262.c b/User/sx1262.c index e095a59..fd108dd 100644 --- a/User/sx1262.c +++ b/User/sx1262.c @@ -11,9 +11,9 @@ #define TAG "SX1262" // Global Stuff -static uint8_t PacketParams[6]; -static char txActive; -static int txLost = 0; +uint8_t PacketParams[6]; +char txActive; +int txLost = 0; static char debugPrint; // Arduino compatible macros @@ -22,7 +22,7 @@ static char debugPrint; void LoRaError (int error) { if (debugPrint) { - ESP_LOGE (TAG, "LoRaErrorDefault=%d", error); + MESH_LOGE (TAG, "LoRaErrorDefault=%d", error); } while (1) { vTaskDelay (1); @@ -112,7 +112,7 @@ void spi_read_byte (uint8_t *rx, const uint8_t *tx, size_t len) { // Wait TX ready while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_TXE) == RESET); if (debugPrint) { - printf ("Sent %02X over spi.\n", out); + MESH_LOGV (TAG, "Sent %02X over spi.\n", out); } SPI_I2S_SendData (SPI1, out); // Wait RX ready @@ -121,7 +121,7 @@ void spi_read_byte (uint8_t *rx, const uint8_t *tx, size_t len) { uint8_t in = (uint8_t)SPI_I2S_ReceiveData (SPI1); if (debugPrint) { - printf ("Got %02X over spi.\n", in); + MESH_LOGV (TAG, "Got %02X over spi.\n", in); } if (rx) rx[i] = in; @@ -129,6 +129,36 @@ void spi_read_byte (uint8_t *rx, const uint8_t *tx, size_t len) { GPIO_WriteBit (GPIOA, GPIO_Pin_4, 1); } +// Full-duplex transfer: TX and RX buffers +void spi_read_byte_offs (uint8_t *rx, const uint8_t *tx, size_t len, uint8_t off) { + GPIO_WriteBit (GPIOA, GPIO_Pin_4, 0); + for (size_t i = 0; i < len; i++) { + uint8_t out = 0xFF; + if (i < off) { + out = tx ? tx[i] : 0xFF; + } + + // Wait TX ready + while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_TXE) == RESET); + if (debugPrint) { + MESH_LOGV (TAG, "Sent %02X over spi.\n", out); + } + SPI_I2S_SendData (SPI1, out); + // Wait RX ready + + while (SPI_I2S_GetFlagStatus (SPI1, SPI_I2S_FLAG_RXNE) == RESET); + + uint8_t in = (uint8_t)SPI_I2S_ReceiveData (SPI1); + if (debugPrint) { + MESH_LOGV (TAG, "Got %02X over spi.\n", in); + } + if (rx && i >= off) { + rx[i - off] = in; + } + } + GPIO_WriteBit (GPIOA, GPIO_Pin_4, 1); +} + int16_t LoRaBegin (uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltage, char useRegulatorLDO) { if (txPowerInDbm > 22) { txPowerInDbm = 22; @@ -142,17 +172,17 @@ int16_t LoRaBegin (uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltag uint8_t wk[2]; ReadRegister (SX126X_REG_LORA_SYNC_WORD_MSB, wk, 2); // 0x0740 uint16_t syncWord = (wk[0] << 8) + wk[1]; - ESP_LOGI (TAG, "syncWord=0x%x", syncWord); + MESH_LOGI (TAG, "syncWord=0x%x", syncWord); if (syncWord != SX126X_SYNC_WORD_PUBLIC && syncWord != SX126X_SYNC_WORD_PRIVATE) { - ESP_LOGE (TAG, "SX126x error, maybe no SPI connection"); + MESH_LOGE (TAG, "SX126x error, maybe no SPI connection"); return ERR_INVALID_MODE; } - ESP_LOGI (TAG, "SX126x installed"); + MESH_LOGI (TAG, "SX126x installed"); SetStandby (SX126X_STANDBY_RC); SetDio2AsRfSwitchCtrl (1); - ESP_LOGI (TAG, "tcxoVoltage=%f", tcxoVoltage); + MESH_LOGI (TAG, "tcxoVoltage=%f", tcxoVoltage); // set TCXO control, if requested if (tcxoVoltage > 0.0) { SetDio3AsTcxoCtrl (tcxoVoltage, RADIO_TCXO_SETUP_TIME); // Configure the radio to use a TCXO controlled by DIO3 @@ -160,7 +190,7 @@ int16_t LoRaBegin (uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltag Calibrate (SX126X_CALIBRATE_IMAGE_ON | SX126X_CALIBRATE_ADC_BULK_P_ON | SX126X_CALIBRATE_ADC_BULK_N_ON | SX126X_CALIBRATE_ADC_PULSE_ON | SX126X_CALIBRATE_PLL_ON | SX126X_CALIBRATE_RC13M_ON | SX126X_CALIBRATE_RC64K_ON); - ESP_LOGI (TAG, "useRegulatorLDO=%d", useRegulatorLDO); + MESH_LOGI (TAG, "useRegulatorLDO=%d", useRegulatorLDO); if (useRegulatorLDO) { SetRegulatorMode (SX126X_REGULATOR_LDO); // set regulator mode: LDO } else { @@ -239,7 +269,7 @@ void LoRaConfig (uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, ); - ESP_LOGI (TAG, "Almost done setting LoRa"); + MESH_LOGI (TAG, "Almost done setting LoRa"); // Receive state no receive timeoout SetRx (0xFFFFFF); } @@ -286,12 +316,12 @@ char LoRaSend (uint8_t *pData, int16_t len, uint8_t mode) { irqStatus = GetIrqStatus(); } if (debugPrint) { - ESP_LOGI (TAG, "irqStatus=0x%x", irqStatus); + MESH_LOGI (TAG, "irqStatus=0x%x", irqStatus); if (irqStatus & SX126X_IRQ_TX_DONE) { - ESP_LOGI (TAG, "SX126X_IRQ_TX_DONE"); + MESH_LOGI (TAG, "SX126X_IRQ_TX_DONE"); } if (irqStatus & SX126X_IRQ_TIMEOUT) { - ESP_LOGI (TAG, "SX126X_IRQ_TIMEOUT"); + MESH_LOGI (TAG, "SX126X_IRQ_TIMEOUT"); } } txActive = 0; @@ -306,7 +336,7 @@ char LoRaSend (uint8_t *pData, int16_t len, uint8_t mode) { } } if (debugPrint) { - ESP_LOGI (TAG, "Send rv=0x%x", rv); + MESH_LOGI (TAG, "Send rv=0x%x", rv); } if (rv == 0) txLost++; @@ -331,11 +361,12 @@ char ReceiveMode (void) { return rv; } -void GetPacketStatus (int8_t *rssiPacket, int8_t *snrPacket) { +void GetPacketStatus (int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr) { uint8_t buf[4]; ReadCommand (SX126X_CMD_GET_PACKET_STATUS, buf, 4); // 0x14 *rssiPacket = (buf[3] >> 1) * -1; (buf[2] < 128) ? (*snrPacket = buf[2] >> 2) : (*snrPacket = ((buf[2] - 256) >> 2)); + *rawSnr = buf[2]; } void SetTxPower (int8_t txPowerInDbm) { @@ -347,7 +378,7 @@ void ResetLora (void) { GPIO_WriteBit (GPIOE, GPIO_Pin_3, 0); vTaskDelay (pdMS_TO_TICKS (20)); GPIO_WriteBit (GPIOE, GPIO_Pin_3, 1); - ESP_LOGW (TAG, "Waiting for idle"); + MESH_LOGW (TAG, "Waiting for idle"); vTaskDelay (pdMS_TO_TICKS (10)); // ensure BUSY is low (state meachine ready) WaitForIdle (BUSY_WAIT, "Reset", 1); @@ -512,7 +543,7 @@ void SetDioIrqParams (uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, ui } void SetStopRxTimerOnPreambleDetect (char enable) { - ESP_LOGI (TAG, "SetStopRxTimerOnPreambleDetect enable=%d", enable); + MESH_LOGI (TAG, "SetStopRxTimerOnPreambleDetect enable=%d", enable); // uint8_t data = (uint8_t)enable; uint8_t data = 0; if (enable) @@ -573,7 +604,7 @@ void ClearIrqStatus (uint16_t irq) { void SetRx (uint32_t timeout) { if (debugPrint) { - ESP_LOGI (TAG, "----- SetRx timeout=%d", timeout); + MESH_LOGI (TAG, "----- SetRx timeout=%d", timeout); } SetStandby (SX126X_STANDBY_RC); uint8_t buf[3]; @@ -588,14 +619,14 @@ void SetRx (uint32_t timeout) { vTaskDelay (pdMS_TO_TICKS (1)); } if ((GetStatus() & 0x70) != 0x50) { - ESP_LOGE (TAG, "SetRx Illegal Status"); + MESH_LOGE (TAG, "SetRx Illegal Status"); LoRaError (ERR_INVALID_SETRX_STATE); } } void SetTx (uint32_t timeoutInMs) { if (debugPrint) { - ESP_LOGI (TAG, "----- SetTx timeoutInMs=%d", timeoutInMs); + MESH_LOGI (TAG, "----- SetTx timeoutInMs=%d", timeoutInMs); } SetStandby (SX126X_STANDBY_RC); uint8_t buf[3]; @@ -605,7 +636,9 @@ void SetTx (uint32_t timeoutInMs) { tout = (uint32_t)(timeoutInUs / 0.015625); } if (debugPrint) { - ESP_LOGI (TAG, "SetTx timeoutInMs=%d" " tout=%d", timeoutInMs, tout); + MESH_LOGI (TAG, "SetTx timeoutInMs=%d" + " tout=%d", + timeoutInMs, tout); } buf[0] = (uint8_t)((tout >> 16) & 0xFF); buf[1] = (uint8_t)((tout >> 8) & 0xFF); @@ -618,7 +651,7 @@ void SetTx (uint32_t timeoutInMs) { vTaskDelay (1); } if ((GetStatus() & 0x70) != 0x60) { - ESP_LOGE (TAG, "SetTx Illegal Status"); + MESH_LOGE (TAG, "SetTx Illegal Status"); LoRaError (ERR_INVALID_SETTX_STATE); } } @@ -649,7 +682,7 @@ void WaitForIdleBegin (unsigned long timeout, char *text) { char ret = WaitForIdle (BUSY_WAIT, text, stop); if (ret == 1) break; - ESP_LOGW (TAG, "WaitForIdle fail retry=%d", retry); + MESH_LOGW (TAG, "WaitForIdle fail retry=%d", retry); vTaskDelay (pdMS_TO_TICKS (10)); } } @@ -666,22 +699,23 @@ char WaitForIdle (unsigned long timeout, char *text, char stop) { if (GPIO_ReadInputDataBit (GPIOE, GPIO_Pin_1)) { if (stop) { - ESP_LOGE (TAG, "WaitForIdle Timeout text=%s timeout=%lu start=%d", text, timeout, start); + MESH_LOGE (TAG, "WaitForIdle Timeout text=%s timeout=%lu start=%d", text, timeout, start); LoRaError (ERR_IDLE_TIMEOUT); } else { - ESP_LOGW (TAG, "WaitForIdle Timeout text=%s timeout=%lu start=%d", text, timeout, start); + MESH_LOGW (TAG, "WaitForIdle Timeout text=%s timeout=%lu start=%d", text, timeout, start); ret = 0; } } return ret; } +/* uint8_t ReadBuffer (uint8_t *rxData, int16_t rxDataLen) { uint8_t offset = 0; uint8_t payloadLength = 0; GetRxBufferStatus (&payloadLength, &offset); if (payloadLength > rxDataLen) { - ESP_LOGW (TAG, "ReadBuffer rxDataLen too small. payloadLength=%d rxDataLen=%d", payloadLength, rxDataLen); + MESH_LOGW (TAG, "ReadBuffer rxDataLen too small. payloadLength=%d rxDataLen=%d", payloadLength, rxDataLen); return 0; } @@ -700,13 +734,35 @@ uint8_t ReadBuffer (uint8_t *rxData, int16_t rxDataLen) { memcpy (rxData, &buf[3], payloadLength); free (buf); } else { - ESP_LOGE (TAG, "ReadBuffer malloc fail"); + MESH_LOGE (TAG, "ReadBuffer malloc fail"); payloadLength = 0; } // wait for BUSY to go low WaitForIdle (BUSY_WAIT, "end ReadBuffer", 0); + return payloadLength; +}*/ + + +uint8_t ReadBuffer (uint8_t *rxData, int16_t rxDataLen) { + uint8_t offset = 0; + uint8_t payloadLength = 0; + GetRxBufferStatus (&payloadLength, &offset); + + if (payloadLength > rxDataLen) { + MESH_LOGW (TAG, "ReadBuffer rxDataLen too small. payloadLength=%d rxDataLen=%d", payloadLength, rxDataLen); + return 0; + } + + WaitForIdle (BUSY_WAIT, "start ReadBuffer", 1); + + uint8_t cmd[3] = {SX126X_CMD_READ_BUFFER, offset, SX126X_CMD_NOP}; + + spi_read_byte_offs (rxData, cmd, rxDataLen, sizeof (cmd)); + + WaitForIdle (BUSY_WAIT, "end ReadBuffer", 0); + return payloadLength; } @@ -724,7 +780,7 @@ void WriteBuffer (uint8_t *txData, int16_t txDataLen) { spi_write_byte (buf, txDataLen + 2); free (buf); } else { - ESP_LOGE (TAG, "WriteBuffer malloc fail"); + MESH_LOGE (TAG, "WriteBuffer malloc fail"); } // wait for BUSY to go low @@ -736,9 +792,9 @@ void WriteRegister (uint16_t reg, uint8_t *data, uint8_t numBytes) { WaitForIdle (BUSY_WAIT, "start WriteRegister", 1); if (debugPrint) { - ESP_LOGI (TAG, "WriteRegister: REG=0x%02x", reg); + MESH_LOGI (TAG, "WriteRegister: REG=0x%02x", reg); for (uint8_t n = 0; n < numBytes; n++) { - ESP_LOGI (TAG, "DataOut:%02x ", data[n]); + MESH_LOGI (TAG, "DataOut:%02x ", data[n]); } } @@ -759,7 +815,7 @@ void ReadRegister (uint16_t reg, uint8_t *data, uint8_t numBytes) { WaitForIdle (BUSY_WAIT, "start ReadRegister", 1); if (debugPrint) { - ESP_LOGI (TAG, "ReadRegister: REG=0x%02x", reg); + MESH_LOGI (TAG, "ReadRegister: REG=0x%02x", reg); } // start transfer @@ -771,15 +827,15 @@ void ReadRegister (uint16_t reg, uint8_t *data, uint8_t numBytes) { buf[1] = (reg & 0xFF00) >> 8; buf[2] = reg & 0xff; if (debugPrint) { - ESP_LOGI (TAG, "Reading bytes"); + MESH_LOGI (TAG, "Reading bytes"); } spi_read_byte (buf2, buf, 4 + numBytes); - ESP_LOGI (TAG, "read a byte"); + MESH_LOGI (TAG, "read a byte"); memcpy (data, &buf2[4], numBytes); if (debugPrint) { for (uint8_t n = 0; n < numBytes; n++) { - ESP_LOGI (TAG, "DataIn:%02x ", data[n]); + MESH_LOGI (TAG, "DataIn:%02x ", data[n]); } } @@ -793,14 +849,14 @@ void WriteCommand (uint8_t cmd, uint8_t *data, uint8_t numBytes) { for (int retry = 1; retry < 10; retry++) { status = WriteCommand2 (cmd, data, numBytes); if (debugPrint) { - ESP_LOGD (TAG, "status=%02x", status); + MESH_LOGD (TAG, "status=%02x", status); } if (status == 0) break; - ESP_LOGW (TAG, "WriteCommand2 status=%02x retry=%d", status, retry); + MESH_LOGW (TAG, "WriteCommand2 status=%02x retry=%d", status, retry); } if (status != 0) { - ESP_LOGE (TAG, "SPI Transaction error:0x%02x", status); + MESH_LOGE (TAG, "SPI Transaction error:0x%02x", status); LoRaError (ERR_SPI_TRANSACTION); } } @@ -810,7 +866,7 @@ uint8_t WriteCommand2 (uint8_t cmd, uint8_t *data, uint8_t numBytes) { WaitForIdle (BUSY_WAIT, "start WriteCommand2", 1); if (debugPrint) { - ESP_LOGI (TAG, "WriteCommand: CMD=0x%02x", cmd); + MESH_LOGI (TAG, "WriteCommand: CMD=0x%02x", cmd); } // start transfer @@ -846,7 +902,7 @@ void ReadCommand (uint8_t cmd, uint8_t *data, uint8_t numBytes) { WaitForIdleBegin (BUSY_WAIT, "start ReadCommand"); if (debugPrint) { - ESP_LOGI (TAG, "ReadCommand: CMD=0x%02x", cmd); + MESH_LOGI (TAG, "ReadCommand: CMD=0x%02x", cmd); } // start transfer diff --git a/User/sx1262.h b/User/sx1262.h index f96f188..1fe4a2a 100644 --- a/User/sx1262.h +++ b/User/sx1262.h @@ -381,10 +381,11 @@ void LoRaDebugPrint(char enable); // Private function void spi_write_byte(uint8_t* Dataout, size_t DataLength ); void spi_read_byte(uint8_t *rx, const uint8_t *tx, size_t len); +void spi_read_byte_offs (uint8_t *rx, const uint8_t *tx, size_t len, uint8_t off); uint8_t spi_transfer(uint8_t address); char ReceiveMode(void); -void GetPacketStatus(int8_t *rssiPacket, int8_t *snrPacket); +void GetPacketStatus (int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr); void SetTxPower(int8_t txPowerInDbm); void FixInvertedIQ(uint8_t iqConfig); @@ -429,5 +430,8 @@ void ReadCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes); void SPItransfer(uint8_t cmd, char write, uint8_t* dataOut, uint8_t* dataIn, uint8_t numBytes, char waitForBusy); void LoRaError(int error); +extern uint8_t PacketParams[6]; +extern char txActive; +extern int txLost; #endif diff --git a/User/util/log.h b/User/util/log.h index 714c64a..db555b9 100644 --- a/User/util/log.h +++ b/User/util/log.h @@ -1,20 +1,33 @@ #ifndef LOGGER_HEADER #define LOGGER_HEADER -// Define log levels -#define LOG_ERROR "E" -#define LOG_WARN "W" -#define LOG_INFO "I" -#define LOG_DEBUG "D" +#include -// Define a generic log macro -#define LOG_PRINT(level, tag, fmt, ...) \ - printf("[%s] %s: " fmt "\r\n", level, tag, ##__VA_ARGS__) +// Log levels as integers for easy comparison +#define LOG_LEVEL_ERROR 0 +#define LOG_LEVEL_WARN 1 +#define LOG_LEVEL_INFO 2 +#define LOG_LEVEL_DEBUG 3 +#define LOG_LEVEL_VERBOSE 4 -// Define ESP-like shortcuts -#define ESP_LOGE(tag, fmt, ...) LOG_PRINT(LOG_ERROR, tag, fmt, ##__VA_ARGS__) -#define ESP_LOGW(tag, fmt, ...) LOG_PRINT(LOG_WARN, tag, fmt, ##__VA_ARGS__) -#define ESP_LOGI(tag, fmt, ...) LOG_PRINT(LOG_INFO, tag, fmt, ##__VA_ARGS__) -#define ESP_LOGD(tag, fmt, ...) LOG_PRINT(LOG_DEBUG, tag, fmt, ##__VA_ARGS__) +// Current log level (change at runtime or compile-time) +#ifndef CURRENT_LOG_LEVEL +#define CURRENT_LOG_LEVEL LOG_LEVEL_DEBUG +#endif -#endif \ No newline at end of file +// Internal macro to check log level +#define LOG_PRINT_IF(level, levelStr, tag, fmt, ...) \ + do { \ + if ((level) <= CURRENT_LOG_LEVEL) { \ + printf("[%s] %s: " fmt "\r\n", levelStr, tag, ##__VA_ARGS__); \ + } \ + } while(0) + +// ESP-like shortcuts +#define MESH_LOGE(tag, fmt, ...) LOG_PRINT_IF(LOG_LEVEL_ERROR, "E", tag, fmt, ##__VA_ARGS__) +#define MESH_LOGW(tag, fmt, ...) LOG_PRINT_IF(LOG_LEVEL_WARN, "W", tag, fmt, ##__VA_ARGS__) +#define MESH_LOGI(tag, fmt, ...) LOG_PRINT_IF(LOG_LEVEL_INFO, "I", tag, fmt, ##__VA_ARGS__) +#define MESH_LOGD(tag, fmt, ...) LOG_PRINT_IF(LOG_LEVEL_DEBUG, "D", tag, fmt, ##__VA_ARGS__) +#define MESH_LOGV(tag, fmt, ...) LOG_PRINT_IF(LOG_LEVEL_VERBOSE, "V", tag, fmt, ##__VA_ARGS__) + +#endif