diff --git a/.mrs/b8de1c376c1e7394fcaec2d3f2322ffc-.snapshot b/.mrs/b8de1c376c1e7394fcaec2d3f2322ffc-.snapshot index 3917de6..8a9b737 100644 --- a/.mrs/b8de1c376c1e7394fcaec2d3f2322ffc-.snapshot +++ b/.mrs/b8de1c376c1e7394fcaec2d3f2322ffc-.snapshot @@ -1 +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 +{"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/lib/config.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/config.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/config.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/config.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/config.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/config.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/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/lib/base64.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/base64.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/base64.c\",\"scheme\":\"file\"},\"encoding\":\"gbk\"}"},{"id":"workbench.editors.files.fileEditorInput","value":"{\"resourceJSON\":{\"$mid\":1,\"fsPath\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/hexdump.c\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/hexdump.c\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/hexdump.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/User/util/hexdump.h\",\"external\":\"file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/hexdump.h\",\"path\":\"/home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/hexdump.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\"}"}],"mru":[3,2,0,1,7,6,5,4,8]},"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/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/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/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/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/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/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/control.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":126,"column":88},"position":{"lineNumber":126,"column":88}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":106,"column":1},"firstPositionDeltaTop":-9},"contributionsState":{"editor.contrib.folding":{"lineCount":150,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":2004}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/hmac.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":109,"column":5},"position":{"lineNumber":109,"column":16}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":88,"column":1},"firstPositionDeltaTop":-9},"contributionsState":{"editor.contrib.folding":{"lineCount":118,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1695}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/handy.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":54,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":87,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1040}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/prp.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":45,"column":1},"firstPositionDeltaTop":-12},"contributionsState":{"editor.contrib.folding":{"lineCount":65,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":881}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/sha2.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":70,"column":13},"position":{"lineNumber":70,"column":27}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":58,"column":1},"firstPositionDeltaTop":-15},"contributionsState":{"editor.contrib.folding":{"lineCount":236,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1131}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/sha256.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":49,"column":6},"position":{"lineNumber":49,"column":20}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":28,"column":1},"firstPositionDeltaTop":-9},"contributionsState":{"editor.contrib.folding":{"lineCount":232,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":555}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/ack.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":19,"column":1},"position":{"lineNumber":36,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":9,"column":1},"firstPositionDeltaTop":-5},"contributionsState":{"editor.contrib.folding":{"lineCount":43,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":190}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/cifra/chash.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":19,"column":20},"position":{"lineNumber":19,"column":20}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":138,"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/license.txt",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":15,"column":1},"position":{"lineNumber":15,"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,"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":52},"position":{"lineNumber":11,"column":52}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":13,"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.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":101,"column":73},"position":{"lineNumber":101,"column":73}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":74,"column":1},"firstPositionDeltaTop":-17},"contributionsState":{"editor.contrib.folding":{"lineCount":107,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1404}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/rtc/rtc.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":6,"column":24},"position":{"lineNumber":6,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":33},"contributionsState":{"editor.contrib.folding":{"lineCount":293,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":true,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/rtc/rtc.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":76,"column":1},"firstPositionDeltaTop":-6},"contributionsState":{"editor.contrib.folding":{"lineCount":97,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1431}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshframing.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":28,"column":43},"position":{"lineNumber":28,"column":43}}],"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/meshcore/packets/advert.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":176,"column":16},"position":{"lineNumber":176,"column":27}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":161,"column":1},"firstPositionDeltaTop":-1},"contributionsState":{"editor.contrib.folding":{"lineCount":209,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":3041}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/encrypted.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":27,"column":61},"position":{"lineNumber":27,"column":61}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":29,"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/anonymous.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":212,"column":15},"position":{"lineNumber":212,"column":15}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":188,"column":1},"firstPositionDeltaTop":-12},"contributionsState":{"editor.contrib.folding":{"lineCount":217,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":3598}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshcore.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":14,"column":20},"position":{"lineNumber":14,"column":20}}],"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":4,"column":61},"position":{"lineNumber":4,"column":30}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":29,"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/keypair.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":6,"column":105},"position":{"lineNumber":6,"column":109}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":24,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":0}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/Peripheral/src/ch32v30x_rng.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":43,"column":10},"position":{"lineNumber":43,"column":10}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":19,"column":1},"firstPositionDeltaTop":-8},"contributionsState":{"editor.contrib.folding":{"lineCount":155,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":383}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/Ld/Link.ld",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":187,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":173,"column":1},"firstPositionDeltaTop":-6},"contributionsState":{"editor.contrib.folding":{"lineCount":187,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":3307}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/Peripheral/src/ch32v30x_flash.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":1,"column":1},"position":{"lineNumber":1227,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":1179,"column":1},"firstPositionDeltaTop":-11},"contributionsState":{"editor.contrib.folding":{"lineCount":1227,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":22426}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshframing.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":383,"column":44},"position":{"lineNumber":383,"column":44}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":361,"column":1},"firstPositionDeltaTop":-12},"contributionsState":{"editor.contrib.folding":{"lineCount":491,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":6852}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/adc/temperature.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":215,"column":5},"position":{"lineNumber":215,"column":15}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":194,"column":1},"firstPositionDeltaTop":-9},"contributionsState":{"editor.contrib.folding":{"lineCount":250,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":3676}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/meshcore.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":38,"column":15},"position":{"lineNumber":38,"column":17}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":48,"column":1},"firstPositionDeltaTop":-10},"contributionsState":{"editor.contrib.folding":{"lineCount":82,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":903}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packetstructs.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":157,"column":22},"position":{"lineNumber":157,"column":22}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":136,"column":1},"firstPositionDeltaTop":-9},"contributionsState":{"editor.contrib.folding":{"lineCount":248,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":2574}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/sx1262.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":90,"column":30},"position":{"lineNumber":90,"column":30}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":77,"column":1},"firstPositionDeltaTop":-18},"contributionsState":{"editor.contrib.folding":{"lineCount":980,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":1495}}}}],["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":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.c",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":26,"column":82},"position":{"lineNumber":26,"column":1}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":3,"column":1},"firstPositionDeltaTop":-18},"contributionsState":{"editor.contrib.folding":{"lineCount":39,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":56}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/sx1262.h",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":374,"column":33},"position":{"lineNumber":374,"column":33}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":355,"column":1},"firstPositionDeltaTop":-2},"contributionsState":{"editor.contrib.folding":{"lineCount":453,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":6728}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/util/hexdump.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":9,"column":6},"position":{"lineNumber":9,"column":21}}],"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/lib/config.h",{"1":{"cursorState":[{"inSelectionMode":true,"selectionStart":{"lineNumber":50,"column":13},"position":{"lineNumber":50,"column":26}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":21,"column":1},"firstPositionDeltaTop":-9},"contributionsState":{"editor.contrib.folding":{"lineCount":79,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":389}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/lib/config.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":244,"column":30},"position":{"lineNumber":244,"column":30}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":224,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":274,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":4237}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/main.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":150,"column":27},"position":{"lineNumber":150,"column":27}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":128,"column":1},"firstPositionDeltaTop":0},"contributionsState":{"editor.contrib.folding":{"lineCount":265,"foldedImports":false},"editor.contrib.wordHighlighter":true,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":2413}}}}],["file:///home/bruno/Documents/Programming/projects/femtomesh_sw/User/meshcore/packets/encrypted.c",{"1":{"cursorState":[{"inSelectionMode":false,"selectionStart":{"lineNumber":563,"column":53},"position":{"lineNumber":563,"column":53}}],"viewState":{"scrollLeft":0,"firstPosition":{"lineNumber":551,"column":1},"firstPositionDeltaTop":-18},"contributionsState":{"editor.contrib.folding":{"lineCount":789,"provider":"syntax","foldedImports":false},"editor.contrib.wordHighlighter":false,"editor.contrib.findController":{"widgetViewZoneVisible":false,"scrollTop":10468}}}}]]},"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/lib/adc/temperature.c b/User/lib/adc/temperature.c index cc0d4ce..bfd85d3 100644 --- a/User/lib/adc/temperature.c +++ b/User/lib/adc/temperature.c @@ -217,7 +217,7 @@ s32 getVoltage(void) u16 ADC_val; s32 val_mv; - ADC_val = Get_ADC_Average( ADC_Channel_0, 10 ); + ADC_val = Get_ADC_Average( ADC_Channel_1, 10 ); ADC_val = Get_ConversionVal(ADC_val); diff --git a/User/lib/base64.c b/User/lib/base64.c index eff14f0..a9a97ef 100644 --- a/User/lib/base64.c +++ b/User/lib/base64.c @@ -3,16 +3,17 @@ static const char b64_enc_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -void base64_encode(const uint8_t *in, size_t ilen, char *out) -{ +void base64_encode (const uint8_t *in, size_t ilen, char *out) { size_t out_len = 0; for (size_t i = 0; i < ilen; i += 3) { uint32_t triple = 0; int remain = ilen - i; triple |= in[i] << 16; - if (remain > 1) triple |= in[i + 1] << 8; - if (remain > 2) triple |= in[i + 2]; + if (remain > 1) + triple |= in[i + 1] << 8; + if (remain > 2) + triple |= in[i + 2]; out[out_len++] = b64_enc_table[(triple >> 18) & 0x3F]; out[out_len++] = b64_enc_table[(triple >> 12) & 0x3F]; diff --git a/User/lib/base64.h b/User/lib/base64.h index 1b0fbe6..70f79e6 100644 --- a/User/lib/base64.h +++ b/User/lib/base64.h @@ -3,6 +3,6 @@ #include #include -void base64_encode(const uint8_t *in, size_t ilen, char *out); +void base64_encode (const uint8_t *in, size_t ilen, char *out); #endif \ No newline at end of file diff --git a/User/lib/config.c b/User/lib/config.c index 6503135..e299bba 100644 --- a/User/lib/config.c +++ b/User/lib/config.c @@ -1,17 +1,30 @@ #include "config.h" #include "ch32v30x_flash.h" +#include "ch32v30x_rng.h" +#include "lib/cifra/sha2.h" +#include "lib/ed25519/ed_25519.h" +#include "sx1262.h" #include "util/hexdump.h" #include "util/log.h" +#include "FreeRTOS.h" +#include "task.h" PersistentData_t persistent; + +LoRaSettings currentLoRaSettings; + #define TAG "Config" -NodeEntry * getNextNode() { +NodeEntry *getNextNode() { uint32_t oldest_timestamp = UINT32_MAX; NodeEntry *selectedNode = &(persistent.contacts[0]); for (int i = 0; i < CONTACT_COUNT; i++) { NodeEntry *curNode = &(persistent.contacts[i]); + if (curNode->flags & NODE_ENTRY_FAV_FLAG) { + continue; + } if (curNode->last_seen_lt == 0) { + selectedNode = curNode; break; } if (curNode->last_seen_lt < oldest_timestamp) { @@ -22,7 +35,7 @@ NodeEntry * getNextNode() { return selectedNode; } -NodeEntry * getNode(uint8_t hash) { +NodeEntry *getNode (uint8_t hash) { NodeEntry *selectedNode = NULL; for (int i = 0; i < CONTACT_COUNT; i++) { NodeEntry *curNode = &(persistent.contacts[i]); @@ -34,34 +47,111 @@ NodeEntry * getNode(uint8_t hash) { return selectedNode; } +NodeEntry *getNodePrefix (const uint8_t *hash) { + NodeEntry *selectedNode = NULL; + for (int i = 0; i < CONTACT_COUNT; i++) { + NodeEntry *curNode = &(persistent.contacts[i]); + if (memcmp (curNode->pubKey, hash, 4)) { + selectedNode = curNode; + break; + } + } + return selectedNode; +} + +Channel *getChannel (uint8_t hash, uint8_t ignoreCount) { + Channel *selectedChannel = NULL; + Channel *finalChannel = NULL; + uint8_t matchCount = 0; + for (int i = 0; i < ChannelCount; i++) { + Channel *curChannel = &(persistent.channels[i]); + if (curChannel->hash == hash) { + selectedChannel = curChannel; + if (++matchCount > ignoreCount) { + finalChannel = selectedChannel; + break; + } + } + } + return finalChannel; +} + +void addChannel (char *name, const uint8_t *key) { + + uint32_t oldest_timestamp = UINT32_MAX; + Channel *selectedChannel = &(persistent.channels[0]); + for (int i = 0; i < ChannelCount; i++) { + Channel *curChan = &(persistent.channels[i]); + + if (curChan->timestamp == 0) { + selectedChannel = curChan; + MESH_LOGD (TAG, "Deciding on channel index %d because of timestamp 0, name is %s", i, name); + break; + } + if (strlen (curChan->name) == 0) { + selectedChannel = curChan; + MESH_LOGD (TAG, "Deciding on channel index %d because of name len 0, name is %s", i, name); + break; + } + + if (curChan->timestamp < oldest_timestamp) { + oldest_timestamp = curChan->timestamp; + selectedChannel = curChan; + } + } + + + memset (selectedChannel->name, 0, sizeof (selectedChannel->name)); + strncpy (selectedChannel->name, name, sizeof (selectedChannel->name)); + memcpy (selectedChannel->key, key, sizeof (selectedChannel->key)); + // Buffer for the digest + uint8_t hash[CF_SHA256_HASHSZ]; + + // Context + cf_sha256_context ctx; + + // 1. Initialize + cf_sha256_init (&ctx); + + // 2. Feed in your data + cf_sha256_update (&ctx, selectedChannel->key, sizeof (selectedChannel->key)); + + // 3. Compute digest + cf_sha256_digest (&ctx, hash); + selectedChannel->hash = hash[0]; + selectedChannel->timestamp = RTC_GetCounter(); +} + void printNodeDB() { - printf("Node database:\n"); + printf ("Node database:\n"); for (int i = 0; i < CONTACT_COUNT; i++) { const NodeEntry *node = &(persistent.contacts[i]); - if (node->last_seen_lt == 0) continue; // skip inactive nodes + if (node->last_seen_lt == 0) + continue; // skip inactive nodes - printf("Node %d:\n", i); - printf(" Name: %s\n", node->name); - hexdump("Pubkey", node->pubKey, sizeof(node->pubKey)); - hexdump("Secret", node->secret, sizeof(node->secret)); - printf("\n"); + printf ("Node %d:\n", i); + printf (" Name: %s\n", node->name); + hexdump ("Pubkey", node->pubKey, sizeof (node->pubKey)); + hexdump ("Secret", node->secret, sizeof (node->secret)); + printf ("\n"); - printf(" GPS: lat=%d, lon=%d\n", node->gps_latitude, node->gps_longitude); - printf(" Path: ... (not expanded, add if needed)\n"); - printf(" Flags: 0x%02X\n", node->flags); - printf(" Type: 0x%02X\n", node->type); - printf(" Authenticated: %s\n", node->authenticated ? "Yes" : "No"); - printf(" Last Seen (remote ts): %d\n", node->last_seen_rt); - printf(" Last Seen (local ts): %d\n", node->last_seen_lt); - printf(" Sync timestamp: %d\n", node->sync_timestamp); - printf("--------------------------------------\n"); + printf (" GPS: lat=%d, lon=%d\n", node->gps_latitude, node->gps_longitude); + printf (" Path: ... (not expanded, add if needed)\n"); + printf (" Flags: 0x%02X\n", node->flags); + printf (" Type: 0x%02X\n", node->type); + printf (" Authenticated: %s\n", node->authenticated ? "Yes" : "No"); + printf (" Last Seen (remote ts): %d\n", node->last_seen_rt); + printf (" Last Seen (local ts): %d\n", node->last_seen_lt); + printf (" Sync timestamp: %d\n", node->sync_timestamp); + printf ("--------------------------------------\n"); } } void loadConfig() { memcpy (&persistent, FLASH_USER_PAGE_ADDR, sizeof (persistent)); + memcpy(¤tLoRaSettings, &(persistent.loraSettings), sizeof(currentLoRaSettings)); uint32_t crcSum = *((uint32_t *)(((uint8_t *)&persistent) + (sizeof (persistent) - 2))); - memset ((((uint8_t *)&persistent) + (sizeof (persistent) - sizeof(crcSum))), 0, 4); + memset ((((uint8_t *)&persistent) + (sizeof (persistent) - sizeof (crcSum))), 0, 4); CRC_ResetDR(); uint32_t currentSum = CRC_CalcBlockCRC ((uint32_t *)&persistent, sizeof (persistent) - 2); @@ -73,9 +163,112 @@ void loadConfig() { void saveConfig() { CRC_ResetDR(); uint32_t currentSum = CRC_CalcBlockCRC ((uint32_t *)&persistent, sizeof (persistent) - 2); - memcpy ((((uint8_t *)&persistent) + (sizeof (persistent) - sizeof(currentSum))), (uint8_t *)currentSum, 4); + memcpy ((((uint8_t *)&persistent) + (sizeof (persistent) - sizeof (currentSum))), (uint8_t *)currentSum, 4); FLASH_Unlock(); FLASH_ErasePage_Fast (1919); FLASH_ProgramPage_Fast (1919, (uint32_t *)&persistent); FLASH_Lock(); +} + +void genSeed (uint8_t *seedOut) { + RCC_AHBPeriphClockCmd (RCC_AHBPeriph_RNG, ENABLE); + RNG_Cmd (ENABLE); + uint32_t random; + for (uint8_t i = 0; i < 8; i++) { + while (RNG_GetFlagStatus (RNG_FLAG_DRDY) == RESET) { + vTaskDelay (10); + } + random = RNG_GetRandomNumber(); + + memcpy (&(seedOut[i * 4]), &random, sizeof (random)); + } + RCC_AHBPeriphClockCmd (RCC_AHBPeriph_RNG, DISABLE); + RNG_Cmd (DISABLE); +} + +const uint8_t publicChannelPSK[16] = {0x8b, 0x33, 0x87, 0xe9, 0xc5, 0xcd, 0xea, 0x6a, 0xc9, 0xe5, 0xed, 0xba, 0xa1, 0x15, 0xcd, 0x72}; +const uint8_t BRNTestChannelPSK[16] = {0x44, 0x81, 0xda, 0x0e, 0x4e, 0x03, 0xc4, 0x9e, 0x84, 0x77, 0x25, 0xd8, 0x3a, 0x93, 0xbf, 0x80}; + +const char *getStringRole (uint8_t role) { + switch (role) { + case NODE_TYPE_CHAT_NODE: + return "Chat node"; + + case NODE_TYPE_REPEATER: + return "Repeater"; + + case NODE_TYPE_ROOM_SERVER: + return "Room server"; + + case NODE_TYPE_SENSOR: + return "Sensor"; + + default: + return "Unknown"; + } +} + +void populateDefaults() { + + uint8_t seed[32]; + // memcpy(seed, "vFt0FRugSOeqnkshImMCVfgHM5vBxz4", 32); //chat node identity + memcpy (seed, "vFt0FRugSOeqnkshImMCVfgHM5vBxz3", 32); // repeater identity + // genSeed(seed); //random identity + + ed25519_create_keypair (persistent.pubkey, persistent.privkey, seed); + + + // persistent.nodeType = NODE_TYPE_CHAT_NODE; + persistent.nodeType = NODE_TYPE_REPEATER; + memset (persistent.password, 0, sizeof (persistent.password)); + strcpy (persistent.password, "hesielko"); + strcpy (persistent.nodeName, "BRN RiscVpeater"); + + persistent.adcMultiplier = 0; + + persistent.loraSettings.txPowerInDbm = 20; + persistent.loraSettings.frequencyInHz = 869554000; + persistent.loraSettings.spreadingFactor = 8; + persistent.loraSettings.bandwidth = SX126X_LORA_BW_62_5; + persistent.loraSettings.codingRate = SX126X_LORA_CR_4_8; + persistent.loraSettings.preambleLength = 16; + persistent.loraSettings.tcxoVoltage = 2.2; // ebyte + // persistent.tcxoVoltage = 1.8; // heltec + + memcpy(¤tLoRaSettings, &(persistent.loraSettings), sizeof(currentLoRaSettings)); + + addChannel ("Public", publicChannelPSK); + addChannel ("BRNTest", BRNTestChannelPSK); + + persistent.doRepeat = 1; + persistent.allowReadOnly = 1; + + + persistent.latitude = 48190900; + persistent.longitude = 17030300; + persistent.altitude = 23400; +} + +void LoraApply() { + + MESH_LOGW (TAG, "LoraInit"); + LoRaInit(); + + + char useRegulatorLDO = 0; + + LoRaDebugPrint (0); + uint16_t loraBeginStat = LoRaBegin (currentLoRaSettings.frequencyInHz, currentLoRaSettings.txPowerInDbm, currentLoRaSettings.tcxoVoltage, useRegulatorLDO); + if (loraBeginStat != 0) { + MESH_LOGE (TAG, "Does not recognize the module"); + while (1) { + vTaskDelay (pdMS_TO_TICKS (1000)); + MESH_LOGE (TAG, "CRITICAL: LoRa not found, halted"); + } + } + + char crcOn = 1; + char invertIrq = 0; + + LoRaConfig (currentLoRaSettings.spreadingFactor, currentLoRaSettings.bandwidth, currentLoRaSettings.codingRate, currentLoRaSettings.preambleLength, 0, crcOn, invertIrq); } \ No newline at end of file diff --git a/User/lib/config.h b/User/lib/config.h index cce2714..4782a1d 100644 --- a/User/lib/config.h +++ b/User/lib/config.h @@ -6,18 +6,14 @@ #define FLASH_USER_PAGE_ADDR ((const void *)(0x08077F00)) -#define AESKeyCount 8 +#define ChannelCount 8 #define CONTACT_COUNT 100 -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; - +#define VERSION "v0.0.1 - BRN Systems RISC-V" + +#define BOARD "WCH CH32V307" + +typedef struct LoRaSettings { int8_t txPowerInDbm; uint32_t frequencyInHz; uint8_t spreadingFactor; @@ -25,11 +21,35 @@ typedef struct { uint8_t codingRate; uint16_t preambleLength; float tcxoVoltage; +} LoRaSettings; - uint8_t aesKeys[AESKeyCount][17]; - uint8_t password[16]; +extern LoRaSettings currentLoRaSettings; + +typedef struct { + uint32_t magic; // e.g. 0xDEADBEEF + + uint8_t privkey[32]; // Ed25519 private + uint8_t pubkey[32]; // Ed25519 public + + uint8_t nodeType; char nodeName[32]; + + int32_t latitude; + int32_t longitude; + int32_t altitude; + + LoRaSettings loraSettings; + + Channel channels[ChannelCount]; NodeEntry contacts[CONTACT_COUNT]; + + uint8_t password[16]; + uint8_t guestPassword[16]; + + uint8_t doRepeat; + uint8_t allowReadOnly; + float adcMultiplier; + float airtimeFactor; uint32_t crc32; // integrity check } PersistentData_t; @@ -40,7 +60,20 @@ void loadConfig(); void printNodeDB(); -NodeEntry * getNextNode(); +NodeEntry *getNextNode(); + +NodeEntry *getNode (uint8_t hash); + +Channel *getChannel (uint8_t hash, uint8_t ignoreCount); + +void addChannel (char *name, const uint8_t *key); + +NodeEntry *getNodePrefix (const uint8_t *hash); + +const char *getStringRole (uint8_t role); + +void populateDefaults(); + +void LoraApply(); -NodeEntry * getNode(uint8_t hash); #endif \ No newline at end of file diff --git a/User/main.c b/User/main.c index d462973..22d2d0b 100644 --- a/User/main.c +++ b/User/main.c @@ -16,6 +16,7 @@ */ #include "FreeRTOS.h" +#include "ch32v30x_rng.h" #include "meshcore/meshframing.h" #include "meshcore/packets/advert.h" #include "meshcore/packets/control.h" @@ -82,49 +83,6 @@ TaskHandle_t Task2Task_Handler; // uint8_t bufIn[260]; void task2_task (void *pvParameters) { - MESH_LOGD (TAG, "Task2 boot0"); - RTC_Init(); - 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"); - 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"); - strcpy (persistent.nodeName, "BRN RiscVpeater"); - - const uint8_t aesKeysDefault[AESKeyCount][17] = { - {0x11, 0x8b, 0x33, 0x87, 0xe9, 0xc5, - 0xcd, 0xea, 0x6a, 0xc9, 0xe5, 0xed, - 0xba, 0xa1, 0x15, 0xcd, 0x72}, - - {0x0a, 0x44, 0x81, 0xda, 0x0e, 0x4e, - 0x03, 0xc4, 0x9e, 0x84, 0x77, 0x25, - 0xd8, 0x3a, 0x93, 0xbf, 0x80} - }; - - memcpy (persistent.aesKeys, aesKeysDefault, sizeof (persistent.aesKeys)); - - // 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) { @@ -156,6 +114,19 @@ void task2_task (void *pvParameters) { printf ("Sending a direct message to the first node\n"); sendEncryptedTextMessage (&(persistent.contacts[0]), &plainTextMessage); } + if (x == 'C') { + for (uint8_t i = 0; i < ChannelCount; i++) { + Channel *channel = &(persistent.channels[i]); + if (strlen (channel->name) == 0) { + continue; + } + if (channel->timestamp == 0) { + continue; + } + printf ("Channel index %d, named %s, timestamp is %d, hash is %d\n", i, channel->name, channel->timestamp, channel->hash); + hexdump ("Pubkey", channel->key, sizeof (channel->key)); + } + } } vTaskDelay (pdMS_TO_TICKS (2000)); } @@ -163,40 +134,27 @@ void task2_task (void *pvParameters) { void task1_task (void *pvParameters) { // loadConfig(); + populateDefaults(); + + LoraApply(); + const int64_t interval_ms = 10; // 10 ms int64_t start_time, end_time, elapsed; - MESH_LOGW (TAG, "LoraInit"); - LoRaInit(); - int8_t txPowerInDbm = 20; - uint32_t frequencyInHz = 869554000; - 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 + ADC_Function_Init(); + RTC_Init(); + startupTime = RTC_GetCounter(); + memset (&stats, 0, sizeof (stats)); - MESH_LOGW (TAG, "Enable TCXO"); - char useRegulatorLDO = 1; - LoRaDebugPrint (0); - MESH_LOGW (TAG, "Starting lora"); - uint16_t loraBeginStat = LoRaBegin (frequencyInHz, txPowerInDbm, tcxoVoltage, useRegulatorLDO); - if (loraBeginStat != 0) { - MESH_LOGE (TAG, "Does not recognize the module"); - while (1) { - vTaskDelay (pdMS_TO_TICKS (1000)); - } - } - - - char crcOn = 1; - char invertIrq = 0; - - LoRaConfig (spreadingFactor, bandwidth, codingRate, preambleLength, 0, crcOn, - invertIrq); + DiscoverRequestPayload discReq; + discReq.prefixOnly = 0; + discReq.since = 0; + discReq.tag = RTC_GetCounter(); + discReq.typeFilter = 0xFF; + sendDiscoverRequest (&discReq); + sendAdvert (1); while (1) { start_time = xTaskGetTickCount(); @@ -211,8 +169,10 @@ void task1_task (void *pvParameters) { // 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); + if (persistent.doRepeat) { + MESH_LOGD (TAG, "Free stack before retransmitFrame: %u bytes", uxTaskGetStackHighWaterMark (NULL) * 4); + retransmitFrame (&frame); + } memset (&frame, 0, sizeof (FrameStruct)); // prepare for the next round } diff --git a/User/meshcore/meshcore.c b/User/meshcore/meshcore.c index 3539ea5..1b28b48 100644 --- a/User/meshcore/meshcore.c +++ b/User/meshcore/meshcore.c @@ -21,12 +21,12 @@ // requires at least a 256 byte data -void processFrame (const FrameStruct *frame) { +void processFrame (FrameStruct *frame) { printFrameHeader (frame); 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 frameType = frame->header & PAYLOAD_TYPE_MASK; unsigned char index = 0; @@ -67,12 +67,15 @@ void processFrame (const FrameStruct *frame) { } else if (frameType == PAYLOAD_TYPE_MULTIPART) { } else if (frameType == PAYLOAD_TYPE_CONTROL) { - decodeControlFrame (frame); + if (frame->path.pathLen == 0) { + decodeControlFrame (frame); + } + frame->header = 0xFF; } else if (frameType == PAYLOAD_TYPE_RAW_CUSTOM) { // not implemented } else { stats.packetsReceivedCount--; } - MESH_LOGD(TAG, "Processed frame"); + MESH_LOGD (TAG, "Processed frame"); } diff --git a/User/meshcore/meshcore.h b/User/meshcore/meshcore.h index 805d31b..011118f 100644 --- a/User/meshcore/meshcore.h +++ b/User/meshcore/meshcore.h @@ -11,6 +11,6 @@ #include #include "stdio.h" -void processFrame (const FrameStruct * frame); +void processFrame (FrameStruct *frame); #endif \ No newline at end of file diff --git a/User/meshcore/meshframing.c b/User/meshcore/meshframing.c index 8f97733..14e0122 100644 --- a/User/meshcore/meshframing.c +++ b/User/meshcore/meshframing.c @@ -381,20 +381,39 @@ void sendFrame (const FrameStruct *frame) { */ 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"); + + /* -------- FLOOD -------- */ + 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) { + + // append self to END of path 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"); + LoRaTransmit (frame); } } - if (frame->header & ROUTE_TYPE_DIRECT || frame->header & ROUTE_TYPE_TRANSPORT_DIRECT) { + /* -------- DIRECT -------- */ + if (frame->header & ROUTE_TYPE_DIRECT || + frame->header & ROUTE_TYPE_TRANSPORT_DIRECT) { + + // are we the next hop? + if (frame->path.pathLen > 0 && + frame->path.path[0] == persistent.pubkey[0]) { + + // remove self from START of path + frame->path.pathLen--; + memmove (frame->path.path, + frame->path.path + 1, + frame->path.pathLen); + + // forward only if there's another hop + if (frame->path.pathLen > 0) { + LoRaTransmit (frame); + } + } } } diff --git a/User/meshcore/meshframing.h b/User/meshcore/meshframing.h index ae050dd..c94341f 100644 --- a/User/meshcore/meshframing.h +++ b/User/meshcore/meshframing.h @@ -12,7 +12,7 @@ #define HMAC_SIZE 2 // meshcore size #define MAX_FLOOD_TTL 64 -int ReadFrame(FrameStruct *frame, int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr); +int ReadFrame (FrameStruct *frame, int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr); void LoRaTransmit (const FrameStruct *frame); @@ -22,10 +22,10 @@ FrameStruct decodeFrame (unsigned char *data, unsigned char dataLen); void sendFrame (const FrameStruct * frame); */ -void printFrameHeader (const FrameStruct * frame) ; +void printFrameHeader (const FrameStruct *frame); -//CALL LAST, PATH GETS MODIFIED -void retransmitFrame (FrameStruct * frame) ; +// CALL LAST, PATH GETS MODIFIED +void retransmitFrame (FrameStruct *frame); // Verify MAC + Decrypt diff --git a/User/meshcore/packets/advert.h b/User/meshcore/packets/advert.h index 383282f..263dd1d 100644 --- a/User/meshcore/packets/advert.h +++ b/User/meshcore/packets/advert.h @@ -5,10 +5,10 @@ void sendAdvert (uint8_t shouldFlood); -void decodeAdvertisement (const FrameStruct * frame); +void decodeAdvertisement (const FrameStruct *frame); -void printAdvertisement (const AdvertisementPayload * advert); +void printAdvertisement (const AdvertisementPayload *advert); -void saveAdvert(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 0d1e517..f35e757 100644 --- a/User/meshcore/packets/anonymous.c +++ b/User/meshcore/packets/anonymous.c @@ -105,10 +105,10 @@ void printAnonRequest (const AnonymousRequestPayload *req, int isRoomServer) { printf (" sync timestamp: %u\n", syncTimestamp); } - + // remaining bytes = password if (index < req->payloadLen) { - uint8_t passwordLen = req->payloadLen - index; + uint8_t passwordLen = req->payloadLen - index; if (passwordLen > 16) passwordLen = 16; passwordLen = strnlen (&(req->payload[index]), passwordLen); @@ -175,8 +175,10 @@ void decodeAnonReq (const FrameStruct *frame) { 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); @@ -206,5 +208,9 @@ void decodeAnonReq (const FrameStruct *frame) { resp.data[index3++] = (randOut >> 24) & 0xFF; resp.data[index3++] = FIRMWARE_VER_LEVEL; resp.dataLen = index3; + if ((frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD || + (frame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) { + sendPathBack (foundNode, &(frame->path)); + } sendEncryptedResponse (foundNode, &resp); } diff --git a/User/meshcore/packets/anonymous.h b/User/meshcore/packets/anonymous.h index c7afb55..b4f95ea 100644 --- a/User/meshcore/packets/anonymous.h +++ b/User/meshcore/packets/anonymous.h @@ -4,7 +4,7 @@ #include "meshcore/packetstructs.h" #include "lib/config.h" -void decodeAnonReq (const FrameStruct * frame); +void decodeAnonReq (const FrameStruct *frame); void sendAnonymousRequest (const NodeEntry *targetNode, const uint8_t *password, uint32_t sync); diff --git a/User/meshcore/packets/control.c b/User/meshcore/packets/control.c index 62c9149..1957ae8 100644 --- a/User/meshcore/packets/control.c +++ b/User/meshcore/packets/control.c @@ -7,6 +7,8 @@ #include "util/hexdump.h" #include "util/log.h" #include +#include "FreeRTOS.h" +#include "task.h" #define TAG "Control" @@ -41,6 +43,7 @@ void sendDiscoverRequest (const DiscoverRequestPayload *discReq) { void sendDiscoverResponse (const DiscoverResponsePayload *discResp) { FrameStruct frame; + frame.header = ROUTE_TYPE_DIRECT | PAYLOAD_TYPE_CONTROL | PAYLOAD_VERSION_0; frame.path.pathLen = 0; uint8_t offset = 0; @@ -89,7 +92,7 @@ void printDiscoverResponse (const DiscoverResponsePayload *p) { printf ("\n"); } -void decodeControlFrame (const FrameStruct * frame) { +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) { @@ -110,7 +113,7 @@ void decodeControlFrame (const FrameStruct * frame) { discReq.since |= frame->payload[index++] << 24; } printDiscoverRequest (&discReq); - if ((discReq.typeFilter >> 2) & persistent.nodeType) { + if ((discReq.typeFilter >> 1) & persistent.nodeType) { DiscoverResponsePayload discResp; discResp.tag = discReq.tag; @@ -119,8 +122,10 @@ void decodeControlFrame (const FrameStruct * frame) { memcpy (discResp.pubkey, persistent.pubkey, discResp.pubkeyLen); discResp.snr = stats.lastSNR; // hopefully the correct one + + MESH_LOGD (TAG, "Replying to a discover request with tag %d", discResp.tag); sendDiscoverResponse (&discResp); - MESH_LOGD(TAG, "Replying to a discover request with tag %d", discResp.tag); + printDiscoverResponse (&discResp); } } else if (type == CONTROL_DATA_FLAG_DISCOVER_RESP) { diff --git a/User/meshcore/packets/control.h b/User/meshcore/packets/control.h index 191cb1b..fdad2df 100644 --- a/User/meshcore/packets/control.h +++ b/User/meshcore/packets/control.h @@ -3,14 +3,14 @@ #include "meshcore/packetstructs.h" -void sendDiscoverRequest(const DiscoverRequestPayload *discReq); +void sendDiscoverRequest (const DiscoverRequestPayload *discReq); -void sendDiscoverResponse(const DiscoverResponsePayload *discResp); +void sendDiscoverResponse (const DiscoverResponsePayload *discResp); -void printDiscoverRequest(const DiscoverRequestPayload *p); +void printDiscoverRequest (const DiscoverRequestPayload *p); -void printDiscoverResponse(const DiscoverResponsePayload *p); +void printDiscoverResponse (const DiscoverResponsePayload *p); -void decodeControlFrame(const FrameStruct * frame); +void decodeControlFrame (const FrameStruct *frame); #endif \ No newline at end of file diff --git a/User/meshcore/packets/custom.h b/User/meshcore/packets/custom.h index 474ecc8..6ef4d48 100644 --- a/User/meshcore/packets/custom.h +++ b/User/meshcore/packets/custom.h @@ -2,5 +2,4 @@ #define CUSTOM_HEADER - #endif \ No newline at end of file diff --git a/User/meshcore/packets/encrypted.c b/User/meshcore/packets/encrypted.c index 7c59ed2..bd5fc48 100644 --- a/User/meshcore/packets/encrypted.c +++ b/User/meshcore/packets/encrypted.c @@ -2,23 +2,27 @@ #include "lib/telemetry/telemetry.h" #include "meshcore/meshframing.h" #include "meshcore/packets/ack.h" +#include "meshcore/packets/advert.h" #include "meshcore/packetstructs.h" #include "meshcore/stats.h" #include "util/hexdump.h" #include "util/log.h" #include +#include #include #include "encrypted.h" #include "FreeRTOS.h" #include "task.h" #include "lib/adc/temperature.h" +#include "lib/rtc/rtc.h" +#include "sx1262.h" #define TICKS_TO_MS(xTicks) (((uint32_t)(xTicks)*1000U) / (uint32_t)configTICK_RATE_HZ) #define TAG "EncryptedMessage" -void sendEncryptedFrame (NodeEntry *targetNode, uint8_t payloadType, const uint8_t *plain, size_t plainLen) { +void sendEncryptedFrame (const NodeEntry *targetNode, uint8_t payloadType, const uint8_t *plain, size_t plainLen) { FrameStruct frame; uint8_t offset = 0; @@ -52,7 +56,7 @@ void sendEncryptedFrame (NodeEntry *targetNode, uint8_t payloadType, const uint8 LoRaTransmit (&frame); } -void sendEncryptedTextMessage (NodeEntry *targetNode, const PlainTextMessagePayload *msg) { +void sendEncryptedTextMessage (const NodeEntry *targetNode, const PlainTextMessagePayload *msg) { if (targetNode == NULL) { MESH_LOGW (TAG, "Node is null"); return; @@ -72,15 +76,16 @@ void sendEncryptedTextMessage (NodeEntry *targetNode, const PlainTextMessagePayl buf[index++] = (msg->textType << 2) | (msg->attempt & 0x03); memcpy (&buf[index], msg->message, msgLen); + index += msgLen; sendEncryptedFrame ( targetNode, PAYLOAD_TYPE_TXT_MSG, buf, - index + msgLen); + index); } -void sendEncryptedResponse (NodeEntry *targetNode, const Response *resp) { +void sendEncryptedResponse (const NodeEntry *targetNode, const Response *resp) { uint8_t buf[256]; uint8_t index = 0; @@ -99,7 +104,7 @@ void sendEncryptedResponse (NodeEntry *targetNode, const Response *resp) { index); } -void sendEncryptedRequest (NodeEntry *targetNode, const Request *req) { +void sendEncryptedRequest (const NodeEntry *targetNode, const Request *req) { uint8_t buf[256]; uint8_t index = 0; @@ -119,7 +124,7 @@ void sendEncryptedRequest (NodeEntry *targetNode, const Request *req) { index); } -void sendEncryptedPathPayload (NodeEntry *targetNode, const ReturnedPathPayload *path) { +void sendEncryptedPathPayload (const NodeEntry *targetNode, const ReturnedPathPayload *path) { uint8_t buf[256]; uint8_t index = 0; @@ -127,9 +132,17 @@ void sendEncryptedPathPayload (NodeEntry *targetNode, const ReturnedPathPayload memcpy (&buf[index], path->path.path, path->path.pathLen); index += path->path.pathLen; - buf[index++] = path->extra.type; - memcpy (&buf[index], path->extra.data, - path->extra.dataLen); + if (path->extra.dataLen > 0) { + buf[index++] = path->extra.type; + memcpy (&buf[index], path->extra.data, path->extra.dataLen); + } else { + buf[index++] = 0xFF; + uint32_t timestamp = RTC_GetCounter(); + buf[index++] = timestamp; + buf[index++] = timestamp >> 8; + buf[index++] = timestamp >> 16; + buf[index++] = timestamp >> 24; + } sendEncryptedFrame ( targetNode, @@ -188,6 +201,8 @@ void printEncryptedPayload (const EncryptedPayloadStruct *enc) { void decodeEncryptedPayload (const FrameStruct *frame) { EncryptedPayloadStruct enc; memset (&enc, 0, sizeof (enc)); + enc.path = &(frame->path); + enc.origFrame = frame; enc.type = frame->header & PAYLOAD_TYPE_MASK; unsigned char index = 0; @@ -206,11 +221,11 @@ void decodeEncryptedPayload (const FrameStruct *frame) { enc.remNode = remNode; - if (remNode == NULL) { MESH_LOGW (TAG, "Node not in DB"); return; } + remNode->last_seen_lt = RTC_GetCounter(); MESH_LOGI (TAG, "Found node with index %d", remNode - persistent.contacts); @@ -228,6 +243,17 @@ void decodeEncryptedPayload (const FrameStruct *frame) { } } +void sendPathBack (const NodeEntry *node, const Path *path) { + ReturnedPathPayload retPath; + retPath.extra.dataLen = 0; // redo to send the resp in path + retPath.extra.type = 0xFF; + + retPath.path.pathLen = path->pathLen; + memcpy (retPath.path.path, path->path, path->pathLen); + + sendEncryptedPathPayload (node, &retPath); +} + void parseEncryptedPayload (const EncryptedPayloadStruct *enc) { // printEncryptedPayload(&enc); @@ -242,7 +268,6 @@ void parseEncryptedPayload (const EncryptedPayloadStruct *enc) { uint8_t index = 0; if (enc->type == PAYLOAD_TYPE_PATH) { - ReturnedPathPayload retPath; retPath.path.pathLen = enc->payload[index++]; if (retPath.path.pathLen > 64) { @@ -255,16 +280,26 @@ void parseEncryptedPayload (const EncryptedPayloadStruct *enc) { retPath.extra.dataLen = enc->payloadLen - index; memcpy (retPath.extra.data, &(enc->payload[index]), retPath.extra.dataLen); + if ((enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD || + (enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) { + sendPathBack (enc->remNode, enc->path); + } + } 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; + enc->remNode->last_seen_rt = req.timestamp; req.requestType = enc->payload[index++]; req.dataLen = enc->payloadLen - index; memcpy (req.data, &(enc->payload[index]), req.dataLen); printRequest (&req); + if ((enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD || + (enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) { + sendPathBack (enc->remNode, enc->path); + } switch (req.requestType) { case REQUEST_GET_STATS: { Response resp; @@ -281,6 +316,7 @@ void parseEncryptedPayload (const EncryptedPayloadStruct *enc) { case REQUEST_GET_TELEMETRY_DATA: { Response resp; resp.tag = req.timestamp; + enc->remNode->last_seen_rt = req.timestamp; uint8_t index2 = 0; resp.data[index2++] = TELEM_CHANNEL_SELF; resp.data[index2++] = LPP_TEMPERATURE; @@ -351,9 +387,403 @@ void parseEncryptedPayload (const EncryptedPayloadStruct *enc) { plaintext.timestamp |= enc->payload[index++] << 8; plaintext.timestamp |= enc->payload[index++] << 16; plaintext.timestamp |= enc->payload[index++] << 24; + enc->remNode->last_seen_rt = plaintext.timestamp; plaintext.attempt = enc->payload[index] & 0x03; plaintext.textType = enc->payload[index++] >> 2; memcpy (plaintext.message, &(enc->payload[index]), enc->payloadLen - index); - printPlainTextMessage (&plaintext); + if ((enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_FLOOD || + (enc->origFrame->header & ROUTE_TYPE_MASK) == ROUTE_TYPE_TRANSPORT_FLOOD) { + sendPathBack (enc->remNode, enc->path); + } + switch (plaintext.textType) { + case TXT_TYPE_PLAIN: + printf ("Plaintext message from %s, attempt %d, timestamp %d: %s", enc->remNode->name, plaintext.attempt, plaintext.timestamp, plaintext.message); + break; + + case TXT_TYPE_CLI_DATA: + if (enc->remNode->authenticated) { + processCommand (plaintext.message, enc->remNode); + } + break; + + case TXT_TYPE_SIGNED_PLAIN: { + uint8_t senderPubKeyPrefix[4]; + memcpy (senderPubKeyPrefix, plaintext.message, sizeof (senderPubKeyPrefix)); + NodeEntry *senderNode = getNodePrefix (senderPubKeyPrefix); + printf ("Plaintext message from server %s, sender is %s, attempt %d, timestamp %d: %s", enc->remNode->name, senderNode->name, plaintext.attempt, plaintext.timestamp, &(plaintext.message[4])); + break; + } + + default: + MESH_LOGW (TAG, "Unknown text type: %d", plaintext.textType); + break; + } } -} \ No newline at end of file +} + +#define STR_EQ_LIT(s, lit) (memcmp ((s), (lit), sizeof (lit) - 1) == 0) + +void processCommand (char *cmd, NodeEntry *remNode) { + PlainTextMessagePayload replyPayload; + replyPayload.timestamp = RTC_GetCounter(); + replyPayload.attempt = 0; + replyPayload.textType = TXT_TYPE_CLI_DATA; + + uint8_t *reply = replyPayload.message; + reply[0] = 0; + + while (*cmd == ' ') cmd++; // skip leading spaces + + // Optional CLI prefix (xx|) for companion radio + if (strlen (cmd) > 4 && cmd[2] == '|') { + memcpy (reply, cmd, 3); + reply += 3; + cmd += 3; + } + + /* ---------------- System ---------------- */ + if (STR_EQ_LIT (cmd, "reboot")) { + NVIC_SystemReset(); + } else if (STR_EQ_LIT (cmd, "advert")) { + sendAdvert (1); // 1500ms delay in reference + strcpy ((char *)reply, "OK - Advert sent"); + } else if (STR_EQ_LIT (cmd, "clear stats")) { + memset (&stats, 0, sizeof (stats)); + strcpy ((char *)reply, "(OK - stats reset)"); + } + + else if (STR_EQ_LIT (cmd, "ver")) { + sprintf ((char *)reply, "%s (Build: %s)", VERSION, __DATE__); + } + + else if (STR_EQ_LIT (cmd, "board")) { + sprintf ((char *)reply, "%s", BOARD); + } + + /* ---------------- Clock ---------------- */ + else if (STR_EQ_LIT (cmd, "clock")) { + RTC_Get(); + sprintf ((char *)reply, "%02d:%02d:%02d - %d/%d/%d UTC", + calendar.hour, calendar.min, calendar.sec, + calendar.w_date, calendar.w_month, calendar.w_year); + } else if (STR_EQ_LIT (cmd, "time ")) { + uint32_t secs = atoi (&cmd[5]); + uint32_t curr = RTC_GetCounter(); + if (secs > curr) { + RTC_SetCounter (secs); + RTC_Get(); + sprintf ((char *)reply, "OK - clock set: %02d:%02d:%02d - %d/%d/%d UTC", + calendar.hour, calendar.min, calendar.sec, + calendar.w_date, calendar.w_month, calendar.w_year); + } else { + strcpy ((char *)reply, "(ERR: clock cannot go backwards)"); + } + } else if (STR_EQ_LIT (cmd, "clock sync")) { + uint32_t curr = RTC_GetCounter(); + uint32_t sender = replyPayload.timestamp; + if (sender > curr) { + RTC_SetCounter (sender + 1); + RTC_Get(); + sprintf ((char *)reply, "OK - clock set: %02d:%02d:%02d - %d/%d/%d UTC", + calendar.hour, calendar.min, calendar.sec, + calendar.w_date, calendar.w_month, calendar.w_year); + } else { + strcpy ((char *)reply, "ERR: clock cannot go backwards"); + } + } + + /* ---------------- Neighbors ---------------- */ + else if (STR_EQ_LIT (cmd, "neighbors")) { + Callbacks_FormatNeighborsReply ((char *)reply); + } else if (STR_EQ_LIT (cmd, "neighbor.remove ")) { + const char *hex = cmd + 16; + uint8_t pubkey[PUB_KEY_SIZE]; + int len = strlen (hex) / 2; + if (mesh_fromHex (pubkey, len, hex)) { + Callbacks_RemoveNeighbor (pubkey, len); + strcpy ((char *)reply, "OK"); + } else { + strcpy ((char *)reply, "ERR: bad pubkey"); + } + } + + /* ---------------- Radio / Temp ---------------- */ + else if (STR_EQ_LIT (cmd, "tempradio ")) { + char tmp[64]; + strcpy (tmp, &cmd[10]); + + const char *parts[5]; + int num = mesh_ParseTextParts (tmp, parts, 5); // assume helper + float freq = num > 0 ? strtof (parts[0], NULL) : 0.0f; + float bw = num > 1 ? strtof (parts[1], NULL) : 0.0f; + uint8_t sf = num > 2 ? atoi (parts[2]) : 0; + uint8_t cr = num > 3 ? atoi (parts[3]) : 0; + int timeout_mins = num > 4 ? atoi (parts[4]) : 0; + if (freq >= 300.0f && freq <= 2500.0f && bw >= 7.0f && bw <= 500.0f && + sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && timeout_mins > 0) { + Callbacks_ApplyTempRadioParams (freq, bw, sf, cr, timeout_mins); + + LoraApply(); + sprintf ((char *)reply, "OK - temp params for %d mins", timeout_mins); + } else { + strcpy ((char *)reply, "Error, invalid params"); + } + } + + /* ---------------- Password ---------------- */ + else if (STR_EQ_LIT (cmd, "password ")) { + strncpy (persistent.password, &cmd[9], sizeof (persistent.password)); + // savePrefs(); TODO add this + sprintf ((char *)reply, "password now: %s", persistent.password); + } + + /* ---------------- GET / SET Config ---------------- */ + else if (STR_EQ_LIT (cmd, "get ")) { + const char *config = &cmd[4]; + + if (memcmp (config, "af", 2) == 0) { + sprintf (reply, "> %f", persistent.airtimeFactor); + } else if (memcmp (config, "int.thresh", 10) == 0) { + sprintf (reply, "> %d", (uint32_t)_prefs->interference_threshold); + } else if (memcmp (config, "agc.reset.interval", 18) == 0) { + sprintf (reply, "> %d", ((uint32_t)_prefs->agc_reset_interval) * 4); + } else if (memcmp (config, "multi.acks", 10) == 0) { + sprintf (reply, "> %d", (uint32_t)_prefs->multi_acks); + } else if (memcmp (config, "allow.read.only", 15) == 0) { + sprintf (reply, "> %s", _prefs->allow_read_only ? "on" : "off"); + } else if (memcmp (config, "flood.advert.interval", 21) == 0) { + sprintf (reply, "> %d", (uint32_t)_prefs->flood_advert_interval); + } else if (memcmp (config, "advert.interval", 15) == 0) { + sprintf (reply, "> %d", ((uint32_t)_prefs->advert_interval) * 2); + } else if (memcmp (config, "guest.password", 14) == 0) { + sprintf (reply, "> %s", persistent.guestPassword); + } else if (memcmp (config, "name", 4) == 0) { + sprintf (reply, "> %s", persistent.nodeName); + } else if (memcmp (config, "repeat", 6) == 0) { + sprintf (reply, "> %s", persistent.doRepeat ? "on" : "off"); + } else if (memcmp (config, "lat", 3) == 0) { + sprintf (reply, "> %d", persistent.latitude); + } else if (memcmp (config, "lon", 3) == 0) { + sprintf (reply, "> %d", persistent.longitude); + } else if (memcmp (config, "radio", 5) == 0) { + char freq[16], bw[16]; + snprintf(freq, sizeof(freq), "%lf", persistent.frequencyInHz / 1000000.0); + snprintf(bw, sizeof(bw), "%lf", loraBwToFloat(persistent.bandwidth)); + sprintf (reply, "> %s,%s,%d,%d", freq, bw, persistent.spreadingFactor, persistent.codingRate + 4); + } else if (memcmp (config, "rxdelay", 7) == 0) { + sprintf (reply, "> %s", StrHelper::ftoa (_prefs->rx_delay_base)); + } else if (memcmp (config, "txdelay", 7) == 0) { + sprintf (reply, "> %s", StrHelper::ftoa (_prefs->tx_delay_factor)); + } else if (memcmp (config, "flood.max", 9) == 0) { + sprintf (reply, "> %d", (uint32_t)_prefs->flood_max); + } else if (memcmp (config, "direct.txdelay", 14) == 0) { + sprintf (reply, "> %s", StrHelper::ftoa (_prefs->direct_tx_delay_factor)); + } else if (memcmp (config, "tx", 2) == 0 && (config[2] == 0 || config[2] == ' ')) { + sprintf (reply, "> %d", (uint32_t)_prefs->tx_power_dbm); + } else if (memcmp (config, "freq", 4) == 0) { + sprintf (reply, "> %s", StrHelper::ftoa (_prefs->freq)); + } else if (memcmp (config, "public.key", 10) == 0) { + strcpy (reply, "> "); + hexdump_compact(persistent.pubkey, sizeof(persistent.pubkey), &(reply[2]), 70); + } else if (memcmp (config, "role", 4) == 0) { + sprintf (reply, "> %s", getStringRole(persistent.nodeType)); + } else if (memcmp (config, "adc.multiplier", 14) == 0) { + sprintf (reply, "> %.3f", persistent.adcMultiplier); + } else { + sprintf (reply, "??: %s", config); + } + + } else if (STR_EQ_LIT (cmd, "set ")) { + const char *config = &cmd[4]; + + if (memcmp (config, "af ", 3) == 0) { + persistent.airtimeFactor = atof (&config[3]); + // savePrefs(); + strcpy (reply, "OK"); + } else if (memcmp (config, "int.thresh ", 11) == 0) { + _prefs->interference_threshold = atoi (&config[11]); + // savePrefs(); + strcpy (reply, "OK"); + } else if (memcmp (config, "agc.reset.interval ", 19) == 0) { + _prefs->agc_reset_interval = atoi (&config[19]) / 4; + // savePrefs(); + sprintf (reply, "OK - interval rounded to %d", ((uint32_t)_prefs->agc_reset_interval) * 4); + } else if (memcmp (config, "multi.acks ", 11) == 0) { + _prefs->multi_acks = atoi (&config[11]); + // savePrefs(); + strcpy (reply, "OK"); + } else if (memcmp (config, "allow.read.only ", 16) == 0) { + if (memcmp (&config[16], "on", 2) == 0) { + persistent.allowReadOnly = 1; + strcpy (reply, "OK"); + } else if (memcmp (&config[16], "off", 3) == 0) { + persistent.allowReadOnly = 0; + strcpy (reply, "OK"); + } + //savePrefs(); + + } else if (memcmp (config, "flood.advert.interval ", 22) == 0) { + int hours = _atoi (&config[22]); + if ((hours > 0 && hours < 3) || (hours > 48)) { + strcpy (reply, "Error: interval range is 3-48 hours"); + } else { + _prefs->flood_advert_interval = (uint8_t)hours; + _callbacks->updateFloodAdvertTimer(); + savePrefs(); + strcpy (reply, "OK"); + } + } else if (memcmp (config, "advert.interval ", 16) == 0) { + int mins = _atoi (&config[16]); + if ((mins > 0 && mins < MIN_LOCAL_ADVERT_INTERVAL) || (mins > 240)) { + sprintf (reply, "Error: interval range is %d-240 minutes", MIN_LOCAL_ADVERT_INTERVAL); + } else { + _prefs->advert_interval = (uint8_t)(mins / 2); + _callbacks->updateAdvertTimer(); + savePrefs(); + strcpy (reply, "OK"); + } + } else if (memcmp (config, "guest.password ", 15) == 0) { + strncpy (persistent.guestPassword, &config[15], sizeof (persistent.guestPassword)); + // savePrefs(); + strcpy (reply, "OK"); + } else if (memcmp (config, "name ", 5) == 0) { + strncpy (persistent.nodeName, &config[5], sizeof (persistent.nodeName)); + // savePrefs(); + strcpy (reply, "OK"); + } else if (memcmp (config, "repeat ", 7) == 0) { + if (memcmp (&config[7], "off", 3) == 0) { + persistent.doRepeat = 0; + } else if (memcmp (&config[7], "on", 2) == 0) { + persistent.doRepeat = 1; + } + // savePrefs(); + strcpy (reply, persistent.doRepeat ? "OK - repeat is now ON" : "OK - repeat is now OFF"); + } else if (memcmp (config, "radio ", 6) == 0) { + strcpy (tmp, &config[6]); + const char *parts[4]; + int num = mesh::Utils::parseTextParts (tmp, parts, 4); + float freq = num > 0 ? strtof (parts[0], nullptr) : 0.0f; + float bw = num > 1 ? strtof (parts[1], nullptr) : 0.0f; + uint8_t sf = num > 2 ? atoi (parts[2]) : 0; + uint8_t cr = num > 3 ? atoi (parts[3]) : 0; + if (freq >= 300.0f && freq <= 2500.0f && sf >= 5 && sf <= 12 && cr >= 5 && cr <= 8 && bw >= 7.0f && bw <= 500.0f) { + _prefs->sf = sf; + _prefs->cr = cr; + _prefs->freq = freq; + _prefs->bw = bw; + _callbacks->savePrefs(); + strcpy (reply, "OK - reboot to apply"); + } else { + strcpy (reply, "Error, invalid radio params"); + } + } else if (memcmp (config, "lat ", 4) == 0) { + double lat = atof (&config[4]); + lat *= 1000000; + persistent.latitude = lat; + // savePrefs(); + strcpy (reply, "OK"); + } else if (memcmp (config, "lon ", 4) == 0) { + double lon = atof (&config[4]); + lon *= 1000000; + persistent.longitude = lon; + // savePrefs(); + strcpy (reply, "OK"); + } else if (memcmp (config, "rxdelay ", 8) == 0) { + float db = atof (&config[8]); + if (db >= 0) { + _prefs->rx_delay_base = db; + savePrefs(); + strcpy (reply, "OK"); + } else { + strcpy (reply, "Error, cannot be negative"); + } + } else if (memcmp (config, "txdelay ", 8) == 0) { + float f = atof (&config[8]); + if (f >= 0) { + _prefs->tx_delay_factor = f; + savePrefs(); + strcpy (reply, "OK"); + } else { + strcpy (reply, "Error, cannot be negative"); + } + } else if (memcmp (config, "flood.max ", 10) == 0) { + uint8_t m = atoi (&config[10]); + if (m <= 64) { + _prefs->flood_max = m; + savePrefs(); + strcpy (reply, "OK"); + } else { + strcpy (reply, "Error, max 64"); + } + } else if (memcmp (config, "direct.txdelay ", 15) == 0) { + float f = atof (&config[15]); + if (f >= 0) { + _prefs->direct_tx_delay_factor = f; + savePrefs(); + strcpy (reply, "OK"); + } else { + strcpy (reply, "Error, cannot be negative"); + } + } else if (memcmp (config, "tx ", 3) == 0) { + _prefs->tx_power_dbm = atoi (&config[3]); + savePrefs(); + _callbacks->setTxPower (_prefs->tx_power_dbm); + strcpy (reply, "OK"); + } else if (memcmp (config, "freq ", 5) == 0) { + double freq = atof (&config[5]); + uint32_t newFreq = mhzToHzLimited (persistent.frequencyInHz); + if (newFreq != 0) { + persistent.frequencyInHz = newFreq; + } + // savePrefs(); + strcpy (reply, "OK - reboot to apply"); + } else if (memcmp (config, "adc.multiplier ", 15) == 0) { + persistent.adcMultiplier = atof (&config[15]); + if (persistent.adcMultiplier == 0.0f) { + strcpy (reply, "OK - using default board multiplier"); + } else { + sprintf (reply, "OK - multiplier set to %.3f", persistent.adcMultiplier); + } + // savePrefs(); + } else { + sprintf (reply, "unknown config: %s", config); + } + } + + + /* ---------------- Stats ---------------- */ + else if (STR_EQ_LIT (cmd, "stats-packets")) { + sprintf (reply, + "{\"recv\":%u,\"sent\":%u,\"flood_tx\":%u,\"direct_tx\":%u,\"flood_rx\":%u,\"direct_rx\":%u}", + stats.packetsReceivedCount, + stats.packetsSentCount, + stats.sentFloodCount, + stats.sentDirectCount, + stats.receivedFloodCount, + stats.receivedDirectCount); + } else if (STR_EQ_LIT (cmd, "stats-radio")) { + sprintf (reply, + "{\"noise_floor\":%d,\"last_rssi\":%d,\"last_snr\":%.2f,\"tx_air_secs\":%u,\"rx_air_secs\":%u}", + stats.noiseFloor, + stats.lastRSSI, + stats.lastSNR / 4.0, + stats.totalAirTimeSeconds, + stats.total_rx_air_time_secs); + } else if (STR_EQ_LIT (cmd, "stats-core")) { + stats.totalUpTimeSeconds = RTC_GetCounter() - startupTime; + stats.totalAirTimeSeconds = TICKS_TO_MS (tickAirtime / 1000); + sprintf (reply, + "{\"battery_mv\":%u,\"uptime_secs\":%u,\"errors\":%u,\"queue_len\":%u}", + getVoltage(), + stats.totalUpTimeSeconds, + stats.err_events, + stats.txQueueLength); + } + + /* ---------------- Unknown ---------------- */ + else { + strcpy ((char *)reply, "Unknown command"); + } + + sendEncryptedTextMessage (remNode, &replyPayload); +} diff --git a/User/meshcore/packets/encrypted.h b/User/meshcore/packets/encrypted.h index 1954450..e4d37e1 100644 --- a/User/meshcore/packets/encrypted.h +++ b/User/meshcore/packets/encrypted.h @@ -8,18 +8,22 @@ #include -void sendEncryptedFrame (NodeEntry *targetNode, uint8_t payloadType, const uint8_t *plain, size_t plainLen); +void sendEncryptedFrame (const NodeEntry *targetNode, uint8_t payloadType, const uint8_t *plain, size_t plainLen); -void sendEncryptedTextMessage (NodeEntry *targetNode, const PlainTextMessagePayload *msg); +void sendEncryptedTextMessage (const NodeEntry *targetNode, const PlainTextMessagePayload *msg); -void sendEncryptedResponse (NodeEntry *targetNode, const Response *resp); +void sendEncryptedResponse (const NodeEntry *targetNode, const Response *resp); -void sendEncryptedRequest (NodeEntry *targetNode, const Request *req); +void sendEncryptedRequest (const NodeEntry *targetNode, const Request *req); -void sendEncryptedPathPayload (NodeEntry *targetNode, const ReturnedPathPayload *path); +void sendEncryptedPathPayload (const NodeEntry *targetNode, const ReturnedPathPayload *path); void decodeEncryptedPayload (const FrameStruct *frame); -void parseEncryptedPayload (const EncryptedPayloadStruct * enc); +void parseEncryptedPayload (const EncryptedPayloadStruct *enc); + +void processCommand(char * cmd, NodeEntry * remNode); + +void sendPathBack (const NodeEntry *node, const Path *path); #endif \ No newline at end of file diff --git a/User/meshcore/packets/group.c b/User/meshcore/packets/group.c index 2ab8bae..dfbba43 100644 --- a/User/meshcore/packets/group.c +++ b/User/meshcore/packets/group.c @@ -11,7 +11,7 @@ void sendGroupMessage (const GroupTextMessage *msg) { // Prepare values locally instead of modifying msg - uint8_t channelHash = persistent.aesKeys[msg->keyIndex][0]; + Channel *channel = &(persistent.channels[msg->keyIndex]); uint8_t flags = 0; int32_t timestamp = RTC_GetCounter(); @@ -19,7 +19,7 @@ void sendGroupMessage (const GroupTextMessage *msg) { frame.header = ROUTE_TYPE_FLOOD | PAYLOAD_TYPE_GRP_TXT | PAYLOAD_VERSION_0; frame.path.pathLen = 0; size_t offset = 0; - frame.payload[offset++] = channelHash; + frame.payload[offset++] = channel->hash; // Build encryption buffer directly on stack (no extra large buffer) uint8_t buf[180]; // enough for timestamp + flags + text @@ -41,10 +41,13 @@ void sendGroupMessage (const GroupTextMessage *msg) { // Encrypt and MAC directly into frame payload after channelHash size_t olen = 0; - encrypt_then_mac (&persistent.aesKeys[msg->keyIndex][1], 16, buf, buf_offset, &frame.payload[offset], &olen); + + encrypt_then_mac (channel->key, 16, buf, buf_offset, &frame.payload[offset], &olen); frame.payloadLen = olen + 1; // +1 for channelHash + channel->timestamp = timestamp; + LoRaTransmit (&frame); } @@ -70,43 +73,35 @@ void decodeGroupMessage (const FrameStruct *frame) { unsigned char tmp[184]; - unsigned char decrypted = 0; - for (unsigned char i = 0; i < AESKeyCount; i++) { + Channel *channel = NULL; - if (msg.channelHash != persistent.aesKeys[i][0]) { - MESH_LOGW (TAG, "Hash %d does not equal %d", persistent.aesKeys[i][0], msg.channelHash); + uint8_t i = 0; + do { + channel = getChannel (msg.channelHash, i); + if (channel == NULL) { + MESH_LOGW (TAG, "Channel hash %d not found", msg.channelHash); + return; + } + if (mac_then_decrypt (channel->key, 16, frame->payload + index, frame->payloadLen - index, tmp) != 0) { + MESH_LOGW (TAG, "HMAC failed on grouphash key %d", msg.channelHash); + i++; continue; + } else { + unsigned char plaintextLen = frame->payloadLen - index; + index = 0; + + memcpy (&msg.timestamp, tmp + index, 4); + index += 4; + msg.flags = tmp[index++]; + + memcpy (msg.text, tmp + index, plaintextLen - index); + + channel->timestamp = RTC_GetCounter(); + + printf ("Message from channel %s: %s\n", channel->name, msg.text); + break; } - 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) { - 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); - decrypted = 1; - break; - } - - - if (!decrypted) { - return; - } - - unsigned char plaintextLen = frame->payloadLen - index; - index = 0; - - memcpy (&msg.timestamp, tmp + index, 4); - index += 4; - msg.flags = tmp[index++]; - - memcpy (msg.text, tmp + index, plaintextLen - index); - - printGroupMessage (&msg); -} - -void printGroupMessage (const GroupTextMessage *msg) { - printf ("Message with channel hash %d, flags %d: %s\n", msg->channelHash, - msg->flags, msg->text); + } while (channel != NULL); } \ No newline at end of file diff --git a/User/meshcore/packets/group.h b/User/meshcore/packets/group.h index 7e97381..befd673 100644 --- a/User/meshcore/packets/group.h +++ b/User/meshcore/packets/group.h @@ -4,12 +4,10 @@ #include "stdint.h" #include "meshcore/packetstructs.h" -void sendGroupMessage (const GroupTextMessage * msg); +void sendGroupMessage (const GroupTextMessage *msg); void makeSendGroupMessage (char *txt, uint8_t keyIndex); -void decodeGroupMessage (const FrameStruct * frame); - -void printGroupMessage (const GroupTextMessage * msg); +void decodeGroupMessage (const FrameStruct *frame); #endif \ No newline at end of file diff --git a/User/meshcore/packets/trace.h b/User/meshcore/packets/trace.h index 7152991..caccf6a 100644 --- a/User/meshcore/packets/trace.h +++ b/User/meshcore/packets/trace.h @@ -2,5 +2,4 @@ #define TRACE_HEADER - #endif \ No newline at end of file diff --git a/User/meshcore/packetstructs.h b/User/meshcore/packetstructs.h index 688c555..31a54fd 100644 --- a/User/meshcore/packetstructs.h +++ b/User/meshcore/packetstructs.h @@ -18,9 +18,16 @@ #define PERM_ACL_READ_WRITE 2 #define PERM_ACL_ADMIN 3 +#define NODE_ENTRY_FAV_FLAG (1 << 0) + #define MAX_PATH_LEN 64 + +#define TXT_TYPE_PLAIN 0 // a plain text message +#define TXT_TYPE_CLI_DATA 1 // a CLI command +#define TXT_TYPE_SIGNED_PLAIN 2 // plain text, signed by sender + typedef enum RouteType { ROUTE_TYPE_TRANSPORT_FLOOD = 0x00, ROUTE_TYPE_FLOOD = 0x01, @@ -126,14 +133,14 @@ typedef struct { 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 last_seen_rt; // remote timestamp + uint32_t last_seen_lt; // local timestamp uint32_t sync_timestamp; } NodeEntry; @@ -146,6 +153,8 @@ typedef struct EncryptedPayloadStruct { uint8_t payload[180]; uint8_t type; NodeEntry *remNode; + const Path *path; + const FrameStruct *origFrame; } EncryptedPayloadStruct; typedef enum NodeType { @@ -229,7 +238,10 @@ typedef struct RepeaterStats { } RepeaterStats; typedef struct Channel { - + char name[32]; + uint8_t key[16]; + uint8_t hash; + int32_t timestamp; } Channel; #endif diff --git a/User/sx1262.c b/User/sx1262.c index fd108dd..4b6eea2 100644 --- a/User/sx1262.c +++ b/User/sx1262.c @@ -29,6 +29,67 @@ void LoRaError (int error) { } } +// Convert bandwidth constant to float in kHz +float loraBwToFloat(uint8_t bw) { + switch (bw) { + case SX126X_LORA_BW_7_8: return 7.8f; + case SX126X_LORA_BW_10_4: return 10.4f; + case SX126X_LORA_BW_15_6: return 15.6f; + case SX126X_LORA_BW_20_8: return 20.8f; + case SX126X_LORA_BW_31_25: return 31.25f; + case SX126X_LORA_BW_41_7: return 41.7f; + case SX126X_LORA_BW_62_5: return 62.5f; + case SX126X_LORA_BW_125_0: return 125.0f; + case SX126X_LORA_BW_250_0: return 250.0f; + case SX126X_LORA_BW_500_0: return 500.0f; + default: return 0.0f; // unknown + } +} + +// Convert float bandwidth (kHz) to constant +uint8_t floatToLoraBw(float bw) { + if (bw == 7.8f) return SX126X_LORA_BW_7_8; + if (bw == 10.4f) return SX126X_LORA_BW_10_4; + if (bw == 15.6f) return SX126X_LORA_BW_15_6; + if (bw == 20.8f) return SX126X_LORA_BW_20_8; + if (bw == 31.25f) return SX126X_LORA_BW_31_25; + if (bw == 41.7f) return SX126X_LORA_BW_41_7; + if (bw == 62.5f) return SX126X_LORA_BW_62_5; + if (bw == 125.0f) return SX126X_LORA_BW_125_0; + if (bw == 250.0f) return SX126X_LORA_BW_250_0; + if (bw == 500.0f) return SX126X_LORA_BW_500_0; + return 0xFF; // invalid +} + +// Convert coding rate constant to float +float loraCrToFloat(uint8_t cr) { + switch (cr) { + case SX126X_LORA_CR_4_5: return 4.0f / 5.0f; + case SX126X_LORA_CR_4_6: return 4.0f / 6.0f; + case SX126X_LORA_CR_4_7: return 4.0f / 7.0f; + case SX126X_LORA_CR_4_8: return 4.0f / 8.0f; + default: return 0.0f; + } +} + +// Convert float coding rate to constant +uint8_t floatToLoraCr(float cr) { + if (cr == 4.0f / 5.0f) return SX126X_LORA_CR_4_5; + if (cr == 4.0f / 6.0f) return SX126X_LORA_CR_4_6; + if (cr == 4.0f / 7.0f) return SX126X_LORA_CR_4_7; + if (cr == 4.0f / 8.0f) return SX126X_LORA_CR_4_8; + return 0xFF; +} + +// Convert MHz to Hz with limit check +uint32_t mhzToHzLimited(double freqMHz) { + double freqHz = freqMHz * 1000000.0; + if (freqHz > 860000000.0 && freqHz < 880000000.0) { + return (uint32_t)freqHz; + } + return 0; // out of range +} + void LoRaInit (void) { txActive = 0; @@ -637,8 +698,8 @@ void SetTx (uint32_t timeoutInMs) { } if (debugPrint) { MESH_LOGI (TAG, "SetTx timeoutInMs=%d" - " tout=%d", - timeoutInMs, tout); + " tout=%d", + timeoutInMs, tout); } buf[0] = (uint8_t)((tout >> 16) & 0xFF); buf[1] = (uint8_t)((tout >> 8) & 0xFF); diff --git a/User/sx1262.h b/User/sx1262.h index 1fe4a2a..4cc2225 100644 --- a/User/sx1262.h +++ b/User/sx1262.h @@ -1,434 +1,449 @@ #ifndef _RA01S_H #define _RA01S_H -//return values -#define ERR_NONE 0 -#define ERR_PACKET_TOO_LONG 1 -#define ERR_UNKNOWN 2 -#define ERR_TX_TIMEOUT 3 -#define ERR_RX_TIMEOUT 4 -#define ERR_CRC_MISMATCH 5 -#define ERR_WRONG_MODEM 6 -#define ERR_INVALID_BANDWIDTH 7 -#define ERR_INVALID_SPREADING_FACTOR 8 -#define ERR_INVALID_CODING_RATE 9 +// return values +#define ERR_NONE 0 +#define ERR_PACKET_TOO_LONG 1 +#define ERR_UNKNOWN 2 +#define ERR_TX_TIMEOUT 3 +#define ERR_RX_TIMEOUT 4 +#define ERR_CRC_MISMATCH 5 +#define ERR_WRONG_MODEM 6 +#define ERR_INVALID_BANDWIDTH 7 +#define ERR_INVALID_SPREADING_FACTOR 8 +#define ERR_INVALID_CODING_RATE 9 #define ERR_INVALID_FREQUENCY_DEVIATION 10 -#define ERR_INVALID_BIT_RATE 11 -#define ERR_INVALID_RX_BANDWIDTH 12 -#define ERR_INVALID_DATA_SHAPING 13 -#define ERR_INVALID_SYNC_WORD 14 -#define ERR_INVALID_OUTPUT_POWER 15 -#define ERR_INVALID_MODE 16 -#define ERR_INVALID_TRANCEIVER 17 -#define ERR_INVALID_SETRX_STATE 18 -#define ERR_INVALID_SETTX_STATE 19 -#define ERR_IDLE_TIMEOUT 20 -#define ERR_SPI_TRANSACTION 21 +#define ERR_INVALID_BIT_RATE 11 +#define ERR_INVALID_RX_BANDWIDTH 12 +#define ERR_INVALID_DATA_SHAPING 13 +#define ERR_INVALID_SYNC_WORD 14 +#define ERR_INVALID_OUTPUT_POWER 15 +#define ERR_INVALID_MODE 16 +#define ERR_INVALID_TRANCEIVER 17 +#define ERR_INVALID_SETRX_STATE 18 +#define ERR_INVALID_SETTX_STATE 19 +#define ERR_IDLE_TIMEOUT 20 +#define ERR_SPI_TRANSACTION 21 // SX126X physical layer properties -#define XTAL_FREQ ( double )32000000 -#define FREQ_DIV ( double )pow( 2.0, 25.0 ) -#define FREQ_STEP ( double )( XTAL_FREQ / FREQ_DIV ) +#define XTAL_FREQ (double)32000000 +#define FREQ_DIV (double)pow (2.0, 25.0) +#define FREQ_STEP (double)(XTAL_FREQ / FREQ_DIV) -#define LOW 0 -#define HIGH 1 -#define BUSY_WAIT 5000 +#define LOW 0 +#define HIGH 1 +#define BUSY_WAIT 5000 // SX126X Model -#define SX1261_TRANCEIVER 0x01 -#define SX1262_TRANCEIVER 0x02 -#define SX1268_TRANCEIVER 0x08 +#define SX1261_TRANCEIVER 0x01 +#define SX1262_TRANCEIVER 0x02 +#define SX1268_TRANCEIVER 0x08 // SX126X SPI commands // operational modes commands -#define SX126X_CMD_NOP 0x00 -#define SX126X_CMD_SET_SLEEP 0x84 -#define SX126X_CMD_SET_STANDBY 0x80 -#define SX126X_CMD_SET_FS 0xC1 -#define SX126X_CMD_SET_TX 0x83 -#define SX126X_CMD_SET_RX 0x82 -#define SX126X_CMD_STOP_TIMER_ON_PREAMBLE 0x9F -#define SX126X_CMD_SET_RX_DUTY_CYCLE 0x94 -#define SX126X_CMD_SET_CAD 0xC5 -#define SX126X_CMD_SET_TX_CONTINUOUS_WAVE 0xD1 -#define SX126X_CMD_SET_TX_INFINITE_PREAMBLE 0xD2 -#define SX126X_CMD_SET_REGULATOR_MODE 0x96 -#define SX126X_CMD_CALIBRATE 0x89 -#define SX126X_CMD_CALIBRATE_IMAGE 0x98 -#define SX126X_CMD_SET_PA_CONFIG 0x95 -#define SX126X_CMD_SET_RX_TX_FALLBACK_MODE 0x93 +#define SX126X_CMD_NOP 0x00 +#define SX126X_CMD_SET_SLEEP 0x84 +#define SX126X_CMD_SET_STANDBY 0x80 +#define SX126X_CMD_SET_FS 0xC1 +#define SX126X_CMD_SET_TX 0x83 +#define SX126X_CMD_SET_RX 0x82 +#define SX126X_CMD_STOP_TIMER_ON_PREAMBLE 0x9F +#define SX126X_CMD_SET_RX_DUTY_CYCLE 0x94 +#define SX126X_CMD_SET_CAD 0xC5 +#define SX126X_CMD_SET_TX_CONTINUOUS_WAVE 0xD1 +#define SX126X_CMD_SET_TX_INFINITE_PREAMBLE 0xD2 +#define SX126X_CMD_SET_REGULATOR_MODE 0x96 +#define SX126X_CMD_CALIBRATE 0x89 +#define SX126X_CMD_CALIBRATE_IMAGE 0x98 +#define SX126X_CMD_SET_PA_CONFIG 0x95 +#define SX126X_CMD_SET_RX_TX_FALLBACK_MODE 0x93 // register and buffer access commands -#define SX126X_CMD_WRITE_REGISTER 0x0D -#define SX126X_CMD_READ_REGISTER 0x1D -#define SX126X_CMD_WRITE_BUFFER 0x0E -#define SX126X_CMD_READ_BUFFER 0x1E +#define SX126X_CMD_WRITE_REGISTER 0x0D +#define SX126X_CMD_READ_REGISTER 0x1D +#define SX126X_CMD_WRITE_BUFFER 0x0E +#define SX126X_CMD_READ_BUFFER 0x1E // DIO and IRQ control -#define SX126X_CMD_SET_DIO_IRQ_PARAMS 0x08 -#define SX126X_CMD_GET_IRQ_STATUS 0x12 -#define SX126X_CMD_CLEAR_IRQ_STATUS 0x02 -#define SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL 0x9D -#define SX126X_CMD_SET_DIO3_AS_TCXO_CTRL 0x97 +#define SX126X_CMD_SET_DIO_IRQ_PARAMS 0x08 +#define SX126X_CMD_GET_IRQ_STATUS 0x12 +#define SX126X_CMD_CLEAR_IRQ_STATUS 0x02 +#define SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL 0x9D +#define SX126X_CMD_SET_DIO3_AS_TCXO_CTRL 0x97 // RF, modulation and packet commands -#define SX126X_CMD_SET_RF_FREQUENCY 0x86 -#define SX126X_CMD_SET_PACKET_TYPE 0x8A -#define SX126X_CMD_GET_PACKET_TYPE 0x11 -#define SX126X_CMD_SET_TX_PARAMS 0x8E -#define SX126X_CMD_SET_MODULATION_PARAMS 0x8B -#define SX126X_CMD_SET_PACKET_PARAMS 0x8C -#define SX126X_CMD_SET_CAD_PARAMS 0x88 -#define SX126X_CMD_SET_BUFFER_BASE_ADDRESS 0x8F -#define SX126X_CMD_SET_LORA_SYMB_NUM_TIMEOUT 0xA0 +#define SX126X_CMD_SET_RF_FREQUENCY 0x86 +#define SX126X_CMD_SET_PACKET_TYPE 0x8A +#define SX126X_CMD_GET_PACKET_TYPE 0x11 +#define SX126X_CMD_SET_TX_PARAMS 0x8E +#define SX126X_CMD_SET_MODULATION_PARAMS 0x8B +#define SX126X_CMD_SET_PACKET_PARAMS 0x8C +#define SX126X_CMD_SET_CAD_PARAMS 0x88 +#define SX126X_CMD_SET_BUFFER_BASE_ADDRESS 0x8F +#define SX126X_CMD_SET_LORA_SYMB_NUM_TIMEOUT 0xA0 -#define SX126X_PA_CONFIG_SX1261 0x01 -#define SX126X_PA_CONFIG_SX1262 0x00 +#define SX126X_PA_CONFIG_SX1261 0x01 +#define SX126X_PA_CONFIG_SX1262 0x00 // status commands -#define SX126X_CMD_GET_STATUS 0xC0 -#define SX126X_CMD_GET_RSSI_INST 0x15 -#define SX126X_CMD_GET_RX_BUFFER_STATUS 0x13 -#define SX126X_CMD_GET_PACKET_STATUS 0x14 -#define SX126X_CMD_GET_DEVICE_ERRORS 0x17 -#define SX126X_CMD_CLEAR_DEVICE_ERRORS 0x07 -#define SX126X_CMD_GET_STATS 0x10 -#define SX126X_CMD_RESET_STATS 0x00 +#define SX126X_CMD_GET_STATUS 0xC0 +#define SX126X_CMD_GET_RSSI_INST 0x15 +#define SX126X_CMD_GET_RX_BUFFER_STATUS 0x13 +#define SX126X_CMD_GET_PACKET_STATUS 0x14 +#define SX126X_CMD_GET_DEVICE_ERRORS 0x17 +#define SX126X_CMD_CLEAR_DEVICE_ERRORS 0x07 +#define SX126X_CMD_GET_STATS 0x10 +#define SX126X_CMD_RESET_STATS 0x00 // SX126X register map -#define SX126X_REG_HOPPING_ENABLE 0x0385 -#define SX126X_REG_PACKECT_LENGTH 0x0386 -#define SX126X_REG_NB_HOPPING_BLOCKS 0x0387 -#define SX126X_REG_NB_SYMBOLS0 0x0388 -#define SX126X_REG_FREQ0 0x038A -#define SX126X_REG_NB_SYMBOLS15 0x03E2 -#define SX126X_REG_FREQ15 0x03E4 -#define SX126X_REG_DIOX_OUTPUT_ENABLE 0x0580 -#define SX126X_REG_DIOX_INPUT_ENABLE 0x0583 -#define SX126X_REG_DIOX_PILL_UP_CONTROL 0x0584 -#define SX126X_REG_DIOX_PULL_DOWN_CONTROL 0x0585 -#define SX126X_REG_WHITENING_INITIAL_MSB 0x06B8 -#define SX126X_REG_WHITENING_INITIAL_LSB 0x06B9 -#define SX126X_REG_CRC_INITIAL_MSB 0x06BC -#define SX126X_REG_CRC_INITIAL_LSB 0x06BD -#define SX126X_REG_CRC_POLYNOMIAL_MSB 0x06BE -#define SX126X_REG_CRC_POLYNOMIAL_LSB 0x06BF -#define SX126X_REG_SYNC_WORD_0 0x06C0 -#define SX126X_REG_SYNC_WORD_1 0x06C1 -#define SX126X_REG_SYNC_WORD_2 0x06C2 -#define SX126X_REG_SYNC_WORD_3 0x06C3 -#define SX126X_REG_SYNC_WORD_4 0x06C4 -#define SX126X_REG_SYNC_WORD_5 0x06C5 -#define SX126X_REG_SYNC_WORD_6 0x06C6 -#define SX126X_REG_SYNC_WORD_7 0x06C7 -#define SX126X_REG_NODE_ADDRESS 0x06CD -#define SX126X_REG_BROADCAST_ADDRESS 0x06CE -#define SX126X_REG_IQ_POLARITY_SETUP 0x0736 -#define SX126X_REG_LORA_SYNC_WORD_MSB 0x0740 -#define SX126X_REG_LORA_SYNC_WORD_LSB 0x0741 -#define SX126X_REG_RANDOM_NUMBER_0 0x0819 -#define SX126X_REG_RANDOM_NUMBER_1 0x081A -#define SX126X_REG_RANDOM_NUMBER_2 0x081B -#define SX126X_REG_RANDOM_NUMBER_3 0x081C -#define SX126X_REG_TX_MODULETION 0x0889 -#define SX126X_REG_RX_GAIN 0x08AC -#define SX126X_REG_TX_CLAMP_CONFIG 0x08D8 -#define SX126X_REG_OCP_CONFIGURATION 0x08E7 -#define SX126X_REG_RTC_CONTROL 0x0902 -#define SX126X_REG_XTA_TRIM 0x0911 -#define SX126X_REG_XTB_TRIM 0x0912 -#define SX126X_REG_DIO3_OUTPUT_VOLTAGE_CONTROL 0x0920 -#define SX126X_REG_EVENT_MASK 0x0944 +#define SX126X_REG_HOPPING_ENABLE 0x0385 +#define SX126X_REG_PACKECT_LENGTH 0x0386 +#define SX126X_REG_NB_HOPPING_BLOCKS 0x0387 +#define SX126X_REG_NB_SYMBOLS0 0x0388 +#define SX126X_REG_FREQ0 0x038A +#define SX126X_REG_NB_SYMBOLS15 0x03E2 +#define SX126X_REG_FREQ15 0x03E4 +#define SX126X_REG_DIOX_OUTPUT_ENABLE 0x0580 +#define SX126X_REG_DIOX_INPUT_ENABLE 0x0583 +#define SX126X_REG_DIOX_PILL_UP_CONTROL 0x0584 +#define SX126X_REG_DIOX_PULL_DOWN_CONTROL 0x0585 +#define SX126X_REG_WHITENING_INITIAL_MSB 0x06B8 +#define SX126X_REG_WHITENING_INITIAL_LSB 0x06B9 +#define SX126X_REG_CRC_INITIAL_MSB 0x06BC +#define SX126X_REG_CRC_INITIAL_LSB 0x06BD +#define SX126X_REG_CRC_POLYNOMIAL_MSB 0x06BE +#define SX126X_REG_CRC_POLYNOMIAL_LSB 0x06BF +#define SX126X_REG_SYNC_WORD_0 0x06C0 +#define SX126X_REG_SYNC_WORD_1 0x06C1 +#define SX126X_REG_SYNC_WORD_2 0x06C2 +#define SX126X_REG_SYNC_WORD_3 0x06C3 +#define SX126X_REG_SYNC_WORD_4 0x06C4 +#define SX126X_REG_SYNC_WORD_5 0x06C5 +#define SX126X_REG_SYNC_WORD_6 0x06C6 +#define SX126X_REG_SYNC_WORD_7 0x06C7 +#define SX126X_REG_NODE_ADDRESS 0x06CD +#define SX126X_REG_BROADCAST_ADDRESS 0x06CE +#define SX126X_REG_IQ_POLARITY_SETUP 0x0736 +#define SX126X_REG_LORA_SYNC_WORD_MSB 0x0740 +#define SX126X_REG_LORA_SYNC_WORD_LSB 0x0741 +#define SX126X_REG_RANDOM_NUMBER_0 0x0819 +#define SX126X_REG_RANDOM_NUMBER_1 0x081A +#define SX126X_REG_RANDOM_NUMBER_2 0x081B +#define SX126X_REG_RANDOM_NUMBER_3 0x081C +#define SX126X_REG_TX_MODULETION 0x0889 +#define SX126X_REG_RX_GAIN 0x08AC +#define SX126X_REG_TX_CLAMP_CONFIG 0x08D8 +#define SX126X_REG_OCP_CONFIGURATION 0x08E7 +#define SX126X_REG_RTC_CONTROL 0x0902 +#define SX126X_REG_XTA_TRIM 0x0911 +#define SX126X_REG_XTB_TRIM 0x0912 +#define SX126X_REG_DIO3_OUTPUT_VOLTAGE_CONTROL 0x0920 +#define SX126X_REG_EVENT_MASK 0x0944 // SX126X SPI command variables -//SX126X_CMD_SET_SLEEP -#define SX126X_SLEEP_START_COLD 0b00000000 // 2 2 sleep mode: cold start, configuration is lost (default) -#define SX126X_SLEEP_START_WARM 0b00000100 // 2 2 warm start, configuration is retained -#define SX126X_SLEEP_RTC_OFF 0b00000000 // 0 0 wake on RTC timeout: disabled -#define SX126X_SLEEP_RTC_ON 0b00000001 // 0 0 enabled +// SX126X_CMD_SET_SLEEP +#define SX126X_SLEEP_START_COLD 0b00000000 // 2 2 sleep mode: cold start, configuration is lost (default) +#define SX126X_SLEEP_START_WARM 0b00000100 // 2 2 warm start, configuration is retained +#define SX126X_SLEEP_RTC_OFF 0b00000000 // 0 0 wake on RTC timeout: disabled +#define SX126X_SLEEP_RTC_ON 0b00000001 // 0 0 enabled -//SX126X_CMD_SET_STANDBY -#define SX126X_STANDBY_RC 0x00 // 7 0 standby mode: 13 MHz RC oscillator -#define SX126X_STANDBY_XOSC 0x01 // 7 0 32 MHz crystal oscillator +// SX126X_CMD_SET_STANDBY +#define SX126X_STANDBY_RC 0x00 // 7 0 standby mode: 13 MHz RC oscillator +#define SX126X_STANDBY_XOSC 0x01 // 7 0 32 MHz crystal oscillator -//SX126X_CMD_SET_RX -#define SX126X_RX_TIMEOUT_NONE 0x000000 // 23 0 Rx timeout duration: no timeout (Rx single mode) -#define SX126X_RX_TIMEOUT_INF 0xFFFFFF // 23 0 infinite (Rx continuous mode) +// SX126X_CMD_SET_RX +#define SX126X_RX_TIMEOUT_NONE 0x000000 // 23 0 Rx timeout duration: no timeout (Rx single mode) +#define SX126X_RX_TIMEOUT_INF 0xFFFFFF // 23 0 infinite (Rx continuous mode) -//SX126X_CMD_STOP_TIMER_ON_PREAMBLE -#define SX126X_STOP_ON_PREAMBLE_OFF 0x00 // 7 0 stop timer on: sync word or header (default) -#define SX126X_STOP_ON_PREAMBLE_ON 0x01 // 7 0 preamble detection +// SX126X_CMD_STOP_TIMER_ON_PREAMBLE +#define SX126X_STOP_ON_PREAMBLE_OFF 0x00 // 7 0 stop timer on: sync word or header (default) +#define SX126X_STOP_ON_PREAMBLE_ON 0x01 // 7 0 preamble detection -//SX126X_CMD_SET_REGULATOR_MODE -#define SX126X_REGULATOR_LDO 0x00 // 7 0 set regulator mode: LDO (default) -#define SX126X_REGULATOR_DC_DC 0x01 // 7 0 DC-DC +// SX126X_CMD_SET_REGULATOR_MODE +#define SX126X_REGULATOR_LDO 0x00 // 7 0 set regulator mode: LDO (default) +#define SX126X_REGULATOR_DC_DC 0x01 // 7 0 DC-DC -//SX126X_CMD_CALIBRATE -#define SX126X_CALIBRATE_IMAGE_OFF 0b00000000 // 6 6 image calibration: disabled -#define SX126X_CALIBRATE_IMAGE_ON 0b01000000 // 6 6 enabled -#define SX126X_CALIBRATE_ADC_BULK_P_OFF 0b00000000 // 5 5 ADC bulk P calibration: disabled -#define SX126X_CALIBRATE_ADC_BULK_P_ON 0b00100000 // 5 5 enabled -#define SX126X_CALIBRATE_ADC_BULK_N_OFF 0b00000000 // 4 4 ADC bulk N calibration: disabled -#define SX126X_CALIBRATE_ADC_BULK_N_ON 0b00010000 // 4 4 enabled -#define SX126X_CALIBRATE_ADC_PULSE_OFF 0b00000000 // 3 3 ADC pulse calibration: disabled -#define SX126X_CALIBRATE_ADC_PULSE_ON 0b00001000 // 3 3 enabled -#define SX126X_CALIBRATE_PLL_OFF 0b00000000 // 2 2 PLL calibration: disabled -#define SX126X_CALIBRATE_PLL_ON 0b00000100 // 2 2 enabled -#define SX126X_CALIBRATE_RC13M_OFF 0b00000000 // 1 1 13 MHz RC osc. calibration: disabled -#define SX126X_CALIBRATE_RC13M_ON 0b00000010 // 1 1 enabled -#define SX126X_CALIBRATE_RC64K_OFF 0b00000000 // 0 0 64 kHz RC osc. calibration: disabled -#define SX126X_CALIBRATE_RC64K_ON 0b00000001 // 0 0 enabled +// SX126X_CMD_CALIBRATE +#define SX126X_CALIBRATE_IMAGE_OFF 0b00000000 // 6 6 image calibration: disabled +#define SX126X_CALIBRATE_IMAGE_ON 0b01000000 // 6 6 enabled +#define SX126X_CALIBRATE_ADC_BULK_P_OFF 0b00000000 // 5 5 ADC bulk P calibration: disabled +#define SX126X_CALIBRATE_ADC_BULK_P_ON 0b00100000 // 5 5 enabled +#define SX126X_CALIBRATE_ADC_BULK_N_OFF 0b00000000 // 4 4 ADC bulk N calibration: disabled +#define SX126X_CALIBRATE_ADC_BULK_N_ON 0b00010000 // 4 4 enabled +#define SX126X_CALIBRATE_ADC_PULSE_OFF 0b00000000 // 3 3 ADC pulse calibration: disabled +#define SX126X_CALIBRATE_ADC_PULSE_ON 0b00001000 // 3 3 enabled +#define SX126X_CALIBRATE_PLL_OFF 0b00000000 // 2 2 PLL calibration: disabled +#define SX126X_CALIBRATE_PLL_ON 0b00000100 // 2 2 enabled +#define SX126X_CALIBRATE_RC13M_OFF 0b00000000 // 1 1 13 MHz RC osc. calibration: disabled +#define SX126X_CALIBRATE_RC13M_ON 0b00000010 // 1 1 enabled +#define SX126X_CALIBRATE_RC64K_OFF 0b00000000 // 0 0 64 kHz RC osc. calibration: disabled +#define SX126X_CALIBRATE_RC64K_ON 0b00000001 // 0 0 enabled -//SX126X_CMD_CALIBRATE_IMAGE -#define SX126X_CAL_IMG_430_MHZ_1 0x6B -#define SX126X_CAL_IMG_430_MHZ_2 0x6F -#define SX126X_CAL_IMG_470_MHZ_1 0x75 -#define SX126X_CAL_IMG_470_MHZ_2 0x81 -#define SX126X_CAL_IMG_779_MHZ_1 0xC1 -#define SX126X_CAL_IMG_779_MHZ_2 0xC5 -#define SX126X_CAL_IMG_863_MHZ_1 0xD7 -#define SX126X_CAL_IMG_863_MHZ_2 0xDB -#define SX126X_CAL_IMG_902_MHZ_1 0xE1 -#define SX126X_CAL_IMG_902_MHZ_2 0xE9 +// SX126X_CMD_CALIBRATE_IMAGE +#define SX126X_CAL_IMG_430_MHZ_1 0x6B +#define SX126X_CAL_IMG_430_MHZ_2 0x6F +#define SX126X_CAL_IMG_470_MHZ_1 0x75 +#define SX126X_CAL_IMG_470_MHZ_2 0x81 +#define SX126X_CAL_IMG_779_MHZ_1 0xC1 +#define SX126X_CAL_IMG_779_MHZ_2 0xC5 +#define SX126X_CAL_IMG_863_MHZ_1 0xD7 +#define SX126X_CAL_IMG_863_MHZ_2 0xDB +#define SX126X_CAL_IMG_902_MHZ_1 0xE1 +#define SX126X_CAL_IMG_902_MHZ_2 0xE9 -//SX126X_CMD_SET_PA_CONFIG -#define SX126X_PA_CONFIG_HP_MAX 0x07 -#define SX126X_PA_CONFIG_SX1268 0x01 -#define SX126X_PA_CONFIG_PA_LUT 0x01 +// SX126X_CMD_SET_PA_CONFIG +#define SX126X_PA_CONFIG_HP_MAX 0x07 +#define SX126X_PA_CONFIG_SX1268 0x01 +#define SX126X_PA_CONFIG_PA_LUT 0x01 -//SX126X_CMD_SET_RX_TX_FALLBACK_MODE -#define SX126X_RX_TX_FALLBACK_MODE_FS 0x40 // 7 0 after Rx/Tx go to: FS mode -#define SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC 0x30 // 7 0 standby with crystal oscillator -#define SX126X_RX_TX_FALLBACK_MODE_STDBY_RC 0x20 // 7 0 standby with RC oscillator (default) +// SX126X_CMD_SET_RX_TX_FALLBACK_MODE +#define SX126X_RX_TX_FALLBACK_MODE_FS 0x40 // 7 0 after Rx/Tx go to: FS mode +#define SX126X_RX_TX_FALLBACK_MODE_STDBY_XOSC 0x30 // 7 0 standby with crystal oscillator +#define SX126X_RX_TX_FALLBACK_MODE_STDBY_RC 0x20 // 7 0 standby with RC oscillator (default) -//SX126X_CMD_SET_DIO_IRQ_PARAMS -#define SX126X_IRQ_TIMEOUT 0b1000000000 // 9 9 Rx or Tx timeout -#define SX126X_IRQ_CAD_DETECTED 0b0100000000 // 8 8 channel activity detected -#define SX126X_IRQ_CAD_DONE 0b0010000000 // 7 7 channel activity detection finished -#define SX126X_IRQ_CRC_ERR 0b0001000000 // 6 6 wrong CRC received -#define SX126X_IRQ_HEADER_ERR 0b0000100000 // 5 5 LoRa header CRC error -#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received -#define SX126X_IRQ_SYNC_WORD_VALID 0b0000001000 // 3 3 valid sync word detected -#define SX126X_IRQ_PREAMBLE_DETECTED 0b0000000100 // 2 2 preamble detected -#define SX126X_IRQ_RX_DONE 0b0000000010 // 1 1 packet received -#define SX126X_IRQ_TX_DONE 0b0000000001 // 0 0 packet transmission completed -#define SX126X_IRQ_ALL 0b1111111111 // 9 0 all interrupts -#define SX126X_IRQ_NONE 0b0000000000 // 9 0 no interrupts +// SX126X_CMD_SET_DIO_IRQ_PARAMS +#define SX126X_IRQ_TIMEOUT 0b1000000000 // 9 9 Rx or Tx timeout +#define SX126X_IRQ_CAD_DETECTED 0b0100000000 // 8 8 channel activity detected +#define SX126X_IRQ_CAD_DONE 0b0010000000 // 7 7 channel activity detection finished +#define SX126X_IRQ_CRC_ERR 0b0001000000 // 6 6 wrong CRC received +#define SX126X_IRQ_HEADER_ERR 0b0000100000 // 5 5 LoRa header CRC error +#define SX126X_IRQ_HEADER_VALID 0b0000010000 // 4 4 valid LoRa header received +#define SX126X_IRQ_SYNC_WORD_VALID 0b0000001000 // 3 3 valid sync word detected +#define SX126X_IRQ_PREAMBLE_DETECTED 0b0000000100 // 2 2 preamble detected +#define SX126X_IRQ_RX_DONE 0b0000000010 // 1 1 packet received +#define SX126X_IRQ_TX_DONE 0b0000000001 // 0 0 packet transmission completed +#define SX126X_IRQ_ALL 0b1111111111 // 9 0 all interrupts +#define SX126X_IRQ_NONE 0b0000000000 // 9 0 no interrupts -//SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL -#define SX126X_DIO2_AS_IRQ 0x00 // 7 0 DIO2 configuration: IRQ -#define SX126X_DIO2_AS_RF_SWITCH 0x01 // 7 0 RF switch control +// SX126X_CMD_SET_DIO2_AS_RF_SWITCH_CTRL +#define SX126X_DIO2_AS_IRQ 0x00 // 7 0 DIO2 configuration: IRQ +#define SX126X_DIO2_AS_RF_SWITCH 0x01 // 7 0 RF switch control -//SX126X_CMD_SET_DIO3_AS_TCXO_CTRL -#define SX126X_DIO3_OUTPUT_1_6 0x00 // 7 0 DIO3 voltage output for TCXO: 1.6 V -#define SX126X_DIO3_OUTPUT_1_7 0x01 // 7 0 1.7 V -#define SX126X_DIO3_OUTPUT_1_8 0x02 // 7 0 1.8 V -#define SX126X_DIO3_OUTPUT_2_2 0x03 // 7 0 2.2 V -#define SX126X_DIO3_OUTPUT_2_4 0x04 // 7 0 2.4 V -#define SX126X_DIO3_OUTPUT_2_7 0x05 // 7 0 2.7 V -#define SX126X_DIO3_OUTPUT_3_0 0x06 // 7 0 3.0 V -#define SX126X_DIO3_OUTPUT_3_3 0x07 // 7 0 3.3 V +// SX126X_CMD_SET_DIO3_AS_TCXO_CTRL +#define SX126X_DIO3_OUTPUT_1_6 0x00 // 7 0 DIO3 voltage output for TCXO: 1.6 V +#define SX126X_DIO3_OUTPUT_1_7 0x01 // 7 0 1.7 V +#define SX126X_DIO3_OUTPUT_1_8 0x02 // 7 0 1.8 V +#define SX126X_DIO3_OUTPUT_2_2 0x03 // 7 0 2.2 V +#define SX126X_DIO3_OUTPUT_2_4 0x04 // 7 0 2.4 V +#define SX126X_DIO3_OUTPUT_2_7 0x05 // 7 0 2.7 V +#define SX126X_DIO3_OUTPUT_3_0 0x06 // 7 0 3.0 V +#define SX126X_DIO3_OUTPUT_3_3 0x07 // 7 0 3.3 V -//Radio complete Wake-up Time with TCXO stabilisation time -#define RADIO_TCXO_SETUP_TIME 5000 // [us] +// Radio complete Wake-up Time with TCXO stabilisation time +#define RADIO_TCXO_SETUP_TIME 5000 // [us] -//SX126X_CMD_SET_PACKET_TYPE -#define SX126X_PACKET_TYPE_GFSK 0x00 // 7 0 packet type: GFSK -#define SX126X_PACKET_TYPE_LORA 0x01 // 7 0 LoRa +// SX126X_CMD_SET_PACKET_TYPE +#define SX126X_PACKET_TYPE_GFSK 0x00 // 7 0 packet type: GFSK +#define SX126X_PACKET_TYPE_LORA 0x01 // 7 0 LoRa -//SX126X_CMD_SET_TX_PARAMS -#define SX126X_PA_RAMP_10U 0x00 // 7 0 ramp time: 10 us -#define SX126X_PA_RAMP_20U 0x01 // 7 0 20 us -#define SX126X_PA_RAMP_40U 0x02 // 7 0 40 us -#define SX126X_PA_RAMP_80U 0x03 // 7 0 80 us -#define SX126X_PA_RAMP_200U 0x04 // 7 0 200 us -#define SX126X_PA_RAMP_800U 0x05 // 7 0 800 us -#define SX126X_PA_RAMP_1700U 0x06 // 7 0 1700 us -#define SX126X_PA_RAMP_3400U 0x07 // 7 0 3400 us +// SX126X_CMD_SET_TX_PARAMS +#define SX126X_PA_RAMP_10U 0x00 // 7 0 ramp time: 10 us +#define SX126X_PA_RAMP_20U 0x01 // 7 0 20 us +#define SX126X_PA_RAMP_40U 0x02 // 7 0 40 us +#define SX126X_PA_RAMP_80U 0x03 // 7 0 80 us +#define SX126X_PA_RAMP_200U 0x04 // 7 0 200 us +#define SX126X_PA_RAMP_800U 0x05 // 7 0 800 us +#define SX126X_PA_RAMP_1700U 0x06 // 7 0 1700 us +#define SX126X_PA_RAMP_3400U 0x07 // 7 0 3400 us -//SX126X_CMD_SET_MODULATION_PARAMS -#define SX126X_GFSK_FILTER_NONE 0x00 // 7 0 GFSK filter: none -#define SX126X_GFSK_FILTER_GAUSS_0_3 0x08 // 7 0 Gaussian, BT = 0.3 -#define SX126X_GFSK_FILTER_GAUSS_0_5 0x09 // 7 0 Gaussian, BT = 0.5 -#define SX126X_GFSK_FILTER_GAUSS_0_7 0x0A // 7 0 Gaussian, BT = 0.7 -#define SX126X_GFSK_FILTER_GAUSS_1 0x0B // 7 0 Gaussian, BT = 1 -#define SX126X_GFSK_RX_BW_4_8 0x1F // 7 0 GFSK Rx bandwidth: 4.8 kHz -#define SX126X_GFSK_RX_BW_5_8 0x17 // 7 0 5.8 kHz -#define SX126X_GFSK_RX_BW_7_3 0x0F // 7 0 7.3 kHz -#define SX126X_GFSK_RX_BW_9_7 0x1E // 7 0 9.7 kHz -#define SX126X_GFSK_RX_BW_11_7 0x16 // 7 0 11.7 kHz -#define SX126X_GFSK_RX_BW_14_6 0x0E // 7 0 14.6 kHz -#define SX126X_GFSK_RX_BW_19_5 0x1D // 7 0 19.5 kHz -#define SX126X_GFSK_RX_BW_23_4 0x15 // 7 0 23.4 kHz -#define SX126X_GFSK_RX_BW_29_3 0x0D // 7 0 29.3 kHz -#define SX126X_GFSK_RX_BW_39_0 0x1C // 7 0 39.0 kHz -#define SX126X_GFSK_RX_BW_46_9 0x14 // 7 0 46.9 kHz -#define SX126X_GFSK_RX_BW_58_6 0x0C // 7 0 58.6 kHz -#define SX126X_GFSK_RX_BW_78_2 0x1B // 7 0 78.2 kHz -#define SX126X_GFSK_RX_BW_93_8 0x13 // 7 0 93.8 kHz -#define SX126X_GFSK_RX_BW_117_3 0x0B // 7 0 117.3 kHz -#define SX126X_GFSK_RX_BW_156_2 0x1A // 7 0 156.2 kHz -#define SX126X_GFSK_RX_BW_187_2 0x12 // 7 0 187.2 kHz -#define SX126X_GFSK_RX_BW_234_3 0x0A // 7 0 234.3 kHz -#define SX126X_GFSK_RX_BW_312_0 0x19 // 7 0 312.0 kHz -#define SX126X_GFSK_RX_BW_373_6 0x11 // 7 0 373.6 kHz -#define SX126X_GFSK_RX_BW_467_0 0x09 // 7 0 467.0 kHz -#define SX126X_LORA_BW_7_8 0x00 // 7 0 LoRa bandwidth: 7.8 kHz -#define SX126X_LORA_BW_10_4 0x08 // 7 0 10.4 kHz -#define SX126X_LORA_BW_15_6 0x01 // 7 0 15.6 kHz -#define SX126X_LORA_BW_20_8 0x09 // 7 0 20.8 kHz -#define SX126X_LORA_BW_31_25 0x02 // 7 0 31.25 kHz -#define SX126X_LORA_BW_41_7 0x0A // 7 0 41.7 kHz -#define SX126X_LORA_BW_62_5 0x03 // 7 0 62.5 kHz -#define SX126X_LORA_BW_125_0 0x04 // 7 0 125.0 kHz -#define SX126X_LORA_BW_250_0 0x05 // 7 0 250.0 kHz -#define SX126X_LORA_BW_500_0 0x06 // 7 0 500.0 kHz -#define SX126X_LORA_CR_4_5 0x01 // 7 0 LoRa coding rate: 4/5 -#define SX126X_LORA_CR_4_6 0x02 // 7 0 4/6 -#define SX126X_LORA_CR_4_7 0x03 // 7 0 4/7 -#define SX126X_LORA_CR_4_8 0x04 // 7 0 4/8 -#define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF 0x00 // 7 0 LoRa low data rate optimization: disabled -#define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON 0x01 // 7 0 enabled +// SX126X_CMD_SET_MODULATION_PARAMS +#define SX126X_GFSK_FILTER_NONE 0x00 // 7 0 GFSK filter: none +#define SX126X_GFSK_FILTER_GAUSS_0_3 0x08 // 7 0 Gaussian, BT = 0.3 +#define SX126X_GFSK_FILTER_GAUSS_0_5 0x09 // 7 0 Gaussian, BT = 0.5 +#define SX126X_GFSK_FILTER_GAUSS_0_7 0x0A // 7 0 Gaussian, BT = 0.7 +#define SX126X_GFSK_FILTER_GAUSS_1 0x0B // 7 0 Gaussian, BT = 1 +#define SX126X_GFSK_RX_BW_4_8 0x1F // 7 0 GFSK Rx bandwidth: 4.8 kHz +#define SX126X_GFSK_RX_BW_5_8 0x17 // 7 0 5.8 kHz +#define SX126X_GFSK_RX_BW_7_3 0x0F // 7 0 7.3 kHz +#define SX126X_GFSK_RX_BW_9_7 0x1E // 7 0 9.7 kHz +#define SX126X_GFSK_RX_BW_11_7 0x16 // 7 0 11.7 kHz +#define SX126X_GFSK_RX_BW_14_6 0x0E // 7 0 14.6 kHz +#define SX126X_GFSK_RX_BW_19_5 0x1D // 7 0 19.5 kHz +#define SX126X_GFSK_RX_BW_23_4 0x15 // 7 0 23.4 kHz +#define SX126X_GFSK_RX_BW_29_3 0x0D // 7 0 29.3 kHz +#define SX126X_GFSK_RX_BW_39_0 0x1C // 7 0 39.0 kHz +#define SX126X_GFSK_RX_BW_46_9 0x14 // 7 0 46.9 kHz +#define SX126X_GFSK_RX_BW_58_6 0x0C // 7 0 58.6 kHz +#define SX126X_GFSK_RX_BW_78_2 0x1B // 7 0 78.2 kHz +#define SX126X_GFSK_RX_BW_93_8 0x13 // 7 0 93.8 kHz +#define SX126X_GFSK_RX_BW_117_3 0x0B // 7 0 117.3 kHz +#define SX126X_GFSK_RX_BW_156_2 0x1A // 7 0 156.2 kHz +#define SX126X_GFSK_RX_BW_187_2 0x12 // 7 0 187.2 kHz +#define SX126X_GFSK_RX_BW_234_3 0x0A // 7 0 234.3 kHz +#define SX126X_GFSK_RX_BW_312_0 0x19 // 7 0 312.0 kHz +#define SX126X_GFSK_RX_BW_373_6 0x11 // 7 0 373.6 kHz +#define SX126X_GFSK_RX_BW_467_0 0x09 // 7 0 467.0 kHz +#define SX126X_LORA_BW_7_8 0x00 // 7 0 LoRa bandwidth: 7.8 kHz +#define SX126X_LORA_BW_10_4 0x08 // 7 0 10.4 kHz +#define SX126X_LORA_BW_15_6 0x01 // 7 0 15.6 kHz +#define SX126X_LORA_BW_20_8 0x09 // 7 0 20.8 kHz +#define SX126X_LORA_BW_31_25 0x02 // 7 0 31.25 kHz +#define SX126X_LORA_BW_41_7 0x0A // 7 0 41.7 kHz +#define SX126X_LORA_BW_62_5 0x03 // 7 0 62.5 kHz +#define SX126X_LORA_BW_125_0 0x04 // 7 0 125.0 kHz +#define SX126X_LORA_BW_250_0 0x05 // 7 0 250.0 kHz +#define SX126X_LORA_BW_500_0 0x06 // 7 0 500.0 kHz +#define SX126X_LORA_CR_4_5 0x01 // 7 0 LoRa coding rate: 4/5 +#define SX126X_LORA_CR_4_6 0x02 // 7 0 4/6 +#define SX126X_LORA_CR_4_7 0x03 // 7 0 4/7 +#define SX126X_LORA_CR_4_8 0x04 // 7 0 4/8 +#define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_OFF 0x00 // 7 0 LoRa low data rate optimization: disabled +#define SX126X_LORA_LOW_DATA_RATE_OPTIMIZE_ON 0x01 // 7 0 enabled -//SX126X_CMD_SET_PACKET_PARAMS -#define SX126X_GFSK_PREAMBLE_DETECT_OFF 0x00 // 7 0 GFSK minimum preamble length before reception starts: detector disabled -#define SX126X_GFSK_PREAMBLE_DETECT_8 0x04 // 7 0 8 bits -#define SX126X_GFSK_PREAMBLE_DETECT_16 0x05 // 7 0 16 bits -#define SX126X_GFSK_PREAMBLE_DETECT_24 0x06 // 7 0 24 bits -#define SX126X_GFSK_PREAMBLE_DETECT_32 0x07 // 7 0 32 bits -#define SX126X_GFSK_ADDRESS_FILT_OFF 0x00 // 7 0 GFSK address filtering: disabled -#define SX126X_GFSK_ADDRESS_FILT_NODE 0x01 // 7 0 node only -#define SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST 0x02 // 7 0 node and broadcast -#define SX126X_GFSK_PACKET_FIXED 0x00 // 7 0 GFSK packet type: fixed (payload length known in advance to both sides) -#define SX126X_GFSK_PACKET_VARIABLE 0x01 // 7 0 variable (payload length added to packet) -#define SX126X_GFSK_CRC_OFF 0x01 // 7 0 GFSK packet CRC: disabled -#define SX126X_GFSK_CRC_1_BYTE 0x00 // 7 0 1 byte -#define SX126X_GFSK_CRC_2_BYTE 0x02 // 7 0 2 byte -#define SX126X_GFSK_CRC_1_BYTE_INV 0x04 // 7 0 1 byte, inverted -#define SX126X_GFSK_CRC_2_BYTE_INV 0x06 // 7 0 2 byte, inverted -#define SX126X_GFSK_WHITENING_OFF 0x00 // 7 0 GFSK data whitening: disabled -#define SX126X_GFSK_WHITENING_ON 0x01 // 7 0 enabled -#define SX126X_LORA_HEADER_EXPLICIT 0x00 // 7 0 LoRa header mode: explicit -#define SX126X_LORA_HEADER_IMPLICIT 0x01 // 7 0 implicit -#define SX126X_LORA_CRC_OFF 0x00 // 7 0 LoRa CRC mode: disabled -#define SX126X_LORA_CRC_ON 0x01 // 7 0 enabled -#define SX126X_LORA_IQ_STANDARD 0x00 // 7 0 LoRa IQ setup: standard -#define SX126X_LORA_IQ_INVERTED 0x01 // 7 0 inverted +// SX126X_CMD_SET_PACKET_PARAMS +#define SX126X_GFSK_PREAMBLE_DETECT_OFF 0x00 // 7 0 GFSK minimum preamble length before reception starts: detector disabled +#define SX126X_GFSK_PREAMBLE_DETECT_8 0x04 // 7 0 8 bits +#define SX126X_GFSK_PREAMBLE_DETECT_16 0x05 // 7 0 16 bits +#define SX126X_GFSK_PREAMBLE_DETECT_24 0x06 // 7 0 24 bits +#define SX126X_GFSK_PREAMBLE_DETECT_32 0x07 // 7 0 32 bits +#define SX126X_GFSK_ADDRESS_FILT_OFF 0x00 // 7 0 GFSK address filtering: disabled +#define SX126X_GFSK_ADDRESS_FILT_NODE 0x01 // 7 0 node only +#define SX126X_GFSK_ADDRESS_FILT_NODE_BROADCAST 0x02 // 7 0 node and broadcast +#define SX126X_GFSK_PACKET_FIXED 0x00 // 7 0 GFSK packet type: fixed (payload length known in advance to both sides) +#define SX126X_GFSK_PACKET_VARIABLE 0x01 // 7 0 variable (payload length added to packet) +#define SX126X_GFSK_CRC_OFF 0x01 // 7 0 GFSK packet CRC: disabled +#define SX126X_GFSK_CRC_1_BYTE 0x00 // 7 0 1 byte +#define SX126X_GFSK_CRC_2_BYTE 0x02 // 7 0 2 byte +#define SX126X_GFSK_CRC_1_BYTE_INV 0x04 // 7 0 1 byte, inverted +#define SX126X_GFSK_CRC_2_BYTE_INV 0x06 // 7 0 2 byte, inverted +#define SX126X_GFSK_WHITENING_OFF 0x00 // 7 0 GFSK data whitening: disabled +#define SX126X_GFSK_WHITENING_ON 0x01 // 7 0 enabled +#define SX126X_LORA_HEADER_EXPLICIT 0x00 // 7 0 LoRa header mode: explicit +#define SX126X_LORA_HEADER_IMPLICIT 0x01 // 7 0 implicit +#define SX126X_LORA_CRC_OFF 0x00 // 7 0 LoRa CRC mode: disabled +#define SX126X_LORA_CRC_ON 0x01 // 7 0 enabled +#define SX126X_LORA_IQ_STANDARD 0x00 // 7 0 LoRa IQ setup: standard +#define SX126X_LORA_IQ_INVERTED 0x01 // 7 0 inverted -//SX126X_CMD_SET_CAD_PARAMS -#define SX126X_CAD_ON_1_SYMB 0x00 // 7 0 number of symbols used for CAD: 1 -#define SX126X_CAD_ON_2_SYMB 0x01 // 7 0 2 -#define SX126X_CAD_ON_4_SYMB 0x02 // 7 0 4 -#define SX126X_CAD_ON_8_SYMB 0x03 // 7 0 8 -#define SX126X_CAD_ON_16_SYMB 0x04 // 7 0 16 -#define SX126X_CAD_GOTO_STDBY 0x00 // 7 0 after CAD is done, always go to STDBY_RC mode -#define SX126X_CAD_GOTO_RX 0x01 // 7 0 after CAD is done, go to Rx mode if activity is detected +// SX126X_CMD_SET_CAD_PARAMS +#define SX126X_CAD_ON_1_SYMB 0x00 // 7 0 number of symbols used for CAD: 1 +#define SX126X_CAD_ON_2_SYMB 0x01 // 7 0 2 +#define SX126X_CAD_ON_4_SYMB 0x02 // 7 0 4 +#define SX126X_CAD_ON_8_SYMB 0x03 // 7 0 8 +#define SX126X_CAD_ON_16_SYMB 0x04 // 7 0 16 +#define SX126X_CAD_GOTO_STDBY 0x00 // 7 0 after CAD is done, always go to STDBY_RC mode +#define SX126X_CAD_GOTO_RX 0x01 // 7 0 after CAD is done, go to Rx mode if activity is detected -//SX126X_CMD_GET_STATUS -#define SX126X_STATUS_MODE_STDBY_RC 0b00100000 // 6 4 current chip mode: STDBY_RC -#define SX126X_STATUS_MODE_STDBY_XOSC 0b00110000 // 6 4 STDBY_XOSC -#define SX126X_STATUS_MODE_FS 0b01000000 // 6 4 FS -#define SX126X_STATUS_MODE_RX 0b01010000 // 6 4 RX -#define SX126X_STATUS_MODE_TX 0b01100000 // 6 4 TX -#define SX126X_STATUS_DATA_AVAILABLE 0b00000100 // 3 1 command status: packet received and data can be retrieved -#define SX126X_STATUS_CMD_TIMEOUT 0b00000110 // 3 1 SPI command timed out -#define SX126X_STATUS_CMD_INVALID 0b00001000 // 3 1 invalid SPI command -#define SX126X_STATUS_CMD_FAILED 0b00001010 // 3 1 SPI command failed to execute -#define SX126X_STATUS_TX_DONE 0b00001100 // 3 1 packet transmission done -#define SX126X_STATUS_SPI_FAILED 0b11111111 // 7 0 SPI transaction failed +// SX126X_CMD_GET_STATUS +#define SX126X_STATUS_MODE_STDBY_RC 0b00100000 // 6 4 current chip mode: STDBY_RC +#define SX126X_STATUS_MODE_STDBY_XOSC 0b00110000 // 6 4 STDBY_XOSC +#define SX126X_STATUS_MODE_FS 0b01000000 // 6 4 FS +#define SX126X_STATUS_MODE_RX 0b01010000 // 6 4 RX +#define SX126X_STATUS_MODE_TX 0b01100000 // 6 4 TX +#define SX126X_STATUS_DATA_AVAILABLE 0b00000100 // 3 1 command status: packet received and data can be retrieved +#define SX126X_STATUS_CMD_TIMEOUT 0b00000110 // 3 1 SPI command timed out +#define SX126X_STATUS_CMD_INVALID 0b00001000 // 3 1 invalid SPI command +#define SX126X_STATUS_CMD_FAILED 0b00001010 // 3 1 SPI command failed to execute +#define SX126X_STATUS_TX_DONE 0b00001100 // 3 1 packet transmission done +#define SX126X_STATUS_SPI_FAILED 0b11111111 // 7 0 SPI transaction failed -//SX126X_CMD_GET_PACKET_STATUS -#define SX126X_GFSK_RX_STATUS_PREAMBLE_ERR 0b10000000 // 7 7 GFSK Rx status: preamble error -#define SX126X_GFSK_RX_STATUS_SYNC_ERR 0b01000000 // 6 6 sync word error -#define SX126X_GFSK_RX_STATUS_ADRS_ERR 0b00100000 // 5 5 address error -#define SX126X_GFSK_RX_STATUS_CRC_ERR 0b00010000 // 4 4 CRC error -#define SX126X_GFSK_RX_STATUS_LENGTH_ERR 0b00001000 // 3 3 length error -#define SX126X_GFSK_RX_STATUS_ABORT_ERR 0b00000100 // 2 2 abort error -#define SX126X_GFSK_RX_STATUS_PACKET_RECEIVED 0b00000010 // 2 2 packet received -#define SX126X_GFSK_RX_STATUS_PACKET_SENT 0b00000001 // 2 2 packet sent +// SX126X_CMD_GET_PACKET_STATUS +#define SX126X_GFSK_RX_STATUS_PREAMBLE_ERR 0b10000000 // 7 7 GFSK Rx status: preamble error +#define SX126X_GFSK_RX_STATUS_SYNC_ERR 0b01000000 // 6 6 sync word error +#define SX126X_GFSK_RX_STATUS_ADRS_ERR 0b00100000 // 5 5 address error +#define SX126X_GFSK_RX_STATUS_CRC_ERR 0b00010000 // 4 4 CRC error +#define SX126X_GFSK_RX_STATUS_LENGTH_ERR 0b00001000 // 3 3 length error +#define SX126X_GFSK_RX_STATUS_ABORT_ERR 0b00000100 // 2 2 abort error +#define SX126X_GFSK_RX_STATUS_PACKET_RECEIVED 0b00000010 // 2 2 packet received +#define SX126X_GFSK_RX_STATUS_PACKET_SENT 0b00000001 // 2 2 packet sent -//SX126X_CMD_GET_DEVICE_ERRORS -#define SX126X_PA_RAMP_ERR 0b100000000 // 8 8 device errors: PA ramping failed -#define SX126X_PLL_LOCK_ERR 0b001000000 // 6 6 PLL failed to lock -#define SX126X_XOSC_START_ERR 0b000100000 // 5 5 crystal oscillator failed to start -#define SX126X_IMG_CALIB_ERR 0b000010000 // 4 4 image calibration failed -#define SX126X_ADC_CALIB_ERR 0b000001000 // 3 3 ADC calibration failed -#define SX126X_PLL_CALIB_ERR 0b000000100 // 2 2 PLL calibration failed -#define SX126X_RC13M_CALIB_ERR 0b000000010 // 1 1 RC13M calibration failed -#define SX126X_RC64K_CALIB_ERR 0b000000001 // 0 0 RC64K calibration failed +// SX126X_CMD_GET_DEVICE_ERRORS +#define SX126X_PA_RAMP_ERR 0b100000000 // 8 8 device errors: PA ramping failed +#define SX126X_PLL_LOCK_ERR 0b001000000 // 6 6 PLL failed to lock +#define SX126X_XOSC_START_ERR 0b000100000 // 5 5 crystal oscillator failed to start +#define SX126X_IMG_CALIB_ERR 0b000010000 // 4 4 image calibration failed +#define SX126X_ADC_CALIB_ERR 0b000001000 // 3 3 ADC calibration failed +#define SX126X_PLL_CALIB_ERR 0b000000100 // 2 2 PLL calibration failed +#define SX126X_RC13M_CALIB_ERR 0b000000010 // 1 1 RC13M calibration failed +#define SX126X_RC64K_CALIB_ERR 0b000000001 // 0 0 RC64K calibration failed // SX126X SPI register variables -//SX126X_REG_LORA_SYNC_WORD_MSB + LSB -//#define SX126X_SYNC_WORD_PUBLIC 0x3444 -#define SX126X_SYNC_WORD_PUBLIC 0x24B4 //meshtastic -#define SX126X_SYNC_WORD_PRIVATE 0x1424 +// SX126X_REG_LORA_SYNC_WORD_MSB + LSB +// #define SX126X_SYNC_WORD_PUBLIC 0x3444 +#define SX126X_SYNC_WORD_PUBLIC 0x24B4 // meshtastic +#define SX126X_SYNC_WORD_PRIVATE 0x1424 -#define SX126x_TXMODE_ASYNC 0x01 -#define SX126x_TXMODE_SYNC 0x02 -#define SX126x_TXMODE_BACK2RX 0x04 +#define SX126x_TXMODE_ASYNC 0x01 +#define SX126x_TXMODE_SYNC 0x02 +#define SX126x_TXMODE_BACK2RX 0x04 + +// Convert bandwidth constant to float in kHz +float loraBwToFloat(uint8_t bw); + +// Convert float bandwidth (kHz) to constant +uint8_t floatToLoraBw(float bw); + +// Convert coding rate constant to float +float loraCrToFloat(uint8_t cr); + +// Convert float coding rate to constant +uint8_t floatToLoraCr(float cr); + +// Convert MHz to Hz with limit check +uint32_t mhzToHzLimited(double freqMHz); // Public function -void LoRaInit(void); -int16_t LoRaBegin(uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltage, char useRegulatorLDO); -void LoRaConfig(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint16_t preambleLength, uint8_t payloadLen, char crcOn, char invertIrq); -uint8_t LoRaReceive(uint8_t *pData, int16_t len); -char LoRaSend(uint8_t *pData, int16_t len, uint8_t mode); -void LoRaDebugPrint(char enable); +void LoRaInit (void); +int16_t LoRaBegin (uint32_t frequencyInHz, int8_t txPowerInDbm, float tcxoVoltage, char useRegulatorLDO); +void LoRaConfig (uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint16_t preambleLength, uint8_t payloadLen, char crcOn, char invertIrq); +uint8_t LoRaReceive (uint8_t *pData, int16_t len); +char LoRaSend (uint8_t *pData, int16_t len, uint8_t mode); +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_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); +uint8_t spi_transfer (uint8_t address); -char ReceiveMode(void); +char ReceiveMode (void); void GetPacketStatus (int8_t *rssiPacket, int8_t *snrPacket, int8_t *rawSnr); -void SetTxPower(int8_t txPowerInDbm); +void SetTxPower (int8_t txPowerInDbm); -void FixInvertedIQ(uint8_t iqConfig); -void SetDio3AsTcxoCtrl(float voltage, uint32_t delay); -void SetDio2AsRfSwitchCtrl(uint8_t enable); -void ResetLora(void); -void SetStandby(uint8_t mode); -void SetRfFrequency(uint32_t frequency); -void Calibrate(uint8_t calibParam); -void CalibrateImage(uint32_t frequency); -void SetRegulatorMode(uint8_t mode); -void SetBufferBaseAddress(uint8_t txBaseAddress, uint8_t rxBaseAddress); -void SetPowerConfig(int8_t power, uint8_t rampTime); -void SetOvercurrentProtection(float currentLimit); -void SetSyncWord(int16_t sync); -void SetPaConfig(uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel, uint8_t paLut); -void SetDioIrqParams(uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask); -void SetStopRxTimerOnPreambleDetect(char enable); -void SetLoRaSymbNumTimeout(uint8_t SymbNum); -void SetPacketType(uint8_t packetType); -void SetModulationParams(uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint8_t lowDataRateOptimize); -void SetCadParams(uint8_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, uint8_t cadExitMode, uint32_t cadTimeout); -void SetCad(); -uint8_t GetStatus(void); -uint16_t GetIrqStatus(void); -void ClearIrqStatus(uint16_t irq); -void SetRx(uint32_t timeout); -void SetTx(uint32_t timeoutInMs); -int GetPacketLost(); -uint8_t GetRssiInst(); -void GetRxBufferStatus(uint8_t *payloadLength, uint8_t *rxStartBufferPointer); -void Wakeup(void); -void WaitForIdleBegin(unsigned long timeout, char *text); -char WaitForIdle(unsigned long timeout, char *text, char stop); -uint8_t ReadBuffer(uint8_t *rxData, int16_t rxDataLen); -void WriteBuffer(uint8_t *txData, int16_t txDataLen); -void WriteRegister(uint16_t reg, uint8_t* data, uint8_t numBytes); -void ReadRegister(uint16_t reg, uint8_t* data, uint8_t numBytes); -void WriteCommand(uint8_t cmd, uint8_t* data, uint8_t numBytes); -uint8_t WriteCommand2(uint8_t cmd, uint8_t* data, uint8_t numBytes); -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); +void FixInvertedIQ (uint8_t iqConfig); +void SetDio3AsTcxoCtrl (float voltage, uint32_t delay); +void SetDio2AsRfSwitchCtrl (uint8_t enable); +void ResetLora (void); +void SetStandby (uint8_t mode); +void SetRfFrequency (uint32_t frequency); +void Calibrate (uint8_t calibParam); +void CalibrateImage (uint32_t frequency); +void SetRegulatorMode (uint8_t mode); +void SetBufferBaseAddress (uint8_t txBaseAddress, uint8_t rxBaseAddress); +void SetPowerConfig (int8_t power, uint8_t rampTime); +void SetOvercurrentProtection (float currentLimit); +void SetSyncWord (int16_t sync); +void SetPaConfig (uint8_t paDutyCycle, uint8_t hpMax, uint8_t deviceSel, uint8_t paLut); +void SetDioIrqParams (uint16_t irqMask, uint16_t dio1Mask, uint16_t dio2Mask, uint16_t dio3Mask); +void SetStopRxTimerOnPreambleDetect (char enable); +void SetLoRaSymbNumTimeout (uint8_t SymbNum); +void SetPacketType (uint8_t packetType); +void SetModulationParams (uint8_t spreadingFactor, uint8_t bandwidth, uint8_t codingRate, uint8_t lowDataRateOptimize); +void SetCadParams (uint8_t cadSymbolNum, uint8_t cadDetPeak, uint8_t cadDetMin, uint8_t cadExitMode, uint32_t cadTimeout); +void SetCad(); +uint8_t GetStatus (void); +uint16_t GetIrqStatus (void); +void ClearIrqStatus (uint16_t irq); +void SetRx (uint32_t timeout); +void SetTx (uint32_t timeoutInMs); +int GetPacketLost(); +uint8_t GetRssiInst(); +void GetRxBufferStatus (uint8_t *payloadLength, uint8_t *rxStartBufferPointer); +void Wakeup (void); +void WaitForIdleBegin (unsigned long timeout, char *text); +char WaitForIdle (unsigned long timeout, char *text, char stop); +uint8_t ReadBuffer (uint8_t *rxData, int16_t rxDataLen); +void WriteBuffer (uint8_t *txData, int16_t txDataLen); +void WriteRegister (uint16_t reg, uint8_t *data, uint8_t numBytes); +void ReadRegister (uint16_t reg, uint8_t *data, uint8_t numBytes); +void WriteCommand (uint8_t cmd, uint8_t *data, uint8_t numBytes); +uint8_t WriteCommand2 (uint8_t cmd, uint8_t *data, uint8_t numBytes); +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; diff --git a/User/util/hexdump.c b/User/util/hexdump.c index e049b17..5fb502b 100644 --- a/User/util/hexdump.c +++ b/User/util/hexdump.c @@ -21,4 +21,19 @@ void hexdump (const char *label, const uint8_t *data, size_t len) { } printf ("\n"); } +} + +void hexdump_compact(const uint8_t* data, size_t len, char* out, size_t out_size) { + size_t pos = 0; + + for (size_t i = 0; i < len; i++) { + if (pos + 2 >= out_size) break; // make sure we don¡¯t overflow + snprintf(out + pos, 3, "%02x", data[i]); // 2 chars + null terminator + pos += 2; + } + + if (pos < out_size) + out[pos] = '\0'; + else + out[out_size - 1] = '\0'; // ensure null termination } \ No newline at end of file diff --git a/User/util/hexdump.h b/User/util/hexdump.h index cbd0616..85fa06b 100644 --- a/User/util/hexdump.h +++ b/User/util/hexdump.h @@ -6,4 +6,6 @@ #include "stdint.h" void hexdump (const char *label, const uint8_t *data, size_t len); +void hexdump_compact(const uint8_t* data, size_t len, char* out, size_t out_size); + #endif \ No newline at end of file