From 0a2e390c1721632a045c118198bb6b5d2881bfcb Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 16 Aug 2024 14:09:20 +0200 Subject: [PATCH 01/17] Updated Eclipse project settings --- lib-arm/.cproject | 22 +- lib-arm/.settings/language.settings.xml | 6 +- lib-arm/.settings/org.eclipse.cdt.core.prefs | 5 + lib-artnet/.cproject | 264 ++++++---- lib-artnet/.settings/language.settings.xml | 13 +- .../org.eclipse.core.resources.prefs | 6 +- lib-bcm2835/.settings/language.settings.xml | 2 +- .../org.eclipse.core.resources.prefs | 1 - .../.settings/language.settings.xml | 7 +- lib-ddp/.settings/language.settings.xml | 6 +- lib-device/.settings/language.settings.xml | 6 +- lib-display/.cproject | 3 - lib-display/.settings/language.settings.xml | 13 +- lib-displayudf/.cproject | 306 ++++++++---- .../.settings/language.settings.xml | 19 +- lib-dmx/.cproject | 316 ++++++++---- lib-dmx/.settings/language.settings.xml | 21 +- lib-dmxmonitor/.cproject | 21 +- .../.settings/language.settings.xml | 11 +- lib-dmxserial/.cproject | 29 +- lib-dmxserial/.settings/language.settings.xml | 9 +- lib-e131/.cproject | 31 +- lib-e131/.settings/language.settings.xml | 11 +- .../org.eclipse.core.resources.prefs | 8 +- lib-flash/.settings/language.settings.xml | 4 +- lib-flashcode/.settings/language.settings.xml | 4 +- lib-flashcodeinstall/.cproject | 19 +- .../.settings/language.settings.xml | 7 +- lib-gps/.cproject | 10 +- lib-gps/.settings/language.settings.xml | 4 +- lib-h3/.cproject | 29 +- lib-h3/.settings/language.settings.xml | 4 +- lib-hal/.cproject | 276 ++++++---- lib-hal/.settings/language.settings.xml | 16 +- lib-input/.cproject | 6 - lib-input/.settings/language.settings.xml | 6 +- lib-jamstapl/.settings/language.settings.xml | 7 +- lib-l6470/.settings/language.settings.xml | 6 +- lib-l6470dmx/.settings/language.settings.xml | 11 +- lib-lightset/.cproject | 223 +++++++-- lib-lightset/.settings/language.settings.xml | 11 +- lib-ltc/.settings/language.settings.xml | 2 +- lib-midi/.cproject | 11 +- lib-midi/.settings/language.settings.xml | 9 +- lib-network/.cproject | 472 ++++++++++++++---- lib-network/.settings/language.settings.xml | 17 +- .../org.eclipse.cdt.codan.core.prefs | 4 +- lib-osc/.settings/language.settings.xml | 8 +- lib-pca9685/.cproject | 6 - lib-pca9685/.settings/language.settings.xml | 8 +- .../.settings/language.settings.xml | 11 +- lib-pp/.settings/language.settings.xml | 15 +- lib-properties/.cproject | 221 ++++++-- .../.settings/language.settings.xml | 14 +- lib-rdm/.settings/language.settings.xml | 76 +-- lib-rdmsensor/.cproject | 6 - lib-rdmsensor/.settings/language.settings.xml | 11 +- lib-rdmsubdevice/.cproject | 37 +- .../.settings/language.settings.xml | 8 +- lib-remoteconfig/.cproject | 377 ++++++++------ .../.settings/language.settings.xml | 46 +- lib-rgbpanel/.settings/language.settings.xml | 2 +- lib-showfile/.settings/language.settings.xml | 4 +- lib-tcnet/.settings/language.settings.xml | 6 +- lib-tlc59711/.settings/language.settings.xml | 6 +- lib-tlc59711dmx/.cproject | 251 +++++++--- .../.settings/language.settings.xml | 67 +-- lib-usb/.settings/language.settings.xml | 9 +- lib-uuid/.cproject | 3 - lib-uuid/.settings/language.settings.xml | 18 +- lib-widget/.settings/language.settings.xml | 9 +- lib-ws28xx/.cproject | 237 ++++++--- lib-ws28xx/.settings/language.settings.xml | 14 +- .../.settings/language.settings.xml | 4 +- lib-ws28xxdmx/.cproject | 247 ++++++--- lib-ws28xxdmx/.settings/language.settings.xml | 73 +-- linux_artnet/.settings/language.settings.xml | 4 +- linux_ddp/.settings/language.settings.xml | 2 +- linux_e131/.settings/language.settings.xml | 28 +- linux_osc/.settings/language.settings.xml | 2 +- linux_pp/.settings/language.settings.xml | 2 +- opi_dmx_monitor/.cproject | 10 +- .../.settings/language.settings.xml | 6 +- .../.settings/language.settings.xml | 2 +- opi_emac_artnet_dmx/.cproject | 1 - .../.settings/language.settings.xml | 7 +- .../.settings/language.settings.xml | 2 +- .../.settings/language.settings.xml | 2 +- opi_emac_artnet_pixel/.cproject | 205 ++++++-- .../.settings/language.settings.xml | 10 +- opi_emac_artnet_pixel_dmx/.cproject | 193 +++++-- .../.settings/language.settings.xml | 10 +- opi_emac_artnet_pixel_dmx_multi/.cproject | 199 ++++++-- .../.settings/language.settings.xml | 10 +- opi_emac_artnet_pixel_multi/.cproject | 197 ++++++-- .../.settings/language.settings.xml | 10 +- .../.settings/language.settings.xml | 2 +- .../.settings/language.settings.xml | 2 +- .../.settings/language.settings.xml | 2 +- .../.settings/language.settings.xml | 7 +- .../.settings/language.settings.xml | 2 +- .../.settings/language.settings.xml | 7 +- .../.settings/language.settings.xml | 4 +- .../.settings/language.settings.xml | 2 +- .../.settings/language.settings.xml | 2 +- opi_emac_e131_pixel/.cproject | 236 ++++++--- .../.settings/language.settings.xml | 10 +- opi_emac_e131_pixel_dmx/.cproject | 67 +-- .../.settings/language.settings.xml | 4 +- opi_emac_e131_pixel_dmx_multi/.cproject | 70 ++- .../.settings/language.settings.xml | 4 +- opi_emac_e131_pixel_multi/.cproject | 217 +++++--- .../.settings/language.settings.xml | 10 +- .../.settings/language.settings.xml | 2 +- .../.settings/language.settings.xml | 4 +- .../.settings/language.settings.xml | 4 +- .../.settings/language.settings.xml | 4 +- .../.settings/language.settings.xml | 2 +- .../.settings/language.settings.xml | 4 +- .../.settings/language.settings.xml | 4 +- .../.settings/language.settings.xml | 2 +- .../.settings/language.settings.xml | 4 +- .../.settings/language.settings.xml | 2 +- .../.settings/language.settings.xml | 2 +- .../.settings/language.settings.xml | 4 +- .../.settings/language.settings.xml | 4 +- rpi_wifi_artnet_dmx/.cproject | 10 - .../.settings/language.settings.xml | 4 +- rpi_wifi_artnet_monitor/.cproject | 12 - .../.settings/language.settings.xml | 4 +- rpi_wifi_artnet_pixel/.cproject | 10 - .../.settings/language.settings.xml | 6 +- rpi_wifi_e131_dmx/.cproject | 13 - .../.settings/language.settings.xml | 4 +- rpi_wifi_e131_monitor/.cproject | 13 - .../.settings/language.settings.xml | 4 +- rpi_wifi_e131_pixel/.cproject | 13 - .../.settings/language.settings.xml | 4 +- rpi_wifi_osc_dmx/.cproject | 30 +- .../.settings/language.settings.xml | 4 +- rpi_wifi_osc_monitor/.cproject | 10 - .../.settings/language.settings.xml | 4 +- rpi_wifi_osc_pixel/.cproject | 10 - .../.settings/language.settings.xml | 4 +- 144 files changed, 3868 insertions(+), 1971 deletions(-) diff --git a/lib-arm/.cproject b/lib-arm/.cproject index d93f1a0df..267b807f3 100644 --- a/lib-arm/.cproject +++ b/lib-arm/.cproject @@ -30,7 +30,7 @@ - @@ -45,7 +45,7 @@ - @@ -55,7 +55,6 @@ - @@ -134,28 +133,31 @@ - + - + - + - + + + + - + - + - + diff --git a/lib-arm/.settings/language.settings.xml b/lib-arm/.settings/language.settings.xml index 24de12f84..a6b666344 100644 --- a/lib-arm/.settings/language.settings.xml +++ b/lib-arm/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,8 +16,8 @@ - - + + diff --git a/lib-arm/.settings/org.eclipse.cdt.core.prefs b/lib-arm/.settings/org.eclipse.cdt.core.prefs index ce4acac65..a7bd6a931 100644 --- a/lib-arm/.settings/org.eclipse.cdt.core.prefs +++ b/lib-arm/.settings/org.eclipse.cdt.core.prefs @@ -1,3 +1,8 @@ +doxygen/doxygen_new_line_after_brief=true +doxygen/doxygen_use_brief_tag=false +doxygen/doxygen_use_javadoc_tags=true +doxygen/doxygen_use_pre_tag=false +doxygen/doxygen_use_structural_commands=false eclipse.preferences.version=1 environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1544501101.820928665/PATH/delimiter=\: environment/project/cdt.managedbuild.toolchain.gnu.cross.base.1544501101.820928665/PATH/operation=replace diff --git a/lib-artnet/.cproject b/lib-artnet/.cproject index 3fea08af0..021d9bfcd 100644 --- a/lib-artnet/.cproject +++ b/lib-artnet/.cproject @@ -5,7 +5,6 @@ - @@ -125,7 +124,6 @@ - @@ -135,7 +133,6 @@ - @@ -252,17 +249,16 @@ - - - + + - + @@ -271,97 +267,181 @@ - - - - @@ -390,35 +470,41 @@ + + + - + - + - + - + - + - + - + - + + + + \ No newline at end of file diff --git a/lib-artnet/.settings/language.settings.xml b/lib-artnet/.settings/language.settings.xml index 45a96dfcf..6bfe2d1cb 100644 --- a/lib-artnet/.settings/language.settings.xml +++ b/lib-artnet/.settings/language.settings.xml @@ -4,8 +4,8 @@ - - + + @@ -17,19 +17,22 @@ - + - + + + + + - diff --git a/lib-artnet/.settings/org.eclipse.core.resources.prefs b/lib-artnet/.settings/org.eclipse.core.resources.prefs index 32dc57ad4..99f26c020 100644 --- a/lib-artnet/.settings/org.eclipse.core.resources.prefs +++ b/lib-artnet/.settings/org.eclipse.core.resources.prefs @@ -1,4 +1,2 @@ -eclipse.preferences.version=1 -encoding//include/artnet.h=UTF-8 -encoding//include/artnetnode.h=UTF-8 -encoding/=UTF-8 +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/lib-bcm2835/.settings/language.settings.xml b/lib-bcm2835/.settings/language.settings.xml index e020b26c1..d148daee5 100644 --- a/lib-bcm2835/.settings/language.settings.xml +++ b/lib-bcm2835/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/lib-bcm2835/.settings/org.eclipse.core.resources.prefs b/lib-bcm2835/.settings/org.eclipse.core.resources.prefs index 1895d98c2..99f26c020 100644 --- a/lib-bcm2835/.settings/org.eclipse.core.resources.prefs +++ b/lib-bcm2835/.settings/org.eclipse.core.resources.prefs @@ -1,3 +1,2 @@ eclipse.preferences.version=1 -encoding//include/bcm2835.h=UTF-8 encoding/=UTF-8 diff --git a/lib-configstore/.settings/language.settings.xml b/lib-configstore/.settings/language.settings.xml index 1bc711626..02c2228fe 100755 --- a/lib-configstore/.settings/language.settings.xml +++ b/lib-configstore/.settings/language.settings.xml @@ -2,10 +2,13 @@ - - + + + + + diff --git a/lib-ddp/.settings/language.settings.xml b/lib-ddp/.settings/language.settings.xml index 964828623..ff6ec7266 100755 --- a/lib-ddp/.settings/language.settings.xml +++ b/lib-ddp/.settings/language.settings.xml @@ -4,8 +4,8 @@ - - + + @@ -17,7 +17,7 @@ - + diff --git a/lib-device/.settings/language.settings.xml b/lib-device/.settings/language.settings.xml index 23a7e8c3f..b5c9c58da 100644 --- a/lib-device/.settings/language.settings.xml +++ b/lib-device/.settings/language.settings.xml @@ -4,8 +4,8 @@ - - + + @@ -17,7 +17,7 @@ - + diff --git a/lib-display/.cproject b/lib-display/.cproject index c14345ad7..a91552d0d 100755 --- a/lib-display/.cproject +++ b/lib-display/.cproject @@ -102,7 +102,6 @@ - - + + + + + diff --git a/lib-displayudf/.cproject b/lib-displayudf/.cproject index a75144fb7..cf0457ecf 100644 --- a/lib-displayudf/.cproject +++ b/lib-displayudf/.cproject @@ -1,90 +1,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -190,6 +106,196 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -211,34 +317,52 @@ + + + + + + + + + + + + - + - + - + - + - + - + - + + + + + + + diff --git a/lib-displayudf/.settings/language.settings.xml b/lib-displayudf/.settings/language.settings.xml index a82c57fdf..37f53a801 100644 --- a/lib-displayudf/.settings/language.settings.xml +++ b/lib-displayudf/.settings/language.settings.xml @@ -1,23 +1,26 @@ - + - - + + + + + - + - - - - + + + + diff --git a/lib-dmx/.cproject b/lib-dmx/.cproject index 57d01fe3f..f432a57e4 100644 --- a/lib-dmx/.cproject +++ b/lib-dmx/.cproject @@ -5,7 +5,6 @@ - @@ -88,11 +87,10 @@ - - + + - @@ -101,97 +99,68 @@ - - - - - - + + - + @@ -200,52 +169,181 @@ - - - - @@ -272,34 +370,40 @@ + + + - + - + - + - + - + - + - + - + + + + diff --git a/lib-dmx/.settings/language.settings.xml b/lib-dmx/.settings/language.settings.xml index 7b3bee0dc..f8409aefc 100644 --- a/lib-dmx/.settings/language.settings.xml +++ b/lib-dmx/.settings/language.settings.xml @@ -5,31 +5,34 @@ - + - + - - + + + + + - + - - - - + + + + diff --git a/lib-dmxmonitor/.cproject b/lib-dmxmonitor/.cproject index 0bce50547..2b32e748f 100644 --- a/lib-dmxmonitor/.cproject +++ b/lib-dmxmonitor/.cproject @@ -5,7 +5,6 @@ - @@ -25,7 +24,6 @@ - - + + + + + diff --git a/lib-dmxserial/.cproject b/lib-dmxserial/.cproject index bc2e5687f..39ebe7bb0 100644 --- a/lib-dmxserial/.cproject +++ b/lib-dmxserial/.cproject @@ -5,7 +5,6 @@ - @@ -92,7 +91,6 @@ - @@ -193,17 +191,36 @@ - + - + - + - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib-dmxserial/.settings/language.settings.xml b/lib-dmxserial/.settings/language.settings.xml index e30c92e41..6478a718b 100644 --- a/lib-dmxserial/.settings/language.settings.xml +++ b/lib-dmxserial/.settings/language.settings.xml @@ -4,8 +4,11 @@ - - + + + + + @@ -14,7 +17,7 @@ - + diff --git a/lib-e131/.cproject b/lib-e131/.cproject index 3ec85449f..31fed1987 100644 --- a/lib-e131/.cproject +++ b/lib-e131/.cproject @@ -23,7 +23,6 @@ @@ -89,6 +92,7 @@ @@ -133,10 +139,11 @@ - - + + + @@ -145,47 +152,175 @@ - - - - @@ -212,36 +347,42 @@ + + + + + - + - + - + - + - + - + + + + - + + + + - - - - - \ No newline at end of file diff --git a/lib-lightset/.settings/language.settings.xml b/lib-lightset/.settings/language.settings.xml index e7289098f..22d14bfb8 100644 --- a/lib-lightset/.settings/language.settings.xml +++ b/lib-lightset/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,16 +17,19 @@ - + - + - + + + + diff --git a/lib-ltc/.settings/language.settings.xml b/lib-ltc/.settings/language.settings.xml index e396e90b5..bfb7f4ba0 100644 --- a/lib-ltc/.settings/language.settings.xml +++ b/lib-ltc/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/lib-midi/.cproject b/lib-midi/.cproject index 6d42e6a19..5feda7f9d 100644 --- a/lib-midi/.cproject +++ b/lib-midi/.cproject @@ -32,7 +32,6 @@ - @@ -190,10 +187,16 @@ + + + - + + + + diff --git a/lib-midi/.settings/language.settings.xml b/lib-midi/.settings/language.settings.xml index 35cd85b02..7a67189c1 100644 --- a/lib-midi/.settings/language.settings.xml +++ b/lib-midi/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -14,10 +14,13 @@ - - + + + + + diff --git a/lib-network/.cproject b/lib-network/.cproject index 355342876..d6c35f114 100644 --- a/lib-network/.cproject +++ b/lib-network/.cproject @@ -5,6 +5,7 @@ + @@ -13,24 +14,119 @@ - + - - - @@ -100,7 +214,10 @@ - + + + + @@ -136,6 +253,9 @@ + + + @@ -158,6 +286,9 @@ + + + @@ -187,14 +326,16 @@ + + + - - + @@ -203,6 +344,9 @@ + + + @@ -210,10 +354,11 @@ - - + + + @@ -222,81 +367,183 @@ - - - - - - - + + + - + - - - @@ -333,25 +577,22 @@ - + - + - - - - + - + @@ -360,7 +601,22 @@ - + + + + + + + + + + + + + + + + diff --git a/lib-network/.settings/language.settings.xml b/lib-network/.settings/language.settings.xml index 5428b373b..8491c1347 100644 --- a/lib-network/.settings/language.settings.xml +++ b/lib-network/.settings/language.settings.xml @@ -2,13 +2,13 @@ - - - - + + + + @@ -17,19 +17,22 @@ - + - + + + + + - diff --git a/lib-network/.settings/org.eclipse.cdt.codan.core.prefs b/lib-network/.settings/org.eclipse.cdt.codan.core.prefs index ae34d9ba8..b52a5bc4d 100644 --- a/lib-network/.settings/org.eclipse.cdt.codan.core.prefs +++ b/lib-network/.settings/org.eclipse.cdt.codan.core.prefs @@ -164,7 +164,7 @@ org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={lau org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Assignment to itself\\")"} org.eclipse.cdt.codan.internal.checkers.BlacklistProblem=-Warning -org.eclipse.cdt.codan.internal.checkers.BlacklistProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function or method is blacklisted\\")",blacklist\=>()} +org.eclipse.cdt.codan.internal.checkers.BlacklistProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"The use of function or method is denied\\")",blacklist\=>()} org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem=Warning org.eclipse.cdt.codan.internal.checkers.CStyleCastProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"C-Style cast instead of C++ cast\\")",checkMacro\=>true} org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning @@ -239,6 +239,8 @@ org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Suspicious semicolon\\")",else\=>false,afterelse\=>false} org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem=-Warning org.eclipse.cdt.codan.internal.checkers.SymbolShadowingProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Symbol shadowing\\")",paramFuncParameters\=>true} +org.eclipse.cdt.codan.internal.checkers.TemplateInstantiationProblem=Error +org.eclipse.cdt.codan.internal.checkers.TemplateInstantiationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Function cannot be instantiated\\")"} org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},suppression_comment\=>"@suppress(\\"Type cannot be resolved\\")"} org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning diff --git a/lib-osc/.settings/language.settings.xml b/lib-osc/.settings/language.settings.xml index 1505003f2..08eb97609 100644 --- a/lib-osc/.settings/language.settings.xml +++ b/lib-osc/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@ - + @@ -28,8 +28,8 @@ - - + + diff --git a/lib-pca9685/.cproject b/lib-pca9685/.cproject index b64beb67a..ed0275b55 100644 --- a/lib-pca9685/.cproject +++ b/lib-pca9685/.cproject @@ -27,7 +27,6 @@ - @@ -37,7 +36,6 @@ - @@ -55,7 +53,6 @@ - @@ -96,7 +93,6 @@ - @@ -106,7 +102,6 @@ - @@ -124,7 +119,6 @@ - diff --git a/lib-pca9685/.settings/language.settings.xml b/lib-pca9685/.settings/language.settings.xml index e64825710..f5d9857c2 100644 --- a/lib-pca9685/.settings/language.settings.xml +++ b/lib-pca9685/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@ - + @@ -28,8 +28,8 @@ - - + + diff --git a/lib-pca9685dmx/.settings/language.settings.xml b/lib-pca9685dmx/.settings/language.settings.xml index 6e82207f8..d74f367de 100644 --- a/lib-pca9685dmx/.settings/language.settings.xml +++ b/lib-pca9685dmx/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@ - + @@ -26,10 +26,13 @@ - - + + + + + diff --git a/lib-pp/.settings/language.settings.xml b/lib-pp/.settings/language.settings.xml index d1f03c4ed..898a486fe 100755 --- a/lib-pp/.settings/language.settings.xml +++ b/lib-pp/.settings/language.settings.xml @@ -4,17 +4,24 @@ - - + + + + + - - + + + + + + \ No newline at end of file diff --git a/lib-properties/.cproject b/lib-properties/.cproject index 222b017f4..0811ab78d 100644 --- a/lib-properties/.cproject +++ b/lib-properties/.cproject @@ -13,7 +13,7 @@ - + @@ -82,16 +74,17 @@ - - @@ -120,10 +113,11 @@ - - + + + @@ -132,42 +126,159 @@ - - - - @@ -203,16 +314,40 @@ + + + + + + - + + + + + + + + + + + + + + + + + + + - + diff --git a/lib-properties/.settings/language.settings.xml b/lib-properties/.settings/language.settings.xml index a62ff053b..818a97a4a 100644 --- a/lib-properties/.settings/language.settings.xml +++ b/lib-properties/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,22 +17,22 @@ - + - + - - - - + + + + diff --git a/lib-rdm/.settings/language.settings.xml b/lib-rdm/.settings/language.settings.xml index 8c7a2d38f..715fe7f92 100644 --- a/lib-rdm/.settings/language.settings.xml +++ b/lib-rdm/.settings/language.settings.xml @@ -1,39 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib-rdmsensor/.cproject b/lib-rdmsensor/.cproject index 1d71124a9..7965bd8e0 100644 --- a/lib-rdmsensor/.cproject +++ b/lib-rdmsensor/.cproject @@ -25,8 +25,6 @@ diff --git a/lib-rdmsubdevice/.cproject b/lib-rdmsubdevice/.cproject index 0bde4aca8..91e1d037c 100644 --- a/lib-rdmsubdevice/.cproject +++ b/lib-rdmsubdevice/.cproject @@ -5,7 +5,6 @@ - @@ -25,7 +24,6 @@ - @@ -42,7 +40,6 @@ - @@ -86,7 +82,6 @@ - @@ -107,7 +102,6 @@ - @@ -123,7 +117,6 @@ - @@ -148,7 +141,6 @@ - @@ -170,7 +162,6 @@ - @@ -265,34 +256,10 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/lib-rdmsubdevice/.settings/language.settings.xml b/lib-rdmsubdevice/.settings/language.settings.xml index c5d66e844..e3309cfdc 100644 --- a/lib-rdmsubdevice/.settings/language.settings.xml +++ b/lib-rdmsubdevice/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@ - + @@ -28,8 +28,8 @@ - - + + diff --git a/lib-remoteconfig/.cproject b/lib-remoteconfig/.cproject index a725efd0f..02488039a 100644 --- a/lib-remoteconfig/.cproject +++ b/lib-remoteconfig/.cproject @@ -1,138 +1,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -153,11 +21,16 @@ - - - - @@ -328,6 +206,205 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -341,31 +418,37 @@ + + + + + + - + - + + + + + + + - + - + - + - - - - - - \ No newline at end of file diff --git a/lib-remoteconfig/.settings/language.settings.xml b/lib-remoteconfig/.settings/language.settings.xml index 2b2db4557..47c7ac578 100644 --- a/lib-remoteconfig/.settings/language.settings.xml +++ b/lib-remoteconfig/.settings/language.settings.xml @@ -1,21 +1,27 @@ - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib-rgbpanel/.settings/language.settings.xml b/lib-rgbpanel/.settings/language.settings.xml index f162d6253..28ab8645d 100644 --- a/lib-rgbpanel/.settings/language.settings.xml +++ b/lib-rgbpanel/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/lib-showfile/.settings/language.settings.xml b/lib-showfile/.settings/language.settings.xml index 3ab7c0b50..b374e27cc 100644 --- a/lib-showfile/.settings/language.settings.xml +++ b/lib-showfile/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@ - + diff --git a/lib-tcnet/.settings/language.settings.xml b/lib-tcnet/.settings/language.settings.xml index 8ffba4620..2fabd17cd 100644 --- a/lib-tcnet/.settings/language.settings.xml +++ b/lib-tcnet/.settings/language.settings.xml @@ -4,8 +4,8 @@ - - + + @@ -17,7 +17,7 @@ - + diff --git a/lib-tlc59711/.settings/language.settings.xml b/lib-tlc59711/.settings/language.settings.xml index 27e543360..48afb8159 100644 --- a/lib-tlc59711/.settings/language.settings.xml +++ b/lib-tlc59711/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@ - + @@ -29,7 +29,7 @@ - + diff --git a/lib-tlc59711dmx/.cproject b/lib-tlc59711dmx/.cproject index 0a8edae22..f174baf7a 100644 --- a/lib-tlc59711dmx/.cproject +++ b/lib-tlc59711dmx/.cproject @@ -5,7 +5,6 @@ - @@ -22,14 +21,16 @@ - + - - @@ -52,7 +54,9 @@ - @@ -70,7 +74,6 @@ - @@ -87,33 +90,32 @@ - - - - @@ -132,7 +134,6 @@ - @@ -149,11 +150,11 @@ - - + + - + @@ -162,74 +163,160 @@ - - - - @@ -255,24 +342,38 @@ + + + + + - + + + + + + + + + + - + - + @@ -281,16 +382,8 @@ - - - - + - - - - - \ No newline at end of file diff --git a/lib-tlc59711dmx/.settings/language.settings.xml b/lib-tlc59711dmx/.settings/language.settings.xml index b64eec44e..e0ce03150 100644 --- a/lib-tlc59711dmx/.settings/language.settings.xml +++ b/lib-tlc59711dmx/.settings/language.settings.xml @@ -1,30 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib-usb/.settings/language.settings.xml b/lib-usb/.settings/language.settings.xml index 0017c6023..9fec115f4 100644 --- a/lib-usb/.settings/language.settings.xml +++ b/lib-usb/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -16,8 +16,11 @@ - - + + + + + diff --git a/lib-uuid/.cproject b/lib-uuid/.cproject index 3b48ea5fd..51ce1a4cf 100644 --- a/lib-uuid/.cproject +++ b/lib-uuid/.cproject @@ -107,16 +107,13 @@ - - - diff --git a/lib-uuid/.settings/language.settings.xml b/lib-uuid/.settings/language.settings.xml index 5d0d95c68..bacc0e1ec 100644 --- a/lib-uuid/.settings/language.settings.xml +++ b/lib-uuid/.settings/language.settings.xml @@ -2,20 +2,26 @@ - - - + + + + + + - - - + + + + + + \ No newline at end of file diff --git a/lib-widget/.settings/language.settings.xml b/lib-widget/.settings/language.settings.xml index d35a176ce..9fec115f4 100644 --- a/lib-widget/.settings/language.settings.xml +++ b/lib-widget/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -14,10 +14,13 @@ - - + + + + + diff --git a/lib-ws28xx/.cproject b/lib-ws28xx/.cproject index 6160d239c..e5ea36d6b 100644 --- a/lib-ws28xx/.cproject +++ b/lib-ws28xx/.cproject @@ -5,7 +5,6 @@ - @@ -14,7 +13,7 @@ - + @@ -70,7 +69,6 @@ - @@ -79,7 +77,7 @@ - + @@ -130,11 +131,11 @@ - - + + - + @@ -143,58 +144,172 @@ - - - - @@ -224,28 +339,34 @@ + + + + + + - + - + - + - + - + - + diff --git a/lib-ws28xx/.settings/language.settings.xml b/lib-ws28xx/.settings/language.settings.xml index c05c605a8..418c01870 100644 --- a/lib-ws28xx/.settings/language.settings.xml +++ b/lib-ws28xx/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,22 +17,22 @@ - + - + - - - - + + + + diff --git a/lib-ws28xxdisplay/.settings/language.settings.xml b/lib-ws28xxdisplay/.settings/language.settings.xml index b971f38c9..72d40ecd8 100644 --- a/lib-ws28xxdisplay/.settings/language.settings.xml +++ b/lib-ws28xxdisplay/.settings/language.settings.xml @@ -4,8 +4,8 @@ - - + + diff --git a/lib-ws28xxdmx/.cproject b/lib-ws28xxdmx/.cproject index 5a12c0e46..c059099b3 100644 --- a/lib-ws28xxdmx/.cproject +++ b/lib-ws28xxdmx/.cproject @@ -5,7 +5,6 @@ - @@ -14,7 +13,7 @@ - + - - + + - + @@ -210,84 +208,175 @@ - - - - @@ -317,34 +406,40 @@ - + - + - + + + + - + - + - + - + - + + + + diff --git a/lib-ws28xxdmx/.settings/language.settings.xml b/lib-ws28xxdmx/.settings/language.settings.xml index 0eff0013e..601ac1912 100644 --- a/lib-ws28xxdmx/.settings/language.settings.xml +++ b/lib-ws28xxdmx/.settings/language.settings.xml @@ -1,36 +1,39 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/linux_artnet/.settings/language.settings.xml b/linux_artnet/.settings/language.settings.xml index 523e0dd19..286dc1005 100644 --- a/linux_artnet/.settings/language.settings.xml +++ b/linux_artnet/.settings/language.settings.xml @@ -4,8 +4,8 @@ - - + + diff --git a/linux_ddp/.settings/language.settings.xml b/linux_ddp/.settings/language.settings.xml index 801d8a4da..286dc1005 100755 --- a/linux_ddp/.settings/language.settings.xml +++ b/linux_ddp/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/linux_e131/.settings/language.settings.xml b/linux_e131/.settings/language.settings.xml index aee0955b8..286dc1005 100644 --- a/linux_e131/.settings/language.settings.xml +++ b/linux_e131/.settings/language.settings.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/linux_osc/.settings/language.settings.xml b/linux_osc/.settings/language.settings.xml index 801d8a4da..286dc1005 100644 --- a/linux_osc/.settings/language.settings.xml +++ b/linux_osc/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/linux_pp/.settings/language.settings.xml b/linux_pp/.settings/language.settings.xml index 801d8a4da..286dc1005 100755 --- a/linux_pp/.settings/language.settings.xml +++ b/linux_pp/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_dmx_monitor/.cproject b/opi_dmx_monitor/.cproject index af5af6709..0f84ef46e 100644 --- a/opi_dmx_monitor/.cproject +++ b/opi_dmx_monitor/.cproject @@ -5,7 +5,6 @@ - @@ -14,7 +13,7 @@ - + + + + + + - + - + - + - + - - - - - \ No newline at end of file diff --git a/rpi_wifi_osc_dmx/.settings/language.settings.xml b/rpi_wifi_osc_dmx/.settings/language.settings.xml index 380e26f70..2409a0060 100644 --- a/rpi_wifi_osc_dmx/.settings/language.settings.xml +++ b/rpi_wifi_osc_dmx/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@ - + diff --git a/rpi_wifi_osc_monitor/.cproject b/rpi_wifi_osc_monitor/.cproject index d8e74eed7..ac6b01a60 100755 --- a/rpi_wifi_osc_monitor/.cproject +++ b/rpi_wifi_osc_monitor/.cproject @@ -26,10 +26,7 @@ - - - @@ -42,10 +39,7 @@ - - - @@ -67,10 +61,7 @@ - - - @@ -123,7 +114,6 @@ - diff --git a/rpi_wifi_osc_monitor/.settings/language.settings.xml b/rpi_wifi_osc_monitor/.settings/language.settings.xml index 538805b57..58def3b02 100755 --- a/rpi_wifi_osc_monitor/.settings/language.settings.xml +++ b/rpi_wifi_osc_monitor/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@ - + diff --git a/rpi_wifi_osc_pixel/.cproject b/rpi_wifi_osc_pixel/.cproject index 0bb88aac5..9e09d98b5 100755 --- a/rpi_wifi_osc_pixel/.cproject +++ b/rpi_wifi_osc_pixel/.cproject @@ -25,10 +25,7 @@ - - - @@ -41,10 +38,7 @@ - - - @@ -66,10 +60,7 @@ - - - @@ -121,7 +112,6 @@ - diff --git a/rpi_wifi_osc_pixel/.settings/language.settings.xml b/rpi_wifi_osc_pixel/.settings/language.settings.xml index 538805b57..8a475e28e 100755 --- a/rpi_wifi_osc_pixel/.settings/language.settings.xml +++ b/rpi_wifi_osc_pixel/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@ - + From fe71a6fffd6cbd2be10c0a28919f1629d720ee3b Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 16 Aug 2024 14:16:19 +0200 Subject: [PATCH 02/17] Removed lib-c, lib-c++ Added lib-clib - This makes it possible to use Newlib --- .gitignore | 2 - firmware-template-h3/Rules.mk | 2 +- lib-c++/.cproject | 127 ------------ lib-c++/.settings/language.settings.xml | 27 --- lib-c++/.settings/org.eclipse.cdt.core.prefs | 6 - .../org.eclipse.core.resources.prefs | 2 - lib-c++/Makefile.BCM | 6 - lib-c++/Makefile.H3 | 6 - lib-c++/README.md | 4 - lib-c/.cproject | 189 ------------------ lib-c/.project | 26 --- lib-c/.settings/language.settings.xml | 24 --- lib-c/.settings/org.eclipse.cdt.core.prefs | 6 - .../org.eclipse.core.resources.prefs | 2 - lib-c/README.md | 55 ----- lib-c/Rules.mk | 0 lib-clib/.cproject | 157 +++++++++++++++ {lib-c++ => lib-clib}/.project | 2 +- lib-clib/.settings/language.settings.xml | 15 ++ {lib-c => lib-clib}/Makefile.BCM | 2 +- {lib-c => lib-clib}/Makefile.H3 | 2 +- lib-clib/Rules.mk | 2 + {lib-c => lib-clib}/src/abort.c | 0 {lib-c => lib-clib}/src/asctime.c | 0 .../src => lib-clib/src/c++}/cxa_atexit.cpp | 2 +- {lib-c++/src => lib-clib/src/c++}/delete.cpp | 0 .../src => lib-clib/src/c++}/dso_handle.cpp | 0 .../src => lib-clib/src/c++}/impure_prt.cpp | 0 {lib-c++/src => lib-clib/src/c++}/new.cpp | 0 .../src => lib-clib/src/c++}/purecall.cpp | 0 {lib-c => lib-clib}/src/errno.c | 0 {lib-c => lib-clib}/src/gd32/assert.c | 0 {lib-c => lib-clib}/src/gd32/malloc.h | 0 .../src/gd32/time_ptp/time.cpp | 0 .../src/gd32/time_systick/time.cpp | 6 +- .../src/gd32/time_timer/time.cpp | 0 {lib-c => lib-clib}/src/gd32/uuid.cpp | 0 {lib-c => lib-clib}/src/h3/assert.c | 0 {lib-c => lib-clib}/src/h3/clock.c | 0 {lib-c => lib-clib}/src/h3/malloc.h | 0 {lib-c => lib-clib}/src/h3/time.c | 0 {lib-c => lib-clib}/src/h3/uuid.cpp | 0 {lib-c => lib-clib}/src/inet_aton.c | 0 {lib-c => lib-clib}/src/init.c | 0 {lib-c => lib-clib}/src/log.c | 0 {lib-c => lib-clib}/src/malloc.c | 0 {lib-c => lib-clib}/src/memchr.c | 0 {lib-c => lib-clib}/src/memcmp.c | 0 {lib-c => lib-clib}/src/memcpy.c | 0 {lib-c => lib-clib}/src/memmove.c | 0 {lib-c => lib-clib}/src/memset.c | 0 {lib-c => lib-clib}/src/perror.c | 0 {lib-c => lib-clib}/src/printf.c | 0 {lib-c => lib-clib}/src/putchar.c | 0 {lib-c => lib-clib}/src/puts.c | 0 {lib-c => lib-clib}/src/random.c | 0 {lib-c => lib-clib}/src/rpi/assert.c | 0 {lib-c => lib-clib}/src/rpi/malloc.h | 0 {lib-c => lib-clib}/src/strchr.c | 0 {lib-c => lib-clib}/src/strlen.c | 0 {lib-c => lib-clib}/src/strncmp.c | 0 {lib-c => lib-clib}/src/strstr.c | 0 {lib-c => lib-clib}/src/strtok.c | 0 {lib-c => lib-clib}/src/strtoul.c | 0 {lib-c => lib-clib}/src/time.cpp | 4 +- {lib-c => lib-clib}/src/uuid_internal.h | 0 {lib-c => lib-clib}/src/uuid_parse.c | 0 {lib-c => lib-clib}/src/uuid_unparse.c | 0 68 files changed, 184 insertions(+), 492 deletions(-) delete mode 100644 lib-c++/.cproject delete mode 100644 lib-c++/.settings/language.settings.xml delete mode 100644 lib-c++/.settings/org.eclipse.cdt.core.prefs delete mode 100755 lib-c++/.settings/org.eclipse.core.resources.prefs delete mode 100644 lib-c++/Makefile.BCM delete mode 100644 lib-c++/Makefile.H3 delete mode 100644 lib-c++/README.md delete mode 100644 lib-c/.cproject delete mode 100644 lib-c/.project delete mode 100644 lib-c/.settings/language.settings.xml delete mode 100644 lib-c/.settings/org.eclipse.cdt.core.prefs delete mode 100755 lib-c/.settings/org.eclipse.core.resources.prefs delete mode 100644 lib-c/README.md delete mode 100755 lib-c/Rules.mk create mode 100755 lib-clib/.cproject rename {lib-c++ => lib-clib}/.project (97%) mode change 100644 => 100755 create mode 100755 lib-clib/.settings/language.settings.xml rename {lib-c => lib-clib}/Makefile.BCM (85%) mode change 100644 => 100755 rename {lib-c => lib-clib}/Makefile.H3 (85%) mode change 100644 => 100755 create mode 100755 lib-clib/Rules.mk rename {lib-c => lib-clib}/src/abort.c (100%) rename {lib-c => lib-clib}/src/asctime.c (100%) mode change 100644 => 100755 rename {lib-c++/src => lib-clib/src/c++}/cxa_atexit.cpp (93%) rename {lib-c++/src => lib-clib/src/c++}/delete.cpp (100%) mode change 100644 => 100755 rename {lib-c++/src => lib-clib/src/c++}/dso_handle.cpp (100%) rename {lib-c++/src => lib-clib/src/c++}/impure_prt.cpp (100%) rename {lib-c++/src => lib-clib/src/c++}/new.cpp (100%) mode change 100644 => 100755 rename {lib-c++/src => lib-clib/src/c++}/purecall.cpp (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/errno.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/gd32/assert.c (100%) rename {lib-c => lib-clib}/src/gd32/malloc.h (100%) rename {lib-c => lib-clib}/src/gd32/time_ptp/time.cpp (100%) rename {lib-c => lib-clib}/src/gd32/time_systick/time.cpp (95%) rename {lib-c => lib-clib}/src/gd32/time_timer/time.cpp (100%) rename {lib-c => lib-clib}/src/gd32/uuid.cpp (100%) rename {lib-c => lib-clib}/src/h3/assert.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/h3/clock.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/h3/malloc.h (100%) rename {lib-c => lib-clib}/src/h3/time.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/h3/uuid.cpp (100%) rename {lib-c => lib-clib}/src/inet_aton.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/init.c (100%) rename {lib-c => lib-clib}/src/log.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/malloc.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/memchr.c (100%) rename {lib-c => lib-clib}/src/memcmp.c (100%) rename {lib-c => lib-clib}/src/memcpy.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/memmove.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/memset.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/perror.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/printf.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/putchar.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/puts.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/random.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/rpi/assert.c (100%) rename {lib-c => lib-clib}/src/rpi/malloc.h (100%) rename {lib-c => lib-clib}/src/strchr.c (100%) rename {lib-c => lib-clib}/src/strlen.c (100%) rename {lib-c => lib-clib}/src/strncmp.c (100%) rename {lib-c => lib-clib}/src/strstr.c (100%) rename {lib-c => lib-clib}/src/strtok.c (100%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/strtoul.c (100%) rename {lib-c => lib-clib}/src/time.cpp (98%) mode change 100644 => 100755 rename {lib-c => lib-clib}/src/uuid_internal.h (100%) rename {lib-c => lib-clib}/src/uuid_parse.c (100%) rename {lib-c => lib-clib}/src/uuid_unparse.c (100%) diff --git a/.gitignore b/.gitignore index f36fb9c0f..b045b0d1c 100644 --- a/.gitignore +++ b/.gitignore @@ -112,5 +112,3 @@ software_version_id.h /lib-nextion /lib-node /lib-showfile/Doxygen -/lib-clib -lib-network/src/emac/gd32/ptp/ntp/net_ptp.cpp diff --git a/firmware-template-h3/Rules.mk b/firmware-template-h3/Rules.mk index 7cce1f358..f7d88b30e 100644 --- a/firmware-template-h3/Rules.mk +++ b/firmware-template-h3/Rules.mk @@ -29,7 +29,7 @@ endif include ../firmware-template/libs.mk -LIBS+=c++ h3 c arm +LIBS+=h3 clib arm # Output TARGET=$(SUFFIX).img diff --git a/lib-c++/.cproject b/lib-c++/.cproject deleted file mode 100644 index 58e6a9bd7..000000000 --- a/lib-c++/.cproject +++ /dev/null @@ -1,127 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-c++/.settings/language.settings.xml b/lib-c++/.settings/language.settings.xml deleted file mode 100644 index 707f35500..000000000 --- a/lib-c++/.settings/language.settings.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-c++/.settings/org.eclipse.cdt.core.prefs b/lib-c++/.settings/org.eclipse.cdt.core.prefs deleted file mode 100644 index c8ec5df2d..000000000 --- a/lib-c++/.settings/org.eclipse.cdt.core.prefs +++ /dev/null @@ -1,6 +0,0 @@ -doxygen/doxygen_new_line_after_brief=true -doxygen/doxygen_use_brief_tag=false -doxygen/doxygen_use_javadoc_tags=true -doxygen/doxygen_use_pre_tag=false -doxygen/doxygen_use_structural_commands=false -eclipse.preferences.version=1 diff --git a/lib-c++/.settings/org.eclipse.core.resources.prefs b/lib-c++/.settings/org.eclipse.core.resources.prefs deleted file mode 100755 index 99f26c020..000000000 --- a/lib-c++/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding/=UTF-8 diff --git a/lib-c++/Makefile.BCM b/lib-c++/Makefile.BCM deleted file mode 100644 index 53a69699f..000000000 --- a/lib-c++/Makefile.BCM +++ /dev/null @@ -1,6 +0,0 @@ -# -DEFINES = NDEBUG -# -EXTRA_INCLUDES = -# -include ../firmware-template-bcm/lib/Rules.mk \ No newline at end of file diff --git a/lib-c++/Makefile.H3 b/lib-c++/Makefile.H3 deleted file mode 100644 index d9af62c4e..000000000 --- a/lib-c++/Makefile.H3 +++ /dev/null @@ -1,6 +0,0 @@ -# -DEFINES = NDEBUG -# -EXTRA_INCLUDES = -# -include ../firmware-template-h3/lib/Rules.mk \ No newline at end of file diff --git a/lib-c++/README.md b/lib-c++/README.md deleted file mode 100644 index f2e0374d1..000000000 --- a/lib-c++/README.md +++ /dev/null @@ -1,4 +0,0 @@ -## C++ library - -[http://www.orangepi-dmx.org](http://www.orangepi-dmx.org) - diff --git a/lib-c/.cproject b/lib-c/.cproject deleted file mode 100644 index a2e24d16c..000000000 --- a/lib-c/.cproject +++ /dev/null @@ -1,189 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-c/.project b/lib-c/.project deleted file mode 100644 index 0a923474b..000000000 --- a/lib-c/.project +++ /dev/null @@ -1,26 +0,0 @@ - - - lib-c - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/lib-c/.settings/language.settings.xml b/lib-c/.settings/language.settings.xml deleted file mode 100644 index db62722b8..000000000 --- a/lib-c/.settings/language.settings.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-c/.settings/org.eclipse.cdt.core.prefs b/lib-c/.settings/org.eclipse.cdt.core.prefs deleted file mode 100644 index c8ec5df2d..000000000 --- a/lib-c/.settings/org.eclipse.cdt.core.prefs +++ /dev/null @@ -1,6 +0,0 @@ -doxygen/doxygen_new_line_after_brief=true -doxygen/doxygen_use_brief_tag=false -doxygen/doxygen_use_javadoc_tags=true -doxygen/doxygen_use_pre_tag=false -doxygen/doxygen_use_structural_commands=false -eclipse.preferences.version=1 diff --git a/lib-c/.settings/org.eclipse.core.resources.prefs b/lib-c/.settings/org.eclipse.core.resources.prefs deleted file mode 100755 index 99f26c020..000000000 --- a/lib-c/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,2 +0,0 @@ -eclipse.preferences.version=1 -encoding/=UTF-8 diff --git a/lib-c/README.md b/lib-c/README.md deleted file mode 100644 index beb52ede1..000000000 --- a/lib-c/README.md +++ /dev/null @@ -1,55 +0,0 @@ -## Open source C library for standard C functions - -*assert.h* function : - - void __assert_func(const char *file, int line, const char *func, const char *failedexpr); - -*stdio.h* functions : - - int printf(const char* fmt, ...); - int vprintf(const char *fmt, va_list arp); - int sprintf(char *str, const char *fmt, ...); - int vsprintf(char *str, const char *fmt, va_list ap); - int snprintf(char *str, size_t size, const char *fmt, ...); - int vsnprintf(char *str, size_t size, const char *fmt, va_list ap); - void perror(const char *s); - char *strerror(int errnum); - -*stdlib.h* functions : - - void *malloc(size_t size); - void free(void *p); - void *calloc(size_t n, size_t size); - void *realloc(void *ptr, size_t size); - long int random(void); - void srandom(unsigned int seed); - -*time.h* functions : - - time_t time(time_t *t); - time_t mktime(struct tm *tm); - struct tm *localtime(const time_t *timep); - char *asctime(const struct tm *tm); - int clock_getres(clockid_t clockid, struct timespec *res); - int clock_gettime(clockid_t clockid, struct timespec *tp); - int clock_settime(clockid_t clockid, const struct timespec *tp); - -*sys/time.h* functions : - - int gettimeofday(struct timeval *tv, struct timezone *tz); - int settimeofday(const struct timeval *tv, const struct timezone *tz); - -*math.h* functions : - - float log2f(float); - float logf(float); - -*netinet/in.h* -*arpa/inet.h* functions : - - int inet_aton(const char *cp, struct in_addr *inp); - - -[http://www.orangepi-dmx.org](http://www.orangepi-dmx.org) - -[http://www.gd32-dmx.org](http://www.gd32-dmx.org) diff --git a/lib-c/Rules.mk b/lib-c/Rules.mk deleted file mode 100755 index e69de29bb..000000000 diff --git a/lib-clib/.cproject b/lib-clib/.cproject new file mode 100755 index 000000000..81b51ffe9 --- /dev/null +++ b/lib-clib/.cproject @@ -0,0 +1,157 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib-c++/.project b/lib-clib/.project old mode 100644 new mode 100755 similarity index 97% rename from lib-c++/.project rename to lib-clib/.project index cabc78a17..47d0f02c1 --- a/lib-c++/.project +++ b/lib-clib/.project @@ -1,6 +1,6 @@ - lib-c++ + lib-clib diff --git a/lib-clib/.settings/language.settings.xml b/lib-clib/.settings/language.settings.xml new file mode 100755 index 000000000..011bec42a --- /dev/null +++ b/lib-clib/.settings/language.settings.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/lib-c/Makefile.BCM b/lib-clib/Makefile.BCM old mode 100644 new mode 100755 similarity index 85% rename from lib-c/Makefile.BCM rename to lib-clib/Makefile.BCM index fb7148840..d3c29abc6 --- a/lib-c/Makefile.BCM +++ b/lib-clib/Makefile.BCM @@ -1,4 +1,4 @@ -DEFINES=NDEBUG +DEFINES =NDEBUG EXTRA_INCLUDES= diff --git a/lib-c/Makefile.H3 b/lib-clib/Makefile.H3 old mode 100644 new mode 100755 similarity index 85% rename from lib-c/Makefile.H3 rename to lib-clib/Makefile.H3 index c322baf43..d264a13de --- a/lib-c/Makefile.H3 +++ b/lib-clib/Makefile.H3 @@ -1,4 +1,4 @@ -DEFINES=NDEBUG +DEFINES =NDEBUG EXTRA_INCLUDES= diff --git a/lib-clib/Rules.mk b/lib-clib/Rules.mk new file mode 100755 index 000000000..821b5db7e --- /dev/null +++ b/lib-clib/Rules.mk @@ -0,0 +1,2 @@ + +EXTRA_SRCDIR+=src/c++ \ No newline at end of file diff --git a/lib-c/src/abort.c b/lib-clib/src/abort.c similarity index 100% rename from lib-c/src/abort.c rename to lib-clib/src/abort.c diff --git a/lib-c/src/asctime.c b/lib-clib/src/asctime.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/asctime.c rename to lib-clib/src/asctime.c diff --git a/lib-c++/src/cxa_atexit.cpp b/lib-clib/src/c++/cxa_atexit.cpp similarity index 93% rename from lib-c++/src/cxa_atexit.cpp rename to lib-clib/src/c++/cxa_atexit.cpp index 6294dfc4d..cae8031dc 100755 --- a/lib-c++/src/cxa_atexit.cpp +++ b/lib-clib/src/c++/cxa_atexit.cpp @@ -4,7 +4,7 @@ #include -typedef void (*exitfunc_t)(void); +typedef void (*exitfunc_t)(); static exitfunc_t atexit_funcs[32]; static size_t atexit_count = 0; diff --git a/lib-c++/src/delete.cpp b/lib-clib/src/c++/delete.cpp old mode 100644 new mode 100755 similarity index 100% rename from lib-c++/src/delete.cpp rename to lib-clib/src/c++/delete.cpp diff --git a/lib-c++/src/dso_handle.cpp b/lib-clib/src/c++/dso_handle.cpp similarity index 100% rename from lib-c++/src/dso_handle.cpp rename to lib-clib/src/c++/dso_handle.cpp diff --git a/lib-c++/src/impure_prt.cpp b/lib-clib/src/c++/impure_prt.cpp similarity index 100% rename from lib-c++/src/impure_prt.cpp rename to lib-clib/src/c++/impure_prt.cpp diff --git a/lib-c++/src/new.cpp b/lib-clib/src/c++/new.cpp old mode 100644 new mode 100755 similarity index 100% rename from lib-c++/src/new.cpp rename to lib-clib/src/c++/new.cpp diff --git a/lib-c++/src/purecall.cpp b/lib-clib/src/c++/purecall.cpp old mode 100644 new mode 100755 similarity index 100% rename from lib-c++/src/purecall.cpp rename to lib-clib/src/c++/purecall.cpp diff --git a/lib-c/src/errno.c b/lib-clib/src/errno.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/errno.c rename to lib-clib/src/errno.c diff --git a/lib-c/src/gd32/assert.c b/lib-clib/src/gd32/assert.c similarity index 100% rename from lib-c/src/gd32/assert.c rename to lib-clib/src/gd32/assert.c diff --git a/lib-c/src/gd32/malloc.h b/lib-clib/src/gd32/malloc.h similarity index 100% rename from lib-c/src/gd32/malloc.h rename to lib-clib/src/gd32/malloc.h diff --git a/lib-c/src/gd32/time_ptp/time.cpp b/lib-clib/src/gd32/time_ptp/time.cpp similarity index 100% rename from lib-c/src/gd32/time_ptp/time.cpp rename to lib-clib/src/gd32/time_ptp/time.cpp diff --git a/lib-c/src/gd32/time_systick/time.cpp b/lib-clib/src/gd32/time_systick/time.cpp similarity index 95% rename from lib-c/src/gd32/time_systick/time.cpp rename to lib-clib/src/gd32/time_systick/time.cpp index edff2a18a..024803bf2 100644 --- a/lib-c/src/gd32/time_systick/time.cpp +++ b/lib-clib/src/gd32/time_systick/time.cpp @@ -31,7 +31,7 @@ #include #include -extern volatile uint32_t s_nSysTickMillis; +extern volatile uint32_t gv_nSysTickMillis; static uint32_t nPreviousSysTickMillis; static struct timeval s_tv; @@ -45,7 +45,7 @@ extern "C" { int gettimeofday(struct timeval *tv, __attribute__((unused)) struct timezone *tz) { assert(tv != 0); - const auto nCurrentSysTickMillis = s_nSysTickMillis; + const auto nCurrentSysTickMillis = gv_nSysTickMillis; uint32_t nMillisElapsed; @@ -80,7 +80,7 @@ int settimeofday(const struct timeval *tv, __attribute__((unused)) const struct struct timeval g; gettimeofday(&g, nullptr); - nPreviousSysTickMillis = s_nSysTickMillis; + nPreviousSysTickMillis = gv_nSysTickMillis; s_tv.tv_sec = tv->tv_sec; s_tv.tv_usec = tv->tv_usec; diff --git a/lib-c/src/gd32/time_timer/time.cpp b/lib-clib/src/gd32/time_timer/time.cpp similarity index 100% rename from lib-c/src/gd32/time_timer/time.cpp rename to lib-clib/src/gd32/time_timer/time.cpp diff --git a/lib-c/src/gd32/uuid.cpp b/lib-clib/src/gd32/uuid.cpp similarity index 100% rename from lib-c/src/gd32/uuid.cpp rename to lib-clib/src/gd32/uuid.cpp diff --git a/lib-c/src/h3/assert.c b/lib-clib/src/h3/assert.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/h3/assert.c rename to lib-clib/src/h3/assert.c diff --git a/lib-c/src/h3/clock.c b/lib-clib/src/h3/clock.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/h3/clock.c rename to lib-clib/src/h3/clock.c diff --git a/lib-c/src/h3/malloc.h b/lib-clib/src/h3/malloc.h similarity index 100% rename from lib-c/src/h3/malloc.h rename to lib-clib/src/h3/malloc.h diff --git a/lib-c/src/h3/time.c b/lib-clib/src/h3/time.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/h3/time.c rename to lib-clib/src/h3/time.c diff --git a/lib-c/src/h3/uuid.cpp b/lib-clib/src/h3/uuid.cpp similarity index 100% rename from lib-c/src/h3/uuid.cpp rename to lib-clib/src/h3/uuid.cpp diff --git a/lib-c/src/inet_aton.c b/lib-clib/src/inet_aton.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/inet_aton.c rename to lib-clib/src/inet_aton.c diff --git a/lib-c/src/init.c b/lib-clib/src/init.c similarity index 100% rename from lib-c/src/init.c rename to lib-clib/src/init.c diff --git a/lib-c/src/log.c b/lib-clib/src/log.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/log.c rename to lib-clib/src/log.c diff --git a/lib-c/src/malloc.c b/lib-clib/src/malloc.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/malloc.c rename to lib-clib/src/malloc.c diff --git a/lib-c/src/memchr.c b/lib-clib/src/memchr.c similarity index 100% rename from lib-c/src/memchr.c rename to lib-clib/src/memchr.c diff --git a/lib-c/src/memcmp.c b/lib-clib/src/memcmp.c similarity index 100% rename from lib-c/src/memcmp.c rename to lib-clib/src/memcmp.c diff --git a/lib-c/src/memcpy.c b/lib-clib/src/memcpy.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/memcpy.c rename to lib-clib/src/memcpy.c diff --git a/lib-c/src/memmove.c b/lib-clib/src/memmove.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/memmove.c rename to lib-clib/src/memmove.c diff --git a/lib-c/src/memset.c b/lib-clib/src/memset.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/memset.c rename to lib-clib/src/memset.c diff --git a/lib-c/src/perror.c b/lib-clib/src/perror.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/perror.c rename to lib-clib/src/perror.c diff --git a/lib-c/src/printf.c b/lib-clib/src/printf.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/printf.c rename to lib-clib/src/printf.c diff --git a/lib-c/src/putchar.c b/lib-clib/src/putchar.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/putchar.c rename to lib-clib/src/putchar.c diff --git a/lib-c/src/puts.c b/lib-clib/src/puts.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/puts.c rename to lib-clib/src/puts.c diff --git a/lib-c/src/random.c b/lib-clib/src/random.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/random.c rename to lib-clib/src/random.c diff --git a/lib-c/src/rpi/assert.c b/lib-clib/src/rpi/assert.c similarity index 100% rename from lib-c/src/rpi/assert.c rename to lib-clib/src/rpi/assert.c diff --git a/lib-c/src/rpi/malloc.h b/lib-clib/src/rpi/malloc.h similarity index 100% rename from lib-c/src/rpi/malloc.h rename to lib-clib/src/rpi/malloc.h diff --git a/lib-c/src/strchr.c b/lib-clib/src/strchr.c similarity index 100% rename from lib-c/src/strchr.c rename to lib-clib/src/strchr.c diff --git a/lib-c/src/strlen.c b/lib-clib/src/strlen.c similarity index 100% rename from lib-c/src/strlen.c rename to lib-clib/src/strlen.c diff --git a/lib-c/src/strncmp.c b/lib-clib/src/strncmp.c similarity index 100% rename from lib-c/src/strncmp.c rename to lib-clib/src/strncmp.c diff --git a/lib-c/src/strstr.c b/lib-clib/src/strstr.c similarity index 100% rename from lib-c/src/strstr.c rename to lib-clib/src/strstr.c diff --git a/lib-c/src/strtok.c b/lib-clib/src/strtok.c old mode 100644 new mode 100755 similarity index 100% rename from lib-c/src/strtok.c rename to lib-clib/src/strtok.c diff --git a/lib-c/src/strtoul.c b/lib-clib/src/strtoul.c similarity index 100% rename from lib-c/src/strtoul.c rename to lib-clib/src/strtoul.c diff --git a/lib-c/src/time.cpp b/lib-clib/src/time.cpp old mode 100644 new mode 100755 similarity index 98% rename from lib-c/src/time.cpp rename to lib-clib/src/time.cpp index a4f587aaa..86fe621ba --- a/lib-c/src/time.cpp +++ b/lib-clib/src/time.cpp @@ -56,7 +56,7 @@ static struct tm Tm; extern "C" { struct tm *localtime(const time_t *pTime) { - if (pTime == 0) { + if (pTime == nullptr) { return nullptr; } @@ -65,7 +65,7 @@ struct tm *localtime(const time_t *pTime) { } struct tm *gmtime(const time_t *pTime) { - if (pTime == 0) { + if (pTime == nullptr) { return nullptr; } diff --git a/lib-c/src/uuid_internal.h b/lib-clib/src/uuid_internal.h similarity index 100% rename from lib-c/src/uuid_internal.h rename to lib-clib/src/uuid_internal.h diff --git a/lib-c/src/uuid_parse.c b/lib-clib/src/uuid_parse.c similarity index 100% rename from lib-c/src/uuid_parse.c rename to lib-clib/src/uuid_parse.c diff --git a/lib-c/src/uuid_unparse.c b/lib-clib/src/uuid_unparse.c similarity index 100% rename from lib-c/src/uuid_unparse.c rename to lib-clib/src/uuid_unparse.c From f8746ddf9fc5aa7b0d6e9a01dcdb73b24b019500 Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 16 Aug 2024 14:21:04 +0200 Subject: [PATCH 03/17] Major update network stack - Properly implemented RFC 3927 - Properly implemented RFC 5227 - Improved DHCP client (it is now a state-machine) --- lib-network/Makefile.Linux | 4 +- lib-network/Rules.mk | 4 +- lib-network/example/tftpfileserver.h | 2 +- lib-network/include/emac/network.h | 175 +-- lib-network/include/esp8266/network.h | 6 +- lib-network/include/ip4_address.h | 79 ++ lib-network/include/linux/network.h | 38 +- lib-network/{src/net => include}/net.h | 69 +- lib-network/include/net/acd.h | 71 ++ lib-network/include/{ => net/apps}/mdns.h | 31 +- .../include/{ => net/apps}/ntpclient.h | 8 +- .../include/{ => net/apps}/tftpdaemon.h | 9 +- lib-network/include/net/arp.h | 51 + lib-network/include/net/autoip.h | 90 ++ lib-network/include/net/dhcp.h | 139 +++ lib-network/include/net/igmp.h | 13 + lib-network/include/net/protocol/acd.h | 64 ++ lib-network/include/net/protocol/arp.h | 76 ++ .../net/protocol/autoip.h} | 45 +- lib-network/include/net/protocol/dhcp.h | 120 +++ lib-network/include/net/protocol/dns.h | 93 ++ .../net/protocol/ethernet.h} | 43 +- .../net/protocol/iana.h} | 23 +- lib-network/include/net/protocol/icmp.h | 65 ++ .../net/protocol/ieee.h} | 18 +- .../net/protocol/igmp.h} | 71 +- lib-network/include/net/protocol/ip4.h | 71 ++ lib-network/include/{ => net/protocol}/ntp.h | 8 +- lib-network/include/net/protocol/tcp.h | 62 ++ lib-network/include/net/protocol/udp.h | 56 + lib-network/include/netif.h | 168 +++ lib-network/include/network.h | 91 +- lib-network/src/emac/gd32/emac.cpp | 8 +- lib-network/src/emac/gd32/f/net.cpp | 20 +- lib-network/src/emac/gd32/h/net.cpp | 10 +- lib-network/src/emac/gd32/net_phy.cpp | 40 +- lib-network/src/emac/h3/net.cpp | 4 +- lib-network/src/emac/network.cpp | 359 +++---- .../src/emac/phy/link_handle_change.cpp | 18 +- lib-network/src/emac/phy/rtl8201f/net_phy.cpp | 8 +- lib-network/src/esp8266/network.cpp | 8 +- lib-network/src/linux/network.cpp | 73 +- lib-network/src/net/acd.cpp | 328 ++++++ lib-network/src/{ => net}/apps/mdns/mdns.cpp | 114 +- .../src/net/apps/ntp/gd32/ptp/net_ptp.cpp | 484 +++++++++ .../src/{ => net}/apps/ntp/ntpclient.cpp | 4 +- .../src/{ => net}/apps/tftp/tftpdaemon.cpp | 2 +- lib-network/src/net/arp.cpp | 535 +++++++--- lib-network/src/net/arp_cache.cpp | 168 --- lib-network/src/net/autoip.cpp | 172 +++ lib-network/src/net/dhcp.cpp | 996 +++++++++++++----- lib-network/src/net/icmp.cpp | 42 +- lib-network/src/net/igmp.cpp | 172 +-- lib-network/src/net/ip.cpp | 31 +- lib-network/src/net/net.cpp | 248 ++--- lib-network/src/net/net_chksum.cpp | 6 +- lib-network/src/net/net_memcpy.h | 4 +- lib-network/src/net/net_packets.h | 227 ---- lib-network/src/net/net_private.h | 48 +- lib-network/src/net/netif.cpp | 306 ++++++ lib-network/src/net/rfc3927.cpp | 94 -- lib-network/src/net/tcp.cpp | 63 +- lib-network/src/net/udp.cpp | 215 ++-- lib-network/src/noemac/network.cpp | 6 +- 64 files changed, 4689 insertions(+), 1987 deletions(-) create mode 100755 lib-network/include/ip4_address.h rename lib-network/{src/net => include}/net.h (54%) mode change 100644 => 100755 create mode 100755 lib-network/include/net/acd.h rename lib-network/include/{ => net/apps}/mdns.h (80%) rename lib-network/include/{ => net/apps}/ntpclient.h (97%) rename lib-network/include/{ => net/apps}/tftpdaemon.h (94%) mode change 100644 => 100755 create mode 100755 lib-network/include/net/arp.h create mode 100755 lib-network/include/net/autoip.h create mode 100755 lib-network/include/net/dhcp.h create mode 100755 lib-network/include/net/igmp.h create mode 100644 lib-network/include/net/protocol/acd.h create mode 100755 lib-network/include/net/protocol/arp.h rename lib-network/{src/net/net_timers.cpp => include/net/protocol/autoip.h} (61%) create mode 100644 lib-network/include/net/protocol/dhcp.h create mode 100644 lib-network/include/net/protocol/dns.h rename lib-network/{src/net/net_debug.h => include/net/protocol/ethernet.h} (66%) mode change 100644 => 100755 rename lib-network/{src/net/ntp_internal.h => include/net/protocol/iana.h} (65%) create mode 100755 lib-network/include/net/protocol/icmp.h rename lib-network/{src/net/tftp_internal.h => include/net/protocol/ieee.h} (76%) mode change 100644 => 100755 rename lib-network/{src/net/dhcp_internal.h => include/net/protocol/igmp.h} (54%) mode change 100644 => 100755 create mode 100755 lib-network/include/net/protocol/ip4.h rename lib-network/include/{ => net/protocol}/ntp.h (94%) create mode 100755 lib-network/include/net/protocol/tcp.h create mode 100755 lib-network/include/net/protocol/udp.h create mode 100755 lib-network/include/netif.h create mode 100755 lib-network/src/net/acd.cpp rename lib-network/src/{ => net}/apps/mdns/mdns.cpp (88%) create mode 100644 lib-network/src/net/apps/ntp/gd32/ptp/net_ptp.cpp rename lib-network/src/{ => net}/apps/ntp/ntpclient.cpp (99%) rename lib-network/src/{ => net}/apps/tftp/tftpdaemon.cpp (99%) delete mode 100644 lib-network/src/net/arp_cache.cpp create mode 100755 lib-network/src/net/autoip.cpp delete mode 100644 lib-network/src/net/net_packets.h mode change 100755 => 100644 lib-network/src/net/net_private.h create mode 100755 lib-network/src/net/netif.cpp delete mode 100644 lib-network/src/net/rfc3927.cpp diff --git a/lib-network/Makefile.Linux b/lib-network/Makefile.Linux index 1667920db..817243fa7 100644 --- a/lib-network/Makefile.Linux +++ b/lib-network/Makefile.Linux @@ -2,11 +2,11 @@ DEFINES=NDEBUG EXTRA_INCLUDES=../lib-properties/include -EXTRA_SRCDIR=src/apps/tftp +EXTRA_SRCDIR=src/net/apps/tftp ifeq ($(findstring CONFIG_NETWORK_USE_MINIMUM,$(MAKE_FLAGS)), CONFIG_NETWORK_USE_MINIMUM) else - EXTRA_SRCDIR+=src/apps/mdns src/params + EXTRA_SRCDIR+=src/net/apps/mdns src/params endif include ../firmware-template-linux/lib/Rules.mk diff --git a/lib-network/Rules.mk b/lib-network/Rules.mk index e26b6c68f..15e929df3 100644 --- a/lib-network/Rules.mk +++ b/lib-network/Rules.mk @@ -15,7 +15,7 @@ ifneq ($(MAKE_FLAGS),) endif endif ifndef COND - EXTRA_SRCDIR+=src/apps/mdns src/apps/ntp src/apps/tftp + EXTRA_SRCDIR+=src/net/apps/mdns src/net/apps/ntp src/net/apps/tftp EXTRA_SRCDIR+=src/emac src/net src/emac/phy EXTRA_SRCDIR+=src/params ifeq ($(findstring ENABLE_PHY_SWITCH,$(MAKE_FLAGS)), ENABLE_PHY_SWITCH) @@ -39,7 +39,7 @@ ifneq ($(MAKE_FLAGS),) endif endif else - EXTRA_SRCDIR+=src/apps/mdns src/apps/ntp src/apps/tftp + EXTRA_SRCDIR+=src/net/apps/mdns src/net/apps/ntp src/net/apps/tftp EXTRA_SRCDIR+=src/emac src/net EXTRA_SRCDIR+=src/emac/phy EXTRA_SRCDIR+=src/emac/phy/dp83848 src/emac/phy/lan8700 src/emac/phy/phygen src/emac/phy/rtl8201f diff --git a/lib-network/example/tftpfileserver.h b/lib-network/example/tftpfileserver.h index 458f63dda..e6cb9704e 100644 --- a/lib-network/example/tftpfileserver.h +++ b/lib-network/example/tftpfileserver.h @@ -3,7 +3,7 @@ #include -#include "tftpdaemon.h" +#include "net/apps/tftpdaemon.h" class TFTPFileServer final: public TFTPDaemon { public: diff --git a/lib-network/include/emac/network.h b/lib-network/include/emac/network.h index eee1a5675..b06ea59e6 100755 --- a/lib-network/include/emac/network.h +++ b/lib-network/include/emac/network.h @@ -35,6 +35,7 @@ #endif namespace net { +void dhcp_run(); #if defined (CONFIG_ENET_ENABLE_PTP) void ptp_run(); #endif @@ -47,7 +48,10 @@ void ptp_run(); #include "networkparams.h" -#include "../src/net/net.h" +#include "net.h" +#include "netif.h" +#include "ip4_address.h" +#include "net/dhcp.h" #include "emac/net_link_check.h" @@ -58,40 +62,33 @@ class Network { Network(); ~Network() = default; - void Start(const net::Link link); void Print(); - void Shutdown() { - network::display_emac_shutdown(); - network::mdns_shutdown(); - net_shutdown(); - } - void MacAddressCopyTo(uint8_t *pMacAddress) { - memcpy(pMacAddress, m_aNetMacaddr, network::MAC_SIZE); + memcpy(pMacAddress, net::netif_hwaddr(), NETIF_MAX_HWADDR_LEN); } - uint32_t GetSecondaryIp() const { - return m_IpInfo.secondary_ip.addr; + uint32_t GetSecondaryIp() { + return net::netif_secondary_ipaddr(); } void SetIp(uint32_t nIp); - uint32_t GetIp() const { - return m_IpInfo.ip.addr; + uint32_t GetIp() { + return net::netif_ipaddr(); } void SetNetmask(uint32_t nNetmask); - uint32_t GetNetmask() const { - return m_IpInfo.netmask.addr; + uint32_t GetNetmask() { + return net::netif_netmask(); } void SetGatewayIp(uint32_t nGatewayIp); - uint32_t GetGatewayIp() const { - return m_IpInfo.gw.addr; + uint32_t GetGatewayIp() { + return net::netif_gw(); } - uint32_t GetBroadcastIp() const { - return m_IpInfo.broadcast_ip.addr; + uint32_t GetBroadcastIp() { + return net::netif_broadcast_ipaddr(); } /* @@ -102,18 +99,19 @@ class Network { return m_IsDhcpCapable; } - bool EnableDhcp(); + void EnableDhcp(); - bool IsDhcpUsed() const { - return m_IsDhcpUsed; + bool IsDhcpUsed() { + const auto b = net::netif_dhcp(); + return b; } bool IsDhcpKnown() const { return true; } - network::dhcp::Mode GetDhcpMode() const { - if (m_IsDhcpUsed) { + network::dhcp::Mode GetDhcpMode() { + if (IsDhcpUsed()) { return network::dhcp::Mode::ACTIVE; } @@ -121,22 +119,31 @@ class Network { } /* - * Zeroconf + * Zeroconf / autoip */ + void SetZeroconf(); + bool IsZeroconfUsed() const { + return net::netif_autoip(); + } + bool IsZeroconfCapable() const { return m_IsZeroconfCapable; } - bool SetZeroconf(); - bool IsZeroconfUsed() const { - return m_IsZeroconfUsed; - } + + /* + * Host name + */ void SetHostName(const char *pHostName); const char *GetHostName() const { return m_aHostName; } + /* + * Domain name + */ + void SetDomainName(const char *pDomainName) { strncpy(m_aDomainName, pDomainName, network::DOMAINNAME_SIZE - 1); m_aDomainName[network::DOMAINNAME_SIZE - 1] = '\0'; @@ -145,32 +152,62 @@ class Network { return m_aDomainName; } + /* + * Name servers + */ + + uint32_t GetNameServer(const uint32_t nIndex) const { + if (nIndex < network::NAMESERVERS_COUNT) { + return m_nNameservers[nIndex]; + } + + return 0; + } + + uint32_t GetNameServers() const { + return network::NAMESERVERS_COUNT; + } + + const char *GetIfName() const { + return m_aIfName; + } + + uint32_t GetIfIndex() const { + return 1; + } + /* * UDP/IP */ int32_t Begin(uint16_t nPort) { - const auto nIndex = udp_begin(nPort); + const auto nIndex = net::udp_begin(nPort); assert(nIndex != -1); return nIndex; } int32_t End(uint16_t nPort) { - const auto nIndex = udp_end(nPort); + const auto nIndex = net::udp_end(nPort); assert(nIndex == 0); return nIndex; } - uint16_t RecvFrom(int32_t nHandle, void *pBuffer, uint16_t nLength, uint32_t *from_ip, uint16_t *from_port) { - return udp_recv1(nHandle, reinterpret_cast(pBuffer), nLength, from_ip, from_port); + uint32_t RecvFrom(int32_t nHandle, void *pBuffer, uint32_t nLength, uint32_t *from_ip, uint16_t *from_port) { + return net::udp_recv1(nHandle, reinterpret_cast(pBuffer), nLength, from_ip, from_port); } - uint16_t RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort) { - return udp_recv2(nHandle, reinterpret_cast(ppBuffer), pFromIp, pFromPort); + uint32_t RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort) { + return net::udp_recv2(nHandle, reinterpret_cast(ppBuffer), pFromIp, pFromPort); + } + + void SendTo(int32_t nHandle, const void *pBuffer, uint32_t nLength, uint32_t to_ip, uint16_t remote_port) { + if (__builtin_expect((GetIp() != 0), 1)) { + net::udp_send(nHandle, reinterpret_cast(pBuffer), nLength, to_ip, remote_port); + } } - void SendTo(int32_t nHandle, const void *pBuffer, uint16_t nLength, uint32_t to_ip, uint16_t remote_port) { - udp_send(nHandle, reinterpret_cast(pBuffer), nLength, to_ip, remote_port); + void SendToTimestamp(int32_t nHandle, const void *pBuffer, uint32_t nLength, uint32_t to_ip, uint16_t remote_port) { + net::udp_send_timestamp(nHandle, reinterpret_cast(pBuffer), nLength, to_ip, remote_port); } /* @@ -178,17 +215,17 @@ class Network { */ int32_t TcpBegin(const uint16_t nLocalPort) { - return tcp_begin(nLocalPort); + return net::tcp_begin(nLocalPort); } int32_t TcpEnd(const int32_t nHandle); uint16_t TcpRead(const int32_t nHandleListen, const uint8_t **ppBuffer, uint32_t &HandleConnection) { - return tcp_read(nHandleListen, ppBuffer, HandleConnection); + return net::tcp_read(nHandleListen, ppBuffer, HandleConnection); } void TcpWrite(const int32_t nHandleListen, const uint8_t *pBuffer, uint16_t nLength, const uint32_t HandleConnection) { - tcp_write(nHandleListen, pBuffer, nLength, HandleConnection); + net::tcp_write(nHandleListen, pBuffer, nLength, HandleConnection); } /* @@ -196,15 +233,17 @@ class Network { */ void JoinGroup([[maybe_unused]] int32_t nHandle, uint32_t nIp) { - igmp_join(nIp); + net::igmp_join(nIp); } void LeaveGroup([[maybe_unused]] int32_t nHandle, uint32_t nIp) { - igmp_leave(nIp); + net::igmp_leave(nIp); } - void SetQueuedStaticIp(uint32_t nLocalIp = 0, uint32_t nNetmask = 0); - void SetQueuedDhcp() { + void SetQueuedStaticIp(const uint32_t nStaticIp, const uint32_t nNetmask); + void SetQueuedDefaultRoute(const uint32_t nGatewayIp); + void SetQueuedDhcp(const network::dhcp::Mode mode) { + m_QueuedConfig.mode = mode; m_QueuedConfig.nMask |= QueuedConfig::DHCP; } void SetQueuedZeroconf() { @@ -213,15 +252,15 @@ class Network { bool ApplyQueuedConfig(); - uint32_t GetNetmaskCIDR() const { - return static_cast(__builtin_popcount(m_IpInfo.netmask.addr)); + uint32_t GetNetmaskCIDR() { + return static_cast(__builtin_popcount(GetNetmask())); } char GetAddressingMode() { - if (Network::Get()->IsZeroconfUsed()) { + if (IsZeroconfUsed()) { return 'Z'; - } else if (Network::Get()->IsDhcpKnown()) { - if (Network::Get()->IsDhcpUsed()) { + } else if (IsDhcpKnown()) { + if (IsDhcpUsed()) { return 'D'; } else { return 'S'; @@ -231,20 +270,12 @@ class Network { return 'U'; } - const char *GetIfName() const { - return m_aIfName; - } - - uint32_t GetIfIndex() const { - return m_nIfIndex; - } - - bool IsValidIp(uint32_t nIp) { - return (m_IpInfo.ip.addr & m_IpInfo.netmask.addr) == (nIp & m_IpInfo.netmask.addr); + bool IsValidIp(const uint32_t nIp) { + return (GetIp() & GetNetmask()) == (nIp & GetNetmask()); } void Run() { - net_handle(); + net::net_handle(); #if defined (CONFIG_ENET_ENABLE_PTP) net::ptp_run(); #endif @@ -258,6 +289,7 @@ class Network { net::link_handle_change(link_state); } #endif + net::dhcp_run(); } static Network *Get() { @@ -267,28 +299,25 @@ class Network { private: net::Link s_lastState { net::Link::STATE_DOWN }; bool m_IsDhcpCapable { true }; - bool m_IsDhcpUsed { false }; bool m_IsZeroconfCapable { true }; - bool m_IsZeroconfUsed { false }; - uint32_t m_nIfIndex { 1 }; - uint8_t m_nDhcpRetryTime { 0 }; - - struct IpInfo m_IpInfo; + char m_aIfName[IFNAMSIZ]; char m_aHostName[network::HOSTNAME_SIZE]; char m_aDomainName[network::DOMAINNAME_SIZE]; - uint8_t m_aNetMacaddr[network::MAC_SIZE]; - char m_aIfName[IFNAMSIZ]; + uint32_t m_nNameservers[network::NAMESERVERS_COUNT]; struct QueuedConfig { static constexpr uint32_t NONE = 0; static constexpr uint32_t STATIC_IP = (1U << 0); - static constexpr uint32_t NET_MASK = (1U << 1); - static constexpr uint32_t DHCP = (1U << 2); - static constexpr uint32_t ZEROCONF = (1U << 3); + static constexpr uint32_t NETMASK = (1U << 1); + static constexpr uint32_t GW = (1U << 2); + static constexpr uint32_t DHCP = (1U << 3); + static constexpr uint32_t ZEROCONF = (1U << 4); uint32_t nMask = QueuedConfig::NONE; - uint32_t nLocalIp = 0; - uint32_t nNetmask = 0; + uint32_t nStaticIp; + uint32_t nNetmask; + uint32_t nGateway; + network::dhcp::Mode mode; }; QueuedConfig m_QueuedConfig; diff --git a/lib-network/include/esp8266/network.h b/lib-network/include/esp8266/network.h index 646f45f60..4fb001d4c 100644 --- a/lib-network/include/esp8266/network.h +++ b/lib-network/include/esp8266/network.h @@ -89,9 +89,9 @@ class Network { // Not supported } - uint16_t RecvFrom(int32_t nHandle, void *pBuffer, uint16_t nLength, uint32_t *pFromIp, uint16_t *pFromPort); - uint16_t RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort); - void SendTo(int32_t nHandle, const void *pBuffer, uint16_t nLength, uint32_t nToIp, uint16_t nRemotePort) ; + uint32_t RecvFrom(int32_t nHandle, void *pBuffer, uint32_t nLength, uint32_t *pFromIp, uint16_t *pFromPort); + uint32_t RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort); + void SendTo(int32_t nHandle, const void *pBuffer, uint32_t nLength, uint32_t nToIp, uint16_t nRemotePort) ; void Print() { } diff --git a/lib-network/include/ip4_address.h b/lib-network/include/ip4_address.h new file mode 100755 index 000000000..1ba355bd1 --- /dev/null +++ b/lib-network/include/ip4_address.h @@ -0,0 +1,79 @@ +/* + * ip4_address.h + */ + +#ifndef IP4_ADDRESS_H_ +#define IP4_ADDRESS_H_ + +#include + +#define IP2STR(addr) static_cast(addr & 0xFF), static_cast((addr >> 8) & 0xFF), static_cast((addr >> 16) & 0xFF), static_cast((addr >> 24) & 0xFF) +#define IPSTR "%d.%d.%d.%d" + +#define MAC2STR(mac) static_cast(mac[0]),static_cast(mac[1]),static_cast(mac[2]),static_cast(mac[3]), static_cast(mac[4]), static_cast(mac[5]) +#define MACSTR "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" + +namespace network { +static constexpr uint32_t STORE = 96; ///< Configuration store in bytes +static constexpr uint32_t MAC_SIZE = 6; +static constexpr uint32_t HOSTNAME_SIZE = 64; ///< Including a terminating null byte. +static constexpr uint32_t DOMAINNAME_SIZE = 64; ///< Including a terminating null byte. +static constexpr uint32_t NAMESERVERS_COUNT = 3; +static constexpr uint32_t IP4_ANY = 0x00000000; +static constexpr uint32_t IP4_BROADCAST = 0xffffffff; + +static constexpr uint32_t convert_to_uint(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) { + return static_cast(a) | + static_cast(b) << 8 | + static_cast(c) << 16 | + static_cast(d) << 24; +} + +inline bool is_netmask_valid(uint32_t nNetMask) { + if (nNetMask == 0) { + return false; + } + nNetMask = __builtin_bswap32(nNetMask); + return !(nNetMask & (~nNetMask >> 1)); + +} +/** + * The private address ranges are defined in RFC1918. + */ +inline bool is_private_ip(const uint32_t nIp) { + const uint8_t n = (nIp >> 8) & 0xFF; + + switch (nIp & 0xFF) { + case 10: + return true; + break; + case 172: + return (n >= 16) && (n < 32); + case 192: + return n == 168; + default: + break; + } + + return false; +} + +inline bool is_linklocal_ip(const uint32_t nIp) { + return (nIp & 0xFFFF) == 0xA9FE; +} + +inline bool is_multicast_ip(const uint32_t nIp) { + return (nIp & 0xF0) == 0xE0; +} + +inline uint32_t cidr_to_netmask(const uint8_t nCIDR) { + if (nCIDR != 0) { + const auto nNetmask = __builtin_bswap32(static_cast(~0x0) << (32 - nCIDR)); + return nNetmask; + } + + return 0; +} +} // namespace network + +#endif /* IP4_ADDRESS_H_ */ diff --git a/lib-network/include/linux/network.h b/lib-network/include/linux/network.h index b2a0a6118..331325f30 100644 --- a/lib-network/include/linux/network.h +++ b/lib-network/include/linux/network.h @@ -54,9 +54,9 @@ class Network { void JoinGroup(int32_t nHandle, uint32_t nIp); void LeaveGroup(int32_t nHandle, uint32_t nIp); - uint16_t RecvFrom(int32_t nHandle, void *pBuffer, uint16_t nLength, uint32_t *pFromIp, uint16_t *pFromPort); - uint16_t RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort); - void SendTo(int32_t nHandle, const void *pBuffer, uint16_t nLength, uint32_t nToIp, uint16_t nRemotePort); + uint32_t RecvFrom(int32_t nHandle, void *pBuffer, uint32_t nLength, uint32_t *pFromIp, uint16_t *pFromPort); + uint32_t RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort); + void SendTo(int32_t nHandle, const void *pBuffer, uint32_t nLength, uint32_t nToIp, uint16_t nRemotePort); void SetIp(uint32_t nIp); void SetNetmask(uint32_t nNetmask); @@ -69,6 +69,18 @@ class Network { m_aDomainName[network::DOMAINNAME_SIZE - 1] = '\0'; } + uint32_t GetNameServer(const uint32_t nIndex) const { + if (nIndex < network::NAMESERVERS_COUNT) { + return m_nNameservers[nIndex]; + } + + return 0; + } + + uint32_t GetNameServers() const { + return network::NAMESERVERS_COUNT; + } + uint32_t GetSecondaryIp() const { return m_nLocalIp; } @@ -92,8 +104,10 @@ class Network { return false; } - void SetQueuedStaticIp(uint32_t nLocalIp = 0, uint32_t nNetmask = 0); - void SetQueuedDhcp() { + void SetQueuedStaticIp(const uint32_t nStaticIp, const uint32_t nNetmask); + void SetQueuedDefaultRoute(const uint32_t nGatewayIp); + void SetQueuedDhcp(const network::dhcp::Mode mode) { + m_QueuedConfig.mode = mode; m_QueuedConfig.nMask |= QueuedConfig::DHCP; } void SetQueuedZeroconf() { @@ -225,18 +239,22 @@ class Network { char m_aHostName[network::HOSTNAME_SIZE]; char m_aDomainName[network::DOMAINNAME_SIZE]; + uint32_t m_nNameservers[network::NAMESERVERS_COUNT]; uint8_t m_aNetMacaddr[network::MAC_SIZE]; char m_aIfName[IFNAMSIZ]; struct QueuedConfig { static constexpr uint32_t NONE = 0; static constexpr uint32_t STATIC_IP = (1U << 0); - static constexpr uint32_t NET_MASK = (1U << 1); - static constexpr uint32_t DHCP = (1U << 2); - static constexpr uint32_t ZEROCONF = (1U << 3); + static constexpr uint32_t NETMASK = (1U << 1); + static constexpr uint32_t GW = (1U << 2); + static constexpr uint32_t DHCP = (1U << 3); + static constexpr uint32_t ZEROCONF = (1U << 4); uint32_t nMask = QueuedConfig::NONE; - uint32_t nLocalIp = 0; - uint32_t nNetmask = 0; + uint32_t nStaticIp; + uint32_t nNetmask; + uint32_t nGateway; + network::dhcp::Mode mode; }; QueuedConfig m_QueuedConfig; diff --git a/lib-network/src/net/net.h b/lib-network/include/net.h old mode 100644 new mode 100755 similarity index 54% rename from lib-network/src/net/net.h rename to lib-network/include/net.h index 47a278614..d9b688aec --- a/lib-network/src/net/net.h +++ b/lib-network/include/net.h @@ -2,7 +2,7 @@ * @file net.h * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,40 +28,43 @@ #include -struct ip_addr { - uint32_t addr; -}; +#include "netif.h" +#include "emac/phy.h" +#include "net/dhcp.h" +#include "net/protocol/dhcp.h" -typedef struct ip_addr ip_addr_t; +#include "debug.h" -struct IpInfo { - struct ip_addr ip; - struct ip_addr netmask; - struct ip_addr gw; - struct ip_addr broadcast_ip; - struct ip_addr secondary_ip; -}; +namespace network { +void mdns_shutdown(); +} // namespace network -#define IP_BROADCAST (0xFFFFFFFF) -#define HOST_NAME_MAX 64 /* including a terminating null byte. */ +namespace net { +void tcp_shutdown(); +void igmp_shutdown(); +} -void net_init(const uint8_t *const, struct IpInfo *, const char *, bool *, bool *); -void net_shutdown(); +namespace net { +void net_init(net::Link link, ip4_addr_t ipaddr, ip4_addr_t netmask, ip4_addr_t gw, bool &bUseDhcp); +void net_set_primary_ip(const ip4_addr_t ipaddr); +void net_set_secondary_ip(); void net_handle(); -void net_set_ip(struct IpInfo *); -void net_set_netmask(struct IpInfo *); -void net_set_gw(struct IpInfo *); -bool net_set_zeroconf(struct IpInfo *); - -bool net_set_dhcp(struct IpInfo *, const char *const, bool *); -void net_dhcp_release(); +inline void net_link_down() { + network::mdns_shutdown(); +#if defined (ENABLE_HTTPD) + tcp_shutdown(); +#endif + igmp_shutdown(); + dhcp_release_and_stop(); +} int udp_begin(uint16_t); int udp_end(uint16_t); -uint16_t udp_recv1(int, uint8_t *, uint16_t, uint32_t *, uint16_t *); -uint16_t udp_recv2(int, const uint8_t **, uint32_t *, uint16_t *); -int udp_send(int, const uint8_t *, uint16_t, uint32_t, uint16_t); +uint32_t udp_recv1(int, uint8_t *, uint32_t, uint32_t *, uint16_t *); +uint32_t udp_recv2(int, const uint8_t **, uint32_t *, uint16_t *); +void udp_send(int, const uint8_t *, uint32_t, uint32_t, uint16_t); +void udp_send_timestamp(int, const uint8_t *, uint32_t, uint32_t, uint16_t); void igmp_join(uint32_t); void igmp_leave(uint32_t); @@ -70,4 +73,18 @@ int tcp_begin(const uint16_t); uint16_t tcp_read(const int32_t, const uint8_t **, uint32_t &); void tcp_write(const int32_t, const uint8_t *, uint16_t, const uint32_t); +/** + * Must be provided by the application + */ +void display_emac_config(); +void display_emac_start(); +void display_emac_status(const bool); +void display_emac_shutdown(); +void display_ip(); +void display_netmask(); +void display_gateway(); +void display_hostname(); +void display_dhcp_status(net::dhcp::State); +} // namespace het + #endif /* NET_H_ */ diff --git a/lib-network/include/net/acd.h b/lib-network/include/net/acd.h new file mode 100755 index 000000000..f4a8d4fe7 --- /dev/null +++ b/lib-network/include/net/acd.h @@ -0,0 +1,71 @@ +/** + * @file acd.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* This code is inspired by: lwIP + * https://savannah.nongnu.org/projects/lwip/ + */ + +#ifndef NET_ACD_H_ +#define NET_ACD_H_ + +#include + +#include "netif.h" +#include "arp.h" +#include "net/protocol/acd.h" +#include "ip4_address.h" + +/** + * https://datatracker.ietf.org/doc/html/rfc5227.html + * IPv4 Address Conflict Detection + */ + +namespace net { +typedef void (*acd_conflict_callback_t)(acd::Callback callback); + +namespace acd { +struct Acd { + ip4_addr_t ipaddr; + State state; + uint8_t sent_num; + uint8_t lastconflict; + uint8_t num_conflicts; + acd_conflict_callback_t acd_conflict_callback; + uint16_t ttw; +}; +} // namespace acd + +void acd_add(struct acd::Acd *, acd_conflict_callback_t); +void acd_remove(struct acd::Acd *); + +void acd_start(struct acd::Acd *, const ip4_addr_t ipaddr); +void acd_stop(struct acd::Acd *); + +void acd_arp_reply(struct t_arp *); + +void acd_network_changed_link_down(); +void acd_netif_ip_addr_changed(const ip4_addr_t nOldIpAddress, const ip4_addr_t nNewIpAddress); +} // namespace net + +#endif /* NET_ACD_H_ */ diff --git a/lib-network/include/mdns.h b/lib-network/include/net/apps/mdns.h similarity index 80% rename from lib-network/include/mdns.h rename to lib-network/include/net/apps/mdns.h index d57d8c310..4cf05e60c 100755 --- a/lib-network/include/mdns.h +++ b/lib-network/include/net/apps/mdns.h @@ -2,7 +2,7 @@ * @file mdns.h * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,12 +23,13 @@ * THE SOFTWARE. */ -#ifndef MDNS_H_ -#define MDNS_H_ +#ifndef NET_APPS_MDNS_H_ +#define NET_APPS_MDNS_H_ #include #include "network.h" +#include "net/protocol/dns.h" #include "../config/apps_config.h" @@ -37,16 +38,6 @@ enum class Services { CONFIG, TFTP, HTTP, RDMNET_LLRP, NTP, MIDI, OSC, DDP, PP, LAST_NOT_USED }; -struct Header { - uint16_t xid; - uint8_t nFlag1; - uint8_t nFlag2; - uint16_t nQueryCount; - uint16_t nAnswerCount; - uint16_t nAuthorityCount; - uint16_t nAdditionalCount; -} __attribute__((__packed__)); - struct ServiceRecord { char *pName; char *pTextContent; @@ -71,18 +62,18 @@ class MDNS { void Run() { s_nBytesReceived = Network::Get()->RecvFrom(s_nHandle, const_cast(reinterpret_cast(&s_pReceiveBuffer)), &s_nRemoteIp, &s_nRemotePort); - if (__builtin_expect((s_nBytesReceived < sizeof(struct mdns::Header)), 1)) { + if (__builtin_expect((s_nBytesReceived < sizeof(struct net::dns::Header)), 1)) { return; } - const auto *const pHeader = reinterpret_cast(s_pReceiveBuffer); + const auto *const pHeader = reinterpret_cast(s_pReceiveBuffer); const auto nFlag1 = pHeader->nFlag1; if ((nFlag1 >> 3) & 0xF) { return; } - HandleQuestions(__builtin_bswap16(pHeader->nQueryCount)); + HandleQuestions(static_cast(__builtin_bswap16(pHeader->nQueryCount))); } static MDNS *Get() { @@ -94,16 +85,16 @@ class MDNS { void HandleQuestions(const uint32_t nQuestions); void SendAnswerLocalIpAddress(const uint16_t nTransActionID, const uint32_t nTTL); void SendMessage(mdns::ServiceRecord const& serviceRecord, const uint16_t nTransActionID, const uint32_t nTTL); - void SendTo(const uint16_t nLength); + void SendTo(const uint32_t nLength); private: static int32_t s_nHandle; static uint32_t s_nRemoteIp; - static uint16_t s_nRemotePort; - static uint16_t s_nBytesReceived; + static uint32_t s_nBytesReceived; static uint8_t *s_pReceiveBuffer; + static uint16_t s_nRemotePort; static MDNS *s_pThis; }; -#endif /* MDNS_H_ */ +#endif /* NET_APPS_MDNS_H_ */ diff --git a/lib-network/include/ntpclient.h b/lib-network/include/net/apps/ntpclient.h similarity index 97% rename from lib-network/include/ntpclient.h rename to lib-network/include/net/apps/ntpclient.h index 73a9f0248..1a1d526af 100755 --- a/lib-network/include/ntpclient.h +++ b/lib-network/include/net/apps/ntpclient.h @@ -23,14 +23,14 @@ * THE SOFTWARE. */ -#ifndef NTPCLIENT_H_ -#define NTPCLIENT_H_ +#ifndef NET_APPS_NTPCLIENT_H_ +#define NET_APPS_NTPCLIENT_H_ #include #include #include -#include "ntp.h" +#include "net/protocol/ntp.h" #include "hardware.h" #include "debug.h" @@ -144,4 +144,4 @@ class NtpClient { static NtpClient *s_pThis; }; -#endif /* NTPCLIENT_H_ */ +#endif /* NET_APPS_NTPCLIENT_H_ */ diff --git a/lib-network/include/tftpdaemon.h b/lib-network/include/net/apps/tftpdaemon.h old mode 100644 new mode 100755 similarity index 94% rename from lib-network/include/tftpdaemon.h rename to lib-network/include/net/apps/tftpdaemon.h index 1f071e367..2c194b13c --- a/lib-network/include/tftpdaemon.h +++ b/lib-network/include/net/apps/tftpdaemon.h @@ -23,10 +23,11 @@ * THE SOFTWARE. */ -#ifndef TFTPDAEMON_H_ -#define TFTPDAEMON_H_ +#ifndef NET_APPS_TFTPDAEMON_H_ +#define NET_APPS_TFTPDAEMON_H_ #include +#include namespace tftp { enum class Mode { @@ -72,7 +73,7 @@ class TFTPDaemon { uint32_t m_nFromIp { 0 }; uint32_t m_nLength { 0 }; uint32_t m_nDataLength { 0 }; - uint16_t m_nPacketLength { 0 }; + uint32_t m_nPacketLength { 0 }; uint16_t m_nFromPort { 0 }; uint16_t m_nBlockNumber { 0 }; bool m_bIsLastBlock { false }; @@ -85,4 +86,4 @@ class TFTPDaemon { static TFTPDaemon *s_pThis; }; -#endif /* TFTPDAEMON_H_ */ +#endif /* NET_APPS_TFTPDAEMON_H_ */ diff --git a/lib-network/include/net/arp.h b/lib-network/include/net/arp.h new file mode 100755 index 000000000..cddb33d9c --- /dev/null +++ b/lib-network/include/net/arp.h @@ -0,0 +1,51 @@ +/** + * @file arp_private.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef ARP_PRIVATE_H_ +#define ARP_PRIVATE_H_ + +#include "netif.h" +#include "net/protocol/ip4.h" +#include "net/protocol/arp.h" +#include "net/protocol/udp.h" + +namespace net { +namespace arp { +enum class Flags { + FLAG_INSERT, FLAG_UPDATE +}; +} // namespace arp + +void arp_init(); +void arp_handle(struct t_arp *); +void arp_send(struct t_udp *, const uint32_t, const uint32_t); +#if defined CONFIG_ENET_ENABLE_PTP +void arp_send_timestamp(struct t_udp *, const uint32_t, const uint32_t); +#endif +void arp_acd_probe(const ip4_addr_t ipaddr); +void arp_acd_send_announcement(const ip4_addr_t ipaddr); +} // namespace net + +#endif /* ARP_PRIVATE_H_ */ diff --git a/lib-network/include/net/autoip.h b/lib-network/include/net/autoip.h new file mode 100755 index 000000000..332fd7df6 --- /dev/null +++ b/lib-network/include/net/autoip.h @@ -0,0 +1,90 @@ +/** + * @file autoip.h + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* This code is inspired by the lwIP TCP/IP stack. + * https://savannah.nongnu.org/projects/lwip/ + */ +/** + * The autoip.cpp aims to be conform to RFC 3927. + * https://datatracker.ietf.org/doc/html/rfc3927 + * Dynamic Configuration of IPv4 Link-Local Addresses + */ + +#ifndef NET_AUTOIP_H_ +#define NET_AUTOIP_H_ + +#include + +#include "netif.h" +#include "net/acd.h" +#include "net/protocol/autoip.h" + +#include "debug.h" + +namespace net { +namespace autoip { +struct Autoip { + ip4_addr_t llipaddr; + State state; + uint8_t tried_llipaddr; + acd::Acd acd; +}; +} // namespace autoip + +void autoip_start(); +void autoip_stop(); + +inline bool autoip_supplied_address() { + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + + return (autoip != nullptr) + && (globals::netif_default.ip.addr == autoip->llipaddr.addr) + && (autoip->state == autoip::State::AUTOIP_STATE_BOUND); +} + +inline void autoip_network_changed_link_up() { + DEBUG_ENTRY + + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + + if ((autoip != nullptr) && (autoip->state != autoip::State::AUTOIP_STATE_OFF)) { + acd_start(&autoip->acd, autoip->llipaddr); + } + + DEBUG_EXIT +} + +inline void autoip_network_changed_link_down() { + DEBUG_EXIT + + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + + if ((autoip != nullptr) && (autoip->state != autoip::State::AUTOIP_STATE_OFF)) { + autoip_stop(); + } + + DEBUG_EXIT +} +} // namespace net + +#endif /* NET_AUTOIP_H_ */ diff --git a/lib-network/include/net/dhcp.h b/lib-network/include/net/dhcp.h new file mode 100755 index 000000000..1c6f1670d --- /dev/null +++ b/lib-network/include/net/dhcp.h @@ -0,0 +1,139 @@ +/** + * @file dhcp.h + * + */ +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_DHCP_H_ +#define NET_DHCP_H_ + +#include +#include + +#include + +#include "netif.h" +#include "acd.h" +#include "ip4_address.h" +#include "net/protocol/dhcp.h" +#include "net/protocol/iana.h" + +#include "debug.h" + +namespace net { +namespace dhcp { +static constexpr uint32_t DHCP_COARSE_TIMER_SECS = 60; +/** period (in milliseconds) of the application calling dhcp_coarse_tmr() */ +static constexpr uint32_t DHCP_COARSE_TIMER_MSECS = (DHCP_COARSE_TIMER_SECS * 1000UL); +/** period (in milliseconds) of the application calling dhcp_fine_tmr() */ +static constexpr uint32_t DHCP_FINE_TIMER_MSECS = 500; + +#define DHCP_FLAG_SUBNET_MASK_GIVEN 0x01 +#define DHCP_AUTOIP_COOP_TRIES 9 + +enum class AutoipCoopState { + DHCP_AUTOIP_COOP_STATE_OFF = 0, + DHCP_AUTOIP_COOP_STATE_ON = 1 +}; + +typedef uint16_t dhcp_timeout_t; + +struct Dhcp { + int32_t nHandle; + uint32_t xid; + State state; + uint8_t tries; + uint8_t flags; + + dhcp_timeout_t request_timeout; /* #ticks with period DHCP_FINE_TIMER_SECS for request timeout */ + dhcp_timeout_t t1_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for renewal time */ + dhcp_timeout_t t2_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for rebind time */ + dhcp_timeout_t t1_renew_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next renew try */ + dhcp_timeout_t t2_rebind_time; /* #ticks with period DHCP_COARSE_TIMER_SECS until next rebind try */ + dhcp_timeout_t lease_used; /* #ticks with period DHCP_COARSE_TIMER_SECS since last received DHCP ack */ + dhcp_timeout_t t0_timeout; /* #ticks with period DHCP_COARSE_TIMER_SECS for lease time */ + + ip4_addr_t server_ip_addr; + + struct Offered { + ip4_addr_t offered_ip_addr; + ip4_addr_t offered_sn_mask; + ip4_addr_t offered_gw_addr; + + uint32_t offered_t0_lease; /* lease period (in seconds) */ + uint32_t offered_t1_renew; /* recommended renew time (usually 50% of lease period) */ + uint32_t offered_t2_rebind; /* recommended rebind time (usually 87.5 of lease period) */ + }; + + Offered offered; + + acd::Acd acd; +}; +} // namespace dhcp + +bool dhcp_start(); +bool dhcp_renew(); +bool dhcp_release(); +void dhcp_stop(); +void dhcp_release_and_stop(); +void dhcp_inform(); +void dhcp_network_changed_link_up(); + +uint32_t udp_recv2(int, const uint8_t **, uint32_t *, uint16_t *); +void dhcp_process(const dhcp::Message *const, const uint32_t nSize); + +inline void dhcp_run() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + if (dhcp == nullptr) { + return; + } + + uint8_t *pResponse; + uint32_t nFromIp; + uint16_t nFromPort; + + const auto nSize = udp_recv2(dhcp->nHandle, const_cast(&pResponse), &nFromIp, &nFromPort); + + if (__builtin_expect((nSize > 0), 0)) { + if (nFromPort == net::iana::IANA_PORT_DHCP_SERVER) { + const auto *const p = reinterpret_cast(pResponse); + + if (p->xid != dhcp->xid) { + DEBUG_PRINTF("pDhcpMessage->xid=%u, dhcp->xid=%u", p->xid, dhcp->xid); + return; + } + + dhcp_process(p, nSize); + } + } +} + +inline bool dhcp_supplied_address() { + const auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + if ((dhcp != nullptr)) { + return (dhcp->state == dhcp::State::STATE_BOUND) || (dhcp->state == dhcp::State::STATE_RENEWING) || (dhcp->state == dhcp::State::STATE_REBINDING); + } + return false; +} +} // namespace net + +#endif /* NET_DHCP_H_ */ diff --git a/lib-network/include/net/igmp.h b/lib-network/include/net/igmp.h new file mode 100755 index 000000000..252cce6c6 --- /dev/null +++ b/lib-network/include/net/igmp.h @@ -0,0 +1,13 @@ +/* + * igmp.h + */ + +#ifndef NET_IGMP_H_ +#define NET_IGMP_H_ + +namespace net { +//TODO implement +void igmp_report_groups(); +} // namespace net + +#endif /* NET_IGMP_H_ */ diff --git a/lib-network/include/net/protocol/acd.h b/lib-network/include/net/protocol/acd.h new file mode 100644 index 000000000..035b3e5d4 --- /dev/null +++ b/lib-network/include/net/protocol/acd.h @@ -0,0 +1,64 @@ +/** + * @file acd.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_ACD_H_ +#define NET_PROTOCOL_ACD_H_ + +#include + +namespace net::acd { +/** + * RFC 5227 and RFC 3927 Constants + */ +#define PROBE_WAIT 1 ///< second (initial random delay) +#define PROBE_MIN 1 ///< second (minimum delay till repeated probe) +#define PROBE_MAX 2 ///< seconds (maximum delay till repeated probe) +#define PROBE_NUM 3 ///< (number of probe packets) +#define ANNOUNCE_NUM 2 ///< (number of announcement packets) +#define ANNOUNCE_INTERVAL 2 ///< seconds (time between announcement packets) +#define ANNOUNCE_WAIT 2 ///< seconds (delay before announcing) +#define MAX_CONFLICTS 10 ///< (max conflicts before rate limiting) +#define RATE_LIMIT_INTERVAL 60 ///< seconds (delay between successive attempts) +#define DEFEND_INTERVAL 10 ///< seconds (minimum interval between defensive ARPs) + +enum class State: uint8_t { + ACD_STATE_OFF, + ACD_STATE_PROBE_WAIT, + ACD_STATE_PROBING, + ACD_STATE_ANNOUNCE_WAIT, + ACD_STATE_ANNOUNCING, + ACD_STATE_ONGOING, + ACD_STATE_PASSIVE_ONGOING, + ACD_STATE_RATE_LIMIT +}; + +enum class Callback { + ACD_IP_OK, ///< IP address is good, no conflicts found in checking state + ACD_RESTART_CLIENT, ///< Conflict found -> the client should try again + ACD_DECLINE ///< Decline the received IP address (rate limiting) +}; +} // namespace acd + +#endif /* NET_PROTOCOL_ACD_H_ */ diff --git a/lib-network/include/net/protocol/arp.h b/lib-network/include/net/protocol/arp.h new file mode 100755 index 000000000..3d6b6b1ca --- /dev/null +++ b/lib-network/include/net/protocol/arp.h @@ -0,0 +1,76 @@ +/** + * @file arp.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_ARP_H_ +#define NET_PROTOCOL_ARP_H_ + +#include "ip4_address.h" +#include "net/protocol/ethernet.h" +#include "net/protocol/ieee.h" + +#if !defined (PACKED) +# define PACKED __attribute__((packed)) +#endif + +enum ARP_HARDWARE_TYPE { + ARP_HWTYPE_ETHERNET = 1 +}; + +enum ARP_PROTOCOL_TYPE { + ARP_PRTYPE_IPv4 = ETHER_TYPE_IPv4 +}; + +enum ARP_HARDWARE { + ARP_HARDWARE_SIZE = ETH_ADDR_LEN +}; + +enum ARP_PROTOCOL { + ARP_PROTOCOL_SIZE = IPv4_ADDR_LEN +}; + +enum ARP_OPCODE { + ARP_OPCODE_RQST = 1, + ARP_OPCODE_REPLY = 2 +}; + +struct arp_packet { + uint16_t hardware_type; /* 2 */ + uint16_t protocol_type; /* 4 */ + uint8_t hardware_size; /* 5 */ + uint8_t protocol_size; /* 6 */ + uint16_t opcode; /* 8 */ + uint8_t sender_mac[ETH_ADDR_LEN];/*14 */ + uint8_t sender_ip[IPv4_ADDR_LEN];/* 18 */ + uint8_t target_mac[ETH_ADDR_LEN];/*24 */ + uint8_t target_ip[IPv4_ADDR_LEN];/* 28 */ + uint8_t padding[18]; /* 46 */ /* +14 = 60 */ +} PACKED; + +struct t_arp { + struct ether_header ether; + struct arp_packet arp; +} PACKED; + +#endif /* NET_PROTOCOL_ARP_H_ */ diff --git a/lib-network/src/net/net_timers.cpp b/lib-network/include/net/protocol/autoip.h similarity index 61% rename from lib-network/src/net/net_timers.cpp rename to lib-network/include/net/protocol/autoip.h index 7c6438e85..dc3d900ac 100644 --- a/lib-network/src/net/net_timers.cpp +++ b/lib-network/include/net/protocol/autoip.h @@ -1,8 +1,8 @@ /** - * @file net_timers.cpp + * @file autoip.h * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,34 +23,21 @@ * THE SOFTWARE. */ -#pragma GCC push_options -#pragma GCC optimize ("O2") -#pragma GCC optimize ("no-tree-loop-distribute-patterns") +#ifndef NET_PROTOCOL_AUTOIP_H_ +#define NET_PROTOCOL_AUTOIP_H_ -#include +#include "ip4_address.h" -#include "net_private.h" +namespace net::autoip { +static constexpr auto AUTOIP_NET = network::convert_to_uint(169,254,0,0); +static constexpr auto AUTOIP_RANGE_START = network::convert_to_uint(169,254,1,0); +static constexpr auto AUTOIP_RANGE_END = network::convert_to_uint(169,254,254,255); -#include "hardware.h" +enum class State { + AUTOIP_STATE_OFF, + AUTOIP_STATE_CHECKING, + AUTOIP_STATE_BOUND +}; +} // namespace autoip -#include "../../config/net_config.h" - -#ifndef NDEBUG - extern void arp_cache_timer(void); -#endif - -static volatile uint32_t s_ticker; - -#define INTERVAL_MS (100) // 100 msec, 1/10 second - -void net_timers_run() { - const auto nMillis = Hardware::Get()->Millis(); - - if (__builtin_expect(((nMillis - s_ticker) > INTERVAL_MS), 0)) { - s_ticker = nMillis; - igmp_timer(); -#ifndef NDEBUG - arp_cache_timer(); -#endif - } -} +#endif /* NET_PROTOCOL_AUTOIP_H_ */ diff --git a/lib-network/include/net/protocol/dhcp.h b/lib-network/include/net/protocol/dhcp.h new file mode 100644 index 000000000..94064171c --- /dev/null +++ b/lib-network/include/net/protocol/dhcp.h @@ -0,0 +1,120 @@ +/** + * @file dhcp.h + * + */ +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_DHCP_H +#define NET_PROTOCOL_DHCP_H + +#include + +#include "ip4.h" + +namespace net::dhcp { +static constexpr uint32_t OPT_SIZE = 312; +static constexpr uint32_t MAGIC_COOKIE = 0x63825363; ///< You should not modify it number. + +struct OpCode { + static constexpr uint8_t BOOTREQUEST = 1; + static constexpr uint8_t BOOTREPLY = 2; +}; + +struct HardwareType { + static constexpr uint8_t HTYPE_10MB = 1; + static constexpr uint8_t HTYPE_100MB = 2; +}; + +struct Type { + static constexpr uint8_t DISCOVER = 1; + static constexpr uint8_t OFFER = 2; + static constexpr uint8_t REQUEST = 3; + static constexpr uint8_t DECLINE = 4; + static constexpr uint8_t ACK = 5; + static constexpr uint8_t NAK = 6; + static constexpr uint8_t RELEASE = 7; + static constexpr uint8_t INFORM = 8; +}; + +struct Options { + /* BootP options */ + static constexpr uint8_t OPTION_PAD_OPTION = 0; + static constexpr uint8_t OPTION_SUBNET_MASK = 1; ///< RFC 2132 3.3 + static constexpr uint8_t OPTION_ROUTER = 3; + static constexpr uint8_t OPTION_DNS_SERVER = 6; + static constexpr uint8_t OPTION_HOSTNAME = 12; + static constexpr uint8_t OPTION_DOMAIN_NAME = 15; + static constexpr uint8_t OPTION_IP_TTL = 23; + static constexpr uint8_t OPTION_MTU = 26; + static constexpr uint8_t OPTION_BROADCAST = 28; + static constexpr uint8_t OPTION_TCP_TTL = 37; + static constexpr uint8_t OPTION_NTP = 42; + static constexpr uint8_t OPTION_END = 255; + /* DHCP options */ + static constexpr uint8_t OPTION_REQUESTED_IP = 50; ///< RFC 2132 9.1, requested IP address + static constexpr uint8_t OPTION_LEASE_TIME = 51; ///< RFC 2132 9.2, time in seconds, in 4 bytes + static constexpr uint8_t OPTION_OVERLOAD = 52; ///< RFC2132 9.3, use file and/or sname field for options + static constexpr uint8_t OPTION_MESSAGE_TYPE = 53; ///< RFC 2132 9.6, important for DHCP + static constexpr uint8_t OPTION_SERVER_IDENTIFIER = 54; ///< RFC 2132 9.7, server IP address + static constexpr uint8_t OPTION_PARAM_REQUEST = 55; ///< RFC 2132 9.8, requested option types + static constexpr uint8_t OPTION_MAX_MSG_SIZE = 57; ///< RFC 2132 9.10, message size accepted >= 576 + static constexpr uint8_t OPTION_DHCP_T1_VALUE = 58; ///< T1 renewal time + static constexpr uint8_t OPTION_DHCP_T2_VALUE = 59; ///< T2 renewal time + static constexpr uint8_t OPTION_CLIENT_IDENTIFIER = 61; +}; + +enum class State: uint8_t { + STATE_OFF = 0, + STATE_REQUESTING = 1, + STATE_INIT = 2, + STATE_REBOOTING = 3, + STATE_REBINDING = 4, + STATE_RENEWING = 5, + STATE_SELECTING = 6, + STATE_INFORMING = 7, + STATE_CHECKING = 8, + STATE_PERMANENT = 9, + STATE_BOUND = 10, + STATE_RELEASING = 11, + STATE_BACKING_OFF = 12 +}; + +struct Message { + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint8_t ciaddr[IPv4_ADDR_LEN]; + uint8_t yiaddr[IPv4_ADDR_LEN]; + uint8_t siaddr[IPv4_ADDR_LEN]; + uint8_t giaddr[IPv4_ADDR_LEN]; + uint8_t chaddr[16]; + uint8_t sname[64]; + uint8_t file[128]; + uint8_t options[dhcp::OPT_SIZE]; +} __attribute__((packed)); +} // namespace net::dhcp + +#endif /* NET_PROTOCOL_DHCP_H */ diff --git a/lib-network/include/net/protocol/dns.h b/lib-network/include/net/protocol/dns.h new file mode 100644 index 000000000..e486563f8 --- /dev/null +++ b/lib-network/include/net/protocol/dns.h @@ -0,0 +1,93 @@ +/** + * @file dns.h + * + */ +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_DNS_H_ +#define NET_PROTOCOL_DNS_H_ + +#include + +#include "ip4_address.h" + +namespace net { namespace dns { +static constexpr uint32_t SIZEOF_DNS_HDR = 12; + +enum class Flag1 : uint8_t { + FLAG1_RESPONSE = 0x80, ///< query (0), or a response (1). + FLAG1_OPCODE_STATUS = 0x10, ///< a server status request (STATUS) + FLAG1_OPCODE_IQUERY = 0x08, ///< an inverse query (IQUERY) + FLAG1_OPCODE_STANDARD = 0x00, ///< (RFC 6762, section 18.3) + FLAG1_AUTHORATIVE = 0x04, ///< Authoritative Answer + FLAG1_TRUNC = 0x02, ///< TrunCation + FLAG1_RD = 0x01 ///< If RD is set, it directs the name server to pursue the query recursively. +}; + +static constexpr uint8_t operator| (Flag1 a, Flag1 b) { + return static_cast((static_cast(a) | static_cast(b))); +} + +///< NS field TYPE used for "Resource Records" +enum class RRType : uint16_t { + RRTYPE_A = 1, ///< a host address + RRTYPE_PTR = 12, ///< a domain name pointer + RRTYPE_TXT = 16, ///< text strings + RRTYPE_SRV = 33, ///< service location + RRTYPE_ALL = 255 ///< any type +}; + +///< DNS field CLASS used for "Resource Records" +enum class RRClass : uint16_t { + RRCLASS_INTERNET = 1, ///< Internet + RRCLASS_ANY = 255, ///< Any class + RRCLASS_FLUSH = 0x8000 ///< Flush bit +}; + +static constexpr uint16_t operator| (RRClass a, RRClass b) { + return static_cast((static_cast(a) | static_cast(b))); +} + +struct Header { + uint16_t xid; + uint8_t nFlag1; + uint8_t nFlag2; + uint16_t nQueryCount; + uint16_t nAnswerCount; + uint16_t nAuthorityCount; + uint16_t nAdditionalCount; +} __attribute__((__packed__)); + +inline uint8_t dns_header_get_opcode(const Header *const header) { + return ((header->nFlag1) >> 3) & 0xF; +} + +/* + * mDNS + */ + +static constexpr uint32_t MULTICAST_MESSAGE_SIZE = 512; ///< The 1987 DNS specification [RFC1035] restricts DNS messages carried by UDP to no more than 512 bytes +static constexpr uint32_t MULTICAST_ADDRESS = network::convert_to_uint(224, 0, 0, 251); + +} } // namespace net::dns + +#endif /* NET_PROTOCOL_DNS_H_ */ diff --git a/lib-network/src/net/net_debug.h b/lib-network/include/net/protocol/ethernet.h old mode 100644 new mode 100755 similarity index 66% rename from lib-network/src/net/net_debug.h rename to lib-network/include/net/protocol/ethernet.h index 85095c4bf..323c23399 --- a/lib-network/src/net/net_debug.h +++ b/lib-network/include/net/protocol/ethernet.h @@ -1,8 +1,8 @@ /** - * @file net_debug.h + * @file ethernet.h * */ -/* Copyright (C) 2018-2019 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,22 +23,33 @@ * THE SOFTWARE. */ -#ifndef NET_DEBUG_H_ -#define NET_DEBUG_H_ +#ifndef NET_PROTOCOL_ETHERNET_H_ +#define NET_PROTOCOL_ETHERNET_H_ -#include "debug.h" +#include -#ifndef IP2STR - #define IP2STR(addr) (addr & 0xFF), ((addr >> 8) & 0xFF), ((addr >> 16) & 0xFF), ((addr >> 24) & 0xFF) - #define IPSTR "%d.%d.%d.%d" -#endif -#ifndef MAC2STR - #define MAC2STR(mac) (mac[0]),(mac[1]),(mac[2]),(mac[3]), (mac[4]), (mac[5]) - #define MACSTR "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" +#if !defined (PACKED) +# define PACKED __attribute__((packed)) #endif -#if defined (H3) -# include "h3_timer.h" -#endif +enum MTU { + MTU_SIZE = 1500 +}; + +enum ETH_ADDR { + ETH_ADDR_LEN = 6 +}; + +struct ether_header { + uint8_t dst[ETH_ADDR_LEN]; /* 6 */ + uint8_t src[ETH_ADDR_LEN]; /* 12 */ + uint16_t type; /* 14 */ +} PACKED; + +namespace net { +static constexpr uint32_t ETH_HWADDR_LEN = 6; + + +} // namespace net -#endif /* NET_DEBUG_H_ */ +#endif /* NET_PROTOCOL_ETHERNET_H_ */ diff --git a/lib-network/src/net/ntp_internal.h b/lib-network/include/net/protocol/iana.h similarity index 65% rename from lib-network/src/net/ntp_internal.h rename to lib-network/include/net/protocol/iana.h index 328dafabc..bc5c69903 100644 --- a/lib-network/src/net/ntp_internal.h +++ b/lib-network/include/net/protocol/iana.h @@ -1,8 +1,8 @@ /** - * @file ntp_internal.h + * @file iana.h * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,11 +23,18 @@ * THE SOFTWARE. */ -#ifndef NTP_INTERNAL_H_ -#define NTP_INTERNAL_H_ +#ifndef NET_PROTOCOL_IANA_H_ +#define NET_PROTOCOL_IANA_H_ -enum { - NTP_PORT_SERVER = 123 -}; +#include -#endif /* NTP_INTERNAL_H_ */ +namespace net::iana { +static constexpr uint16_t IANA_PORT_DHCP_SERVER = 67; +static constexpr uint16_t IANA_PORT_DHCP_CLIENT = 68; +static constexpr uint16_t IANA_PORT_TFTP = 69; +static constexpr uint16_t IANA_PORT_HTTP = 80; +static constexpr uint16_t IANA_PORT_NTP_SERVER = 123; +static constexpr uint16_t IANA_PORT_MDNS = 5353; +} // namespace net::iana + +#endif /* NET_PROTOCOL_IANA_H_ */ diff --git a/lib-network/include/net/protocol/icmp.h b/lib-network/include/net/protocol/icmp.h new file mode 100755 index 000000000..a9cb2a83e --- /dev/null +++ b/lib-network/include/net/protocol/icmp.h @@ -0,0 +1,65 @@ +/** + * @file icmp.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_ICMP_H_ +#define NET_PROTOCOL_ICMP_H_ + +#include + +#include "net/protocol/ethernet.h" +#include "net/protocol/ip4.h" + +#if !defined (PACKED) +# define PACKED __attribute__((packed)) +#endif + +enum ICMP_TYPE { + ICMP_TYPE_ECHO_REPLY = 0, + ICMP_TYPE_ECHO = 8 +}; + +enum ICMP_CODE { + ICMP_CODE_ECHO = 0 +}; + +struct t_icmp_packet { + uint8_t type; /* 1 */ + uint8_t code; /* 2 */ + uint16_t checksum; /* 4 */ + uint8_t parameter[4]; /* 8 */ +#define ICMP_HEADER_SIZE 8 +#define ICMP_PAYLOAD_SIZE (MTU_SIZE - ICMP_HEADER_SIZE - sizeof(struct ip4_header)) + uint8_t payload[ICMP_PAYLOAD_SIZE]; +} PACKED; + +struct t_icmp { + struct ether_header ether; + struct ip4_header ip4; + struct t_icmp_packet icmp; +} PACKED; + +#define IPv4_ICMP_HEADERS_SIZE (sizeof(struct t_icmp) - sizeof(struct ether_header)) + +#endif /* NET_PROTOCOL_ICMP_H_ */ diff --git a/lib-network/src/net/tftp_internal.h b/lib-network/include/net/protocol/ieee.h old mode 100644 new mode 100755 similarity index 76% rename from lib-network/src/net/tftp_internal.h rename to lib-network/include/net/protocol/ieee.h index 13c9f0562..c65ef0530 --- a/lib-network/src/net/tftp_internal.h +++ b/lib-network/include/net/protocol/ieee.h @@ -1,8 +1,8 @@ /** - * @file tftp_internal.h + * @file ieee.h * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,11 +23,15 @@ * THE SOFTWARE. */ -#ifndef TFTP_INTERNAL_H_ -#define TFTP_INTERNAL_H_ +#ifndef NET_PROTOCOL_IEEE_H_ +#define NET_PROTOCOL_IEEE_H_ -enum { - TFTP_PORT_SERVER = 69 +#include + +enum ETHER_TYPE { + ETHER_TYPE_IPv4 = 0x0800, + ETHER_TYPE_ARP = 0x0806, + ETHER_TYPE_PTP = 0x88F7 /* IEEE1588v2 (PTPv2) over Ethernet */ }; -#endif /* TFTP_INTERNAL_H_ */ +#endif /* NET_PROTOCOL_IEEE_H_ */ diff --git a/lib-network/src/net/dhcp_internal.h b/lib-network/include/net/protocol/igmp.h old mode 100644 new mode 100755 similarity index 54% rename from lib-network/src/net/dhcp_internal.h rename to lib-network/include/net/protocol/igmp.h index 1ce0e730e..d49a7d9f8 --- a/lib-network/src/net/dhcp_internal.h +++ b/lib-network/include/net/protocol/igmp.h @@ -1,8 +1,8 @@ /** - * @file dhcp_internal.h + * @file igmp.h * */ -/* Copyright (C) 2018-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,47 +23,44 @@ * THE SOFTWARE. */ -#ifndef DHCP_INTERNAL_H_ -#define DHCP_INTERNAL_H_ +#ifndef NET_PROTOCOL_IGMP_H_ +#define NET_PROTOCOL_IGMP_H_ -enum DHCP_PORT { - DHCP_PORT_SERVER = 67, - DHCP_PORT_CLIENT = 68 -}; +#include -enum DHCP_OP { - DHCP_OP_BOOTREQUEST = 1, - DHCP_OP_BOOTREPLY = 2 -}; +#include "net/protocol/ethernet.h" +#include "net/protocol/ip4.h" -enum DHCP_HTYPE { - DHCP_HTYPE_10MB = 1, - DHCP_HTYPE_100MB = 2 -}; +#if !defined (PACKED) +# define PACKED __attribute__((packed)) +#endif -enum DCHP_TYPE { - DCHP_TYPE_DISCOVER = 1, - DCHP_TYPE_OFFER = 2, - DCHP_TYPE_REQUEST = 3, - DCHP_TYPE_DECLINE = 4, - DCHP_TYPE_ACK = 5, - DCHP_TYPE_NAK = 6, - DCHP_TYPE_RELEASE = 7, - DCHP_TYPE_INFORM = 8 +enum IGMP_TYPE { + IGMP_TYPE_QUERY = 0x11, + IGMP_TYPE_REPORT = 0x16, + IGMP_TYPE_LEAVE = 0x17 }; -enum DHCP_STATE { - DHCP_STATE_DHCP_INIT = 0, - DHCP_STATE_DHCP_DISCOVER = 1, - DHCP_STATE_DHCP_REQUEST = 2, - DHCP_STATE_DHCP_LEASED = 3, - DHCP_STATE_DHCP_REREQUEST = 4, - DHCP_STATE_DHCP_RELEASE = 5, - DHCP_STATE_DHCP_STOP = 6 -}; +struct t_igmp_packet { + uint8_t type; + uint8_t max_resp_time; + uint16_t checksum; + uint8_t group_address[IPv4_ADDR_LEN]; +} PACKED; -#define DHCP_OPT_SIZE 312 +struct t_igmp { + struct ether_header ether; + struct ip4_header ip4; + union { + struct { + uint32_t ip4_options; + struct t_igmp_packet igmp; + } report; + struct t_igmp_packet igmp; + } igmp; +} PACKED; -#define MAGIC_COOKIE 0x63825363 ///< You should not modify it number. +#define IPv4_IGMP_REPORT_HEADERS_SIZE (sizeof(struct t_igmp) - sizeof(struct ether_header)) +#define IGMP_REPORT_PACKET_SIZE (sizeof(struct t_igmp)) -#endif /* DHCP_INTERNAL_H_ */ +#endif /* NET_PROTOCOL_IGMP_H_ */ diff --git a/lib-network/include/net/protocol/ip4.h b/lib-network/include/net/protocol/ip4.h new file mode 100755 index 000000000..346b99746 --- /dev/null +++ b/lib-network/include/net/protocol/ip4.h @@ -0,0 +1,71 @@ +/** + * @file ip4.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef NET_PROTOCOL_IP4_H_ +#define NET_PROTOCOL_IP4_H_ + +#include + +#include "net/protocol/ethernet.h" + +#if !defined (PACKED) +# define PACKED __attribute__((packed)) +#endif + +enum IPv4_ADDR { + IPv4_ADDR_LEN = 4 +}; + +enum IPv4_PROTO { + IPv4_PROTO_ICMP = 1, + IPv4_PROTO_IGMP = 2, + IPv4_PROTO_TCP = 6, + IPv4_PROTO_UDP = 17 +}; + +enum IPv4_FLAG { + IPv4_FLAG_LF = 0x0000, + IPv4_FLAG_MF = 0x2000, + IPv4_FLAG_DF = 0x4000 +}; + +struct ip4_header { + uint8_t ver_ihl; /* 1 */ + uint8_t tos; /* 2 */ + uint16_t len; /* 4 */ + uint16_t id; /* 6 */ + uint16_t flags_froff; /* 8 */ + uint8_t ttl; /* 9 */ + uint8_t proto; /* 10 */ + uint16_t chksum; /* 12 */ + uint8_t src[IPv4_ADDR_LEN]; /* 16 */ + uint8_t dst[IPv4_ADDR_LEN]; /* 20 */ +} PACKED; + +struct t_ip4 { + struct ether_header ether; + struct ip4_header ip4; +} PACKED; + +#endif /* NET_PROTOCOL_IP4_H_ */ diff --git a/lib-network/include/ntp.h b/lib-network/include/net/protocol/ntp.h similarity index 94% rename from lib-network/include/ntp.h rename to lib-network/include/net/protocol/ntp.h index ec203cd5d..2999c4ced 100755 --- a/lib-network/include/ntp.h +++ b/lib-network/include/net/protocol/ntp.h @@ -2,7 +2,7 @@ * @file ntp.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,8 +23,8 @@ * THE SOFTWARE. */ -#ifndef NTP_H_ -#define NTP_H_ +#ifndef NET_PROTOCOL_NTP_H_ +#define NET_PROTOCOL_NTP_H_ #include @@ -98,4 +98,4 @@ inline void sub_time(struct ntp::time_t *r, const struct ntp::time_t *x, const s } } // namespace ntp -#endif /* NTP_H_ */ +#endif /* NET_PROTOCOL_NTP_H_ */ diff --git a/lib-network/include/net/protocol/tcp.h b/lib-network/include/net/protocol/tcp.h new file mode 100755 index 000000000..b20047f2e --- /dev/null +++ b/lib-network/include/net/protocol/tcp.h @@ -0,0 +1,62 @@ +/** + * @file tcp.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_TCP_H_ +#define NET_PROTOCOL_TCP_H_ + +#include + +#include "net/protocol/ethernet.h" +#include "net/protocol/ip4.h" + +#if !defined (PACKED) +# define PACKED __attribute__((packed)) +#endif + +struct t_tcp_packet { + uint16_t srcpt; /* 2 */ + uint16_t dstpt; /* 4 */ + uint32_t seqnum; /* 8 */ + uint32_t acknum; /* 12 */ + uint8_t offset; /* 13 */ + uint8_t control; /* 14 */ + uint16_t window; /* 16 */ + uint16_t checksum; /* 18 */ + uint16_t urgent; /* 20 */ +#define TCP_HEADER_SIZE 20 +#define TCP_OPTIONS_SIZE 40 /* Assuming maximum TCP options size is 40 bytes */ +#define TCP_DATA_SIZE (MTU_SIZE - TCP_HEADER_SIZE - sizeof(struct ip4_header) - TCP_OPTIONS_SIZE) + uint8_t data[MTU_SIZE - TCP_HEADER_SIZE - sizeof(struct ip4_header)]; +} PACKED; + +struct t_tcp { + struct ether_header ether; + struct ip4_header ip4; + struct t_tcp_packet tcp; +} PACKED; + +#define IPv4_UDP_HEADERS_SIZE (sizeof(struct ip4_header) + UDP_HEADER_SIZE) /* IP | UDP */ + +#endif /* NET_PROTOCOL_TCP_H_ */ diff --git a/lib-network/include/net/protocol/udp.h b/lib-network/include/net/protocol/udp.h new file mode 100755 index 000000000..49bd5ec22 --- /dev/null +++ b/lib-network/include/net/protocol/udp.h @@ -0,0 +1,56 @@ +/** + * @file udp.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NET_PROTOCOL_UDP_H_ +#define NET_PROTOCOL_UDP_H_ + +#include + +#include "net/protocol/ethernet.h" +#include "net/protocol/ip4.h" + +#if !defined (PACKED) +# define PACKED __attribute__((packed)) +#endif + +struct t_udp_packet { + uint16_t source_port; /* 2 */ + uint16_t destination_port; /* 4 */ + uint16_t len; /* 6 */ + uint16_t checksum; /* 8 */ +#define UDP_HEADER_SIZE 8 +#define UDP_DATA_SIZE (MTU_SIZE - UDP_HEADER_SIZE - sizeof(struct ip4_header)) + uint8_t data[UDP_DATA_SIZE]; +}PACKED; + +struct t_udp { + struct ether_header ether; + struct ip4_header ip4; + struct t_udp_packet udp; +} PACKED; + +#define UDP_PACKET_HEADERS_SIZE (sizeof(struct ether_header) + IPv4_UDP_HEADERS_SIZE) /* ETH | IP | UDP */ + +#endif /* NET_PROTOCOL_UDP_H_ */ diff --git a/lib-network/include/netif.h b/lib-network/include/netif.h new file mode 100755 index 000000000..5e7f5dc01 --- /dev/null +++ b/lib-network/include/netif.h @@ -0,0 +1,168 @@ +/** + * @file netif.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef NETIF_H_ +#define NETIF_H_ + +#include + +#include "netif.h" +#include "ip4_address.h" + +#include "debug.h" + +#ifndef NETIF_MAX_HWADDR_LEN +# define NETIF_MAX_HWADDR_LEN 6U +#endif + +namespace net { +struct ip_addr { + uint32_t addr; +}; + +typedef struct ip_addr ip4_addr_t; + +struct netif { + static constexpr uint8_t NETIF_FLAG_LINK_UP = (1U << 0); + static constexpr uint8_t NETIF_FLAG_DHCP_OK = (1U << 1); + static constexpr uint8_t NETIF_FLAG_AUTOIP_OK = (1U << 2); + static constexpr uint8_t NETIF_FLAG_STATICIP_OK = (1U << 3); + + struct ip_addr ip; + struct ip_addr netmask; + struct ip_addr gw; + struct ip_addr broadcast_ip; + struct ip_addr secondary_ip; + + uint8_t hwaddr[NETIF_MAX_HWADDR_LEN]; + uint8_t flags; + + const char *hostname; + + void *dhcp; + void *acd; + void *autoip; +}; + +struct NetifReason { + static constexpr uint16_t NSC_NONE = 0x0000; + static constexpr uint16_t NSC_LINK_CHANGED = 0x0004; + static constexpr uint16_t NSC_IPV4_ADDRESS_CHANGED = 0x0010; + static constexpr uint16_t NSC_IPV4_GATEWAY_CHANGED = 0x0020; + static constexpr uint16_t NSC_IPV4_NETMASK_CHANGED = 0x0040; + static constexpr uint16_t NSC_IPV4_SETTINGS_CHANGED = 0x0080; + static constexpr uint16_t NSC_IPV4_ADDR_VALID = 0x0400; +}; + +struct ipv4_changed { + ip4_addr_t old_address; + ip4_addr_t old_netmask; + ip4_addr_t old_gw; +}; + +struct link_changed { + /** 1: up; 0: down */ + uint8_t state; +} ; + +union netif_ext_callback_args_t { + struct link_changed link_changed; + struct ipv4_changed ipv4_changed; +}; + +namespace globals { +extern struct netif netif_default; +} // namespace globals + +typedef void (* netif_ext_callback_fn)(const uint16_t reason, const netif_ext_callback_args_t *args); + +inline void netif_set_flags(uint8_t flags) { + globals::netif_default.flags |= flags; +} + +inline void netif_clear_flags(uint8_t flags) { + globals::netif_default.flags &= static_cast(~flags); +} + +inline bool netif_dhcp() { + return (globals::netif_default.flags & netif::NETIF_FLAG_DHCP_OK) == netif::NETIF_FLAG_DHCP_OK; +} + +inline bool netif_autoip() { + return (globals::netif_default.flags & netif::NETIF_FLAG_AUTOIP_OK) == netif::NETIF_FLAG_AUTOIP_OK; +} + +inline uint32_t netif_ipaddr() { + return globals::netif_default.ip.addr; +} + +inline uint32_t netif_netmask() { + return globals::netif_default.netmask.addr; +} + +inline uint32_t netif_gw() { + return globals::netif_default.gw.addr; +} + +inline void netif_set_hostname(const char *hostname) { + globals::netif_default.hostname = hostname; +} + +inline const char *netif_hostname() { + return globals::netif_default.hostname; +} + +inline uint32_t netif_secondary_ipaddr() { + return globals::netif_default.secondary_ip.addr; +} + +inline uint32_t netif_broadcast_ipaddr() { + return globals::netif_default.broadcast_ip.addr; +} + +inline const uint8_t *netif_hwaddr() { + return globals::netif_default.hwaddr; +} +void netif_init(); +void netif_set_ipaddr(const ip4_addr_t ipaddr); +void netif_set_netmask(const ip4_addr_t netmask); +void netif_set_gw(const ip4_addr_t gw); +void netif_set_addr(const ip4_addr_t ipaddr, const ip4_addr_t netmask, const ip4_addr_t gw); + +void netif_add_ext_callback(netif_ext_callback_fn fn); + +/** + * Link + */ + +void netif_set_link_up(); +void netif_set_link_down(); + +inline bool netif_is_link_up() { + return (globals::netif_default.flags & netif::NETIF_FLAG_LINK_UP) == netif::NETIF_FLAG_LINK_UP; +} +} // namespace net + +#endif /* NETIF_H_ */ diff --git a/lib-network/include/network.h b/lib-network/include/network.h index 55491787e..7fe09f459 100644 --- a/lib-network/include/network.h +++ b/lib-network/include/network.h @@ -2,7 +2,7 @@ * @file network.h * */ -/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,103 +28,16 @@ #include -#define IP2STR(addr) static_cast(addr & 0xFF), static_cast((addr >> 8) & 0xFF), static_cast((addr >> 16) & 0xFF), static_cast((addr >> 24) & 0xFF) -#define IPSTR "%d.%d.%d.%d" - -#define MAC2STR(mac) static_cast(mac[0]),static_cast(mac[1]),static_cast(mac[2]),static_cast(mac[3]), static_cast(mac[4]), static_cast(mac[5]) -#define MACSTR "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" +#include "ip4_address.h" namespace network { -static constexpr auto STORE = 96; ///< Configuration store in bytes -static constexpr auto IP_SIZE = 4U; -static constexpr auto MAC_SIZE = 6U; -static constexpr auto HOSTNAME_SIZE = 64U; ///< Including a terminating null byte. -static constexpr auto DOMAINNAME_SIZE = 64U; ///< Including a terminating null byte. -static constexpr auto IP4_BROADCAST = 0xffffffff; namespace dhcp { enum class Mode: uint8_t { INACTIVE = 0x00, ///< The IP address was not obtained via DHCP ACTIVE = 0x01, ///< The IP address was obtained via DHCP UNKNOWN = 0x02 ///< The system cannot determine if the address was obtained via DHCP }; -enum class ClientStatus { - IDLE, RENEW, GOT_IP, RETRYING, FAILED -}; } // namespace dhcp - -static constexpr uint32_t convert_to_uint(const uint8_t a, const uint8_t b, const uint8_t c, const uint8_t d) { - return static_cast(a) | - static_cast(b) << 8 | - static_cast(c) << 16 | - static_cast(d) << 24; -} - -inline bool is_netmask_valid(uint32_t nNetMask) { - if (nNetMask == 0) { - return false; - } - nNetMask = __builtin_bswap32(nNetMask); - return !(nNetMask & (~nNetMask >> 1)); - -} -/** - * The private address ranges are defined in RFC1918. - */ -inline bool is_private_ip(const uint32_t nIp) { - const uint8_t n = (nIp >> 8) & 0xFF; - - switch (nIp & 0xFF) { - case 10: - return true; - break; - case 172: - return (n >= 16) && (n < 32); - case 192: - return n == 168; - default: - break; - } - - return false; -} - -inline bool is_multicast_ip(const uint32_t nIp) { - if ((nIp & 0xE0) != 0xE0) { - return false; - } - - if ((nIp & 0xFFFFEF) == 0x0000E0) { // 224.0.0.0 to 224.0.0.255 Local subnetwork - return false; - } - - if ((nIp & 0xFFFFEF) == 0x0100E0) { // 224.0.1.0 to 224.0.1.255 Internetwork control - return false; - } - - return true; -} - -inline uint32_t cidr_to_netmask(const uint8_t nCIDR) { - if (nCIDR != 0) { - const auto nNetmask = __builtin_bswap32(static_cast(~0x0) << (32 - nCIDR)); - return nNetmask; - } - - return 0; -} - -void display_emac_config(); -void display_emac_start(); -void display_emac_status(const bool isLinkUp); -void display_ip(); -void display_netmask(); -void display_gateway(); -void display_hostname(); -void display_dhcp_status(network::dhcp::ClientStatus nStatus); -void display_emac_shutdown(); - -void mdns_announcement(); -void mdns_shutdown(); } // namespace network #if defined(__linux__) || defined (__APPLE__) diff --git a/lib-network/src/emac/gd32/emac.cpp b/lib-network/src/emac/gd32/emac.cpp index fcdab5b8c..e482d3349 100644 --- a/lib-network/src/emac/gd32/emac.cpp +++ b/lib-network/src/emac/gd32/emac.cpp @@ -34,6 +34,10 @@ #include "debug.h" +extern "C" { +void console_error(const char *); +} + extern void enet_gpio_config(); extern enet_descriptors_struct txdesc_tab[ENET_TXBUF_NUM]; extern void mac_address_get(uint8_t paddr[]); @@ -69,7 +73,9 @@ void __attribute__((cold)) emac_config() { enet_deinit(ENETx); enet_software_reset(ENETx); - net::phy_config(PHY_ADDRESS); + if(!net::phy_config(PHY_ADDRESS)) { + console_error("net::phy_config(PHY_ADDRESS)"); + } DEBUG_EXIT } diff --git a/lib-network/src/emac/gd32/f/net.cpp b/lib-network/src/emac/gd32/f/net.cpp index b96ae3f9f..713d281be 100644 --- a/lib-network/src/emac/gd32/f/net.cpp +++ b/lib-network/src/emac/gd32/f/net.cpp @@ -23,21 +23,23 @@ * THE SOFTWARE. */ -#pragma GCC push_options -#pragma GCC optimize ("O2") -#pragma GCC optimize ("no-tree-loop-distribute-patterns") +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif #include #include #include "gd32.h" -#include "gd32_ptp.h" -#include "../src/net/net_packets.h" #include "../src/net/net_memcpy.h" #include "debug.h" #if defined (CONFIG_ENET_ENABLE_PTP) +#include "gd32_ptp.h" + extern enet_descriptors_struct *dma_current_ptp_rxdesc; extern enet_descriptors_struct *dma_current_ptp_txdesc; namespace net { @@ -49,8 +51,6 @@ extern uint32_t ptpTimestamp[2]; extern enet_descriptors_struct *dma_current_rxdesc; extern enet_descriptors_struct *dma_current_txdesc; -extern "C" int console_error(const char *); - int emac_eth_recv(uint8_t **ppPacket) { const auto nLength = enet_desc_information_get(dma_current_rxdesc, RXDESC_FRAME_LENGTH); @@ -183,7 +183,7 @@ inline static void ptpframe_transmit(const uint8_t *pBuffer, const uint32_t nLen } } -void emac_eth_send(void *pBuffer, int nLength) { +void emac_eth_send(void *pBuffer, uint32_t nLength) { while (0 != (dma_current_txdesc->status & ENET_TDES0_DAV)) { __DMB(); } @@ -195,7 +195,7 @@ void emac_eth_send(void *pBuffer, int nLength) { ptpframe_transmit(reinterpret_cast(pBuffer), nLength, false); } -void emac_eth_send_timestamp(void *pBuffer, int nLength) { +void emac_eth_send_timestamp(void *pBuffer, uint32_t nLength) { while (0 != (dma_current_txdesc->status & ENET_TDES0_DAV)) { __DMB(); } @@ -207,7 +207,7 @@ void emac_eth_send_timestamp(void *pBuffer, int nLength) { ptpframe_transmit(reinterpret_cast(pBuffer), nLength, true); } #else -void emac_eth_send(void *pBuffer, int nLength) { +void emac_eth_send(void *pBuffer, uint32_t nLength) { assert(nullptr != pBuffer); assert(nLength <= static_cast(ENET_MAX_FRAME_SIZE)); diff --git a/lib-network/src/emac/gd32/h/net.cpp b/lib-network/src/emac/gd32/h/net.cpp index 06f1c73c3..a3d8114f4 100644 --- a/lib-network/src/emac/gd32/h/net.cpp +++ b/lib-network/src/emac/gd32/h/net.cpp @@ -32,13 +32,13 @@ #include #include "gd32.h" -#include "gd32_ptp.h" -#include "../src/net/net_packets.h" #include "../src/net/net_memcpy.h" #include "debug.h" #if defined (CONFIG_ENET_ENABLE_PTP) +#include "gd32_ptp.h" + extern enet_descriptors_struct *dma_current_ptp_rxdesc; extern enet_descriptors_struct *dma_current_ptp_txdesc; namespace net { @@ -187,7 +187,7 @@ inline static void ptpframe_transmit(void *pBuffer, const uint32_t nLength, cons } } -void emac_eth_send(void *pBuffer, int nLength) { +void emac_eth_send(void *pBuffer, uint32_t nLength) { assert(nullptr != pBuffer); assert(nLength <= static_cast(ENET_MAX_FRAME_SIZE)); @@ -203,7 +203,7 @@ void emac_eth_send(void *pBuffer, int nLength) { ptpframe_transmit(pBuffer, nLength, false); } -void emac_eth_send_timestamp(void *pBuffer, int nLength) { +void emac_eth_send_timestamp(void *pBuffer, uint32_t nLength) { assert(nullptr != pBuffer); assert(nLength <= static_cast(ENET_MAX_FRAME_SIZE)); @@ -219,7 +219,7 @@ void emac_eth_send_timestamp(void *pBuffer, int nLength) { ptpframe_transmit(pBuffer, nLength, true); } #else -void emac_eth_send(void *pBuffer, int nLength) { +void emac_eth_send(void *pBuffer, uint32_t nLength) { assert(nullptr != pBuffer); assert(nLength <= static_cast(ENET_MAX_FRAME_SIZE)); diff --git a/lib-network/src/emac/gd32/net_phy.cpp b/lib-network/src/emac/gd32/net_phy.cpp index 30f3c8045..693aa290c 100644 --- a/lib-network/src/emac/gd32/net_phy.cpp +++ b/lib-network/src/emac/gd32/net_phy.cpp @@ -101,31 +101,31 @@ bool phy_config(const uint32_t nAddress) { reg |= ENET_MDC_HCLK_DIV42; } else if (ENET_RANGE(ahbclk, 100000000U, 150000000U)) { reg |= ENET_MDC_HCLK_DIV62; - } else if ((ENET_RANGE(ahbclk, 150000000U, 200000000U)) || (200000000U == ahbclk)) { + } else if ((ENET_RANGE(ahbclk, 150000000U, 240000000U)) || (240000000U == ahbclk)) { reg |= ENET_MDC_HCLK_DIV102; } else { return false; } #elif defined GD32H7XX - if(ENET_RANGE(ahbclk, 20000000U, 35000000U)) { - reg |= ENET_MDC_HCLK_DIV16; - } else if(ENET_RANGE(ahbclk, 35000000U, 60000000U)) { - reg |= ENET_MDC_HCLK_DIV26; - } else if(ENET_RANGE(ahbclk, 60000000U, 100000000U)) { - reg |= ENET_MDC_HCLK_DIV42; - } else if(ENET_RANGE(ahbclk, 100000000U, 150000000U)) { - reg |= ENET_MDC_HCLK_DIV62; - } else if((ENET_RANGE(ahbclk, 150000000U, 180000000U)) || (180000000U == ahbclk)) { - reg |= ENET_MDC_HCLK_DIV102; - } else if(ENET_RANGE(ahbclk, 250000000U, 300000000U)) { - reg |= ENET_MDC_HCLK_DIV124; - } else if(ENET_RANGE(ahbclk, 300000000U, 350000000U)) { - reg |= ENET_MDC_HCLK_DIV142; - } else if((ENET_RANGE(ahbclk, 350000000U, 400000000U)) || (400000000U == ahbclk)) { - reg |= ENET_MDC_HCLK_DIV162; - } else { - return false; - } + if (ENET_RANGE(ahbclk, 20000000U, 35000000U)) { + reg |= ENET_MDC_HCLK_DIV16; + } else if (ENET_RANGE(ahbclk, 35000000U, 60000000U)) { + reg |= ENET_MDC_HCLK_DIV26; + } else if (ENET_RANGE(ahbclk, 60000000U, 100000000U)) { + reg |= ENET_MDC_HCLK_DIV42; + } else if (ENET_RANGE(ahbclk, 100000000U, 150000000U)) { + reg |= ENET_MDC_HCLK_DIV62; + } else if ((ENET_RANGE(ahbclk, 150000000U, 180000000U)) || (180000000U == ahbclk)) { + reg |= ENET_MDC_HCLK_DIV102; + } else if (ENET_RANGE(ahbclk, 250000000U, 300000000U)) { + reg |= ENET_MDC_HCLK_DIV124; + } else if (ENET_RANGE(ahbclk, 300000000U, 350000000U)) { + reg |= ENET_MDC_HCLK_DIV142; + } else if ((ENET_RANGE(ahbclk, 350000000U, 400000000U)) || (400000000U == ahbclk)) { + reg |= ENET_MDC_HCLK_DIV162; + } else { + return false; + } #endif #if defined (GD32H7XX) diff --git a/lib-network/src/emac/h3/net.cpp b/lib-network/src/emac/h3/net.cpp index 8471be91b..43aadeae7 100644 --- a/lib-network/src/emac/h3/net.cpp +++ b/lib-network/src/emac/h3/net.cpp @@ -63,12 +63,12 @@ __attribute__((hot)) int emac_eth_recv(uint8_t **packetp) { return -1; } -void emac_eth_send(void *packet, int len) { +void emac_eth_send(void *packet, uint32_t len) { auto desc_num = p_coherent_region->tx_currdescnum; auto *desc_p = &p_coherent_region->tx_chain[desc_num]; auto data_start = static_cast(desc_p->buf_addr); - desc_p->st = static_cast(len); + desc_p->st = len; /* Mandatory undocumented bit */ desc_p->st |= (1U << 24); diff --git a/lib-network/src/emac/network.cpp b/lib-network/src/emac/network.cpp index 933631630..e993f43b4 100755 --- a/lib-network/src/emac/network.cpp +++ b/lib-network/src/emac/network.cpp @@ -23,7 +23,12 @@ * THE SOFTWARE. */ +#ifdef DEBUG_NETWORK +# undef NDEBUG +#endif + #include +#include #include #include #include @@ -34,19 +39,21 @@ #include "hardware.h" -#include "../net/net.h" -#include "../../config/net_config.h" - #include "emac/emac.h" #include "emac/phy.h" #include "emac/mmi.h" #include "emac/net_link_check.h" +#include "netif.h" +#include "net/autoip.h" +#include "net/dhcp.h" + +#include "../../config/net_config.h" + #include "debug.h" namespace network { void __attribute__((weak)) mdns_announcement() {} -void __attribute__((weak)) mdns_shutdown() {} } // namespace network static constexpr char TO_HEX(const char i) { @@ -57,6 +64,40 @@ static constexpr char TO_HEX(const char i) { # define PHY_ADDRESS 1 #endif +static void netif_ext_callback(const uint16_t reason, [[maybe_unused]] const net::netif_ext_callback_args_t *args) { + DEBUG_ENTRY + + if ((reason & net::NetifReason::NSC_IPV4_ADDRESS_CHANGED) == net::NetifReason::NSC_IPV4_ADDRESS_CHANGED) { + net::display_ip(); + network::mdns_announcement(); + + printf("ip: " IPSTR " -> " IPSTR "\n", IP2STR(args->ipv4_changed.old_address.addr), IP2STR(net::netif_ipaddr())); + } + + if ((reason & net::NetifReason::NSC_IPV4_NETMASK_CHANGED) == net::NetifReason::NSC_IPV4_NETMASK_CHANGED) { + net::display_netmask(); + + printf("netmask: " IPSTR " -> " IPSTR "\n", IP2STR(args->ipv4_changed.old_netmask.addr), IP2STR(net::netif_netmask())); + } + + if ((reason & net::NetifReason::NSC_IPV4_GATEWAY_CHANGED) == net::NetifReason::NSC_IPV4_GATEWAY_CHANGED) { + net::display_gateway(); + + printf("gw: " IPSTR " -> " IPSTR "\n", IP2STR(args->ipv4_changed.old_gw.addr), IP2STR(net::netif_gw())); + } + + if ((reason & net::NetifReason::NSC_LINK_CHANGED) == net::NetifReason::NSC_LINK_CHANGED) { + if (args->link_changed.state == 0) { // Link down + net::net_link_down(); + + DEBUG_EXIT + return; + } + } + + DEBUG_EXIT +} + Network *Network::s_pThis; Network::Network() { @@ -64,25 +105,30 @@ Network::Network() { assert(s_pThis == nullptr); s_pThis = this; - m_aDomainName[0] = '\0'; - strcpy(m_aIfName, "eth0"); + m_aDomainName[0] = '\0'; + memset(&m_nNameservers, 0, sizeof(m_nNameservers)); - network::display_emac_config(); + net::display_emac_config(); emac_config(); - network::display_emac_start(); + net::display_emac_start(); - emac_start(m_aNetMacaddr, s_lastState); + emac_start(net::globals::netif_default.hwaddr, s_lastState); + printf(MACSTR "\n", MAC2STR(net::globals::netif_default.hwaddr)); net::phy_customized_timing(); net::phy_customized_led(); + net::netif_init(); + net::netif_add_ext_callback(netif_ext_callback); + NetworkParams params; params.Load(); const auto *p = params.GetHostName(); + assert(p != nullptr); if (*p == '\0') { uint32_t k = 0; @@ -91,18 +137,35 @@ Network::Network() { m_aHostName[k++] = HOST_NAME_PREFIX[i]; } - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[3] >> 4); - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[3] & 0x0F); - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[4] >> 4); - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[4] & 0x0F); - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[5] >> 4); - m_aHostName[k++] = TO_HEX(m_aNetMacaddr[5] & 0x0F); + auto hwaddr = net::globals::netif_default.hwaddr; + + m_aHostName[k++] = TO_HEX(hwaddr[3] >> 4); + m_aHostName[k++] = TO_HEX(hwaddr[3] & 0x0F); + m_aHostName[k++] = TO_HEX(hwaddr[4] >> 4); + m_aHostName[k++] = TO_HEX(hwaddr[4] & 0x0F); + m_aHostName[k++] = TO_HEX(hwaddr[5] >> 4); + m_aHostName[k++] = TO_HEX(hwaddr[5] & 0x0F); m_aHostName[k] = '\0'; } else { strncpy(m_aHostName, p, sizeof(m_aHostName) - 1); m_aHostName[sizeof(m_aHostName) - 1] = '\0'; } + net::netif_set_hostname(m_aHostName); + + net::ip4_addr_t ipaddr; + net::ip4_addr_t netmask; + net::ip4_addr_t gw; + + ipaddr.addr = params.GetIpAddress(); + netmask.addr = params.GetNetMask(); + gw.addr = params.GetDefaultGateway(); + + bool isDhcpUsed = params.isDhcpUsed(); + + net::display_emac_status(net::Link::STATE_UP == s_lastState); + net::net_init(s_lastState, ipaddr, netmask, gw, isDhcpUsed); + #if defined (ENET_LINK_CHECK_USE_INT) net::link_interrupt_init(); #elif defined (ENET_LINK_CHECK_USE_PIN_POLL) @@ -110,138 +173,41 @@ Network::Network() { #elif defined (ENET_LINK_CHECK_REG_POLL) net::link_status_read(); #endif - - Start(s_lastState); -} - -void Network::Start(const net::Link link) { - DEBUG_PRINTF("Link %s", link == net::Link::STATE_UP ? "Up" : "Down"); - - NetworkParams params; - params.Load(); - - m_IpInfo.ip.addr = params.GetIpAddress(); - m_IpInfo.netmask.addr = params.GetNetMask(); - m_IpInfo.gw.addr = params.GetDefaultGateway(); - m_IsDhcpUsed = params.isDhcpUsed(); - m_nDhcpRetryTime = params.GetDhcpRetryTime(); - -#ifndef NDEBUG - Print(); -#endif - - network::display_emac_status(net::Link::STATE_UP == link); - - if (net::Link::STATE_UP == link) { - if (!m_IsDhcpUsed) { - DEBUG_PUTS(""); - if (m_IpInfo.ip.addr == 0) { - DEBUG_PUTS(""); - } else if (!IsValidIp(m_IpInfo.gw.addr)) { - DEBUG_PUTS(""); - m_IpInfo.gw.addr = m_IpInfo.ip.addr; - } - } - - if (m_IsDhcpUsed) { - network::display_dhcp_status(network::dhcp::ClientStatus::RENEW); - } - - net_init(m_aNetMacaddr, &m_IpInfo, m_aHostName, &m_IsDhcpUsed, &m_IsZeroconfUsed); - - if (m_IsZeroconfUsed) { - network::display_dhcp_status(network::dhcp::ClientStatus::FAILED); - } - - while (m_IsZeroconfUsed && (m_nDhcpRetryTime != 0) && m_IsDhcpUsed) { - Hardware::Get()->SetMode(hardware::ledblink::Mode::FAST); - - network::display_dhcp_status(network::dhcp::ClientStatus::RETRYING); - - auto nTime = time(nullptr); - while ((time(nullptr) - nTime) < (m_nDhcpRetryTime * 60)) { - Hardware::Get()->Run(); - } - - network::display_dhcp_status(network::dhcp::ClientStatus::RENEW); - - Hardware::Get()->SetMode(hardware::ledblink::Mode::OFF_ON); - - m_IsDhcpUsed = true; - m_IsZeroconfUsed = false; - - net_init(m_aNetMacaddr, &m_IpInfo, m_aHostName, &m_IsDhcpUsed, &m_IsZeroconfUsed); - - if (m_IsDhcpUsed) { - break; - } - } - } else { - if (m_IsDhcpUsed) { - DEBUG_PUTS("m_IsDhcpUsed=true"); - m_IpInfo.ip.addr = 0; - m_IpInfo.netmask.addr = 0; - m_IpInfo.gw.addr = 0; - } - - auto bFalse = false; - - net_init(m_aNetMacaddr, &m_IpInfo, m_aHostName, &bFalse, &bFalse); - } - - network::display_ip(); - network::display_netmask(); - network::display_gateway(); - DEBUG_EXIT } void Network::SetIp(uint32_t nIp) { DEBUG_ENTRY - if (m_IsDhcpUsed) { - m_IsDhcpUsed = false; - net_dhcp_release(); - } - - m_IsZeroconfUsed = false; - - m_IpInfo.ip.addr = nIp; - - if (nIp == 0) { - } else { - m_IpInfo.gw.addr = m_IpInfo.ip.addr; + if (nIp == net::netif_ipaddr()) { + DEBUG_EXIT + return; } - net_set_ip(&m_IpInfo); - net_set_gw(&m_IpInfo); + net::ip4_addr_t ipaddr; + ipaddr.addr = nIp; + net_set_primary_ip(ipaddr); - NetworkStore::SaveIp(m_IpInfo.ip.addr); - NetworkStore::SaveGatewayIp(m_IpInfo.gw.addr); + NetworkStore::SaveIp(nIp); NetworkStore::SaveDhcp(false); - network::mdns_announcement(); - network::display_ip(); - network::display_netmask(); - DEBUG_EXIT } void Network::SetNetmask(uint32_t nNetmask) { DEBUG_ENTRY - if (m_IpInfo.netmask.addr == nNetmask) { + if (nNetmask == net::netif_netmask()) { DEBUG_EXIT return; } - m_IpInfo.netmask.addr = nNetmask; - net_set_netmask(&m_IpInfo); + net::ip4_addr_t netmask; + netmask.addr = nNetmask; - NetworkStore::SaveNetMask(m_IpInfo.netmask.addr); + net::netif_set_netmask(netmask); - network::display_ip(); - network::display_netmask(); + NetworkStore::SaveNetMask(nNetmask); DEBUG_EXIT } @@ -249,17 +215,17 @@ void Network::SetNetmask(uint32_t nNetmask) { void Network::SetGatewayIp(uint32_t nGatewayIp) { DEBUG_ENTRY - if (m_IpInfo.gw.addr == nGatewayIp) { + if (nGatewayIp == net::netif_gw()) { DEBUG_EXIT return; } - m_IpInfo.gw.addr = nGatewayIp; - net_set_gw(&m_IpInfo); + net::ip4_addr_t gw; + gw.addr = nGatewayIp; - NetworkStore::SaveGatewayIp(m_IpInfo.gw.addr); + net::netif_set_gw(gw); - network::display_gateway(); + NetworkStore::SaveGatewayIp(nGatewayIp); DEBUG_EXIT } @@ -270,139 +236,126 @@ void Network::SetHostName(const char *pHostName) { strncpy(m_aHostName, pHostName, network::HOSTNAME_SIZE - 1); m_aHostName[network::HOSTNAME_SIZE - 1] = '\0'; - NetworkStore::SaveHostName(m_aHostName, static_cast(strlen(m_aHostName))); + NetworkStore::SaveHostName(m_aHostName, static_cast(strlen(m_aHostName))); network::mdns_announcement(); - network::display_hostname(); + net::display_hostname(); DEBUG_EXIT } -bool Network::SetZeroconf() { +void Network::SetZeroconf() { DEBUG_ENTRY - const auto bWatchdog = Hardware::Get()->IsWatchdog(); + net::autoip_start(); - if (bWatchdog) { - Hardware::Get()->WatchdogStop(); - } - - m_IsZeroconfUsed = net_set_zeroconf(&m_IpInfo); - - if (m_IsZeroconfUsed) { - m_IsDhcpUsed = false; - - NetworkStore::SaveDhcp(true);// Zeroconf is enabled only when use_dhcp=1 - } - - network::mdns_announcement(); - network::display_ip(); - network::display_netmask(); - - if (bWatchdog) { - Hardware::Get()->WatchdogInit(); - } + NetworkStore::SaveDhcp(false); DEBUG_EXIT - return m_IsZeroconfUsed; } -bool Network::EnableDhcp() { +void Network::EnableDhcp() { DEBUG_ENTRY - const auto bWatchdog = Hardware::Get()->IsWatchdog(); - - if (bWatchdog) { - Hardware::Get()->WatchdogStop(); - } + net::dhcp_start(); - network::display_dhcp_status(network::dhcp::ClientStatus::RENEW); - - m_IsDhcpUsed = net_set_dhcp(&m_IpInfo, m_aHostName, &m_IsZeroconfUsed); - - if (m_IsZeroconfUsed) { - network::display_dhcp_status(network::dhcp::ClientStatus::FAILED); - } else { - network::display_dhcp_status(network::dhcp::ClientStatus::GOT_IP); - } - - DEBUG_PRINTF("m_IsDhcpUsed=%d, m_IsZeroconfUsed=%d", m_IsDhcpUsed, m_IsZeroconfUsed); - - NetworkStore::SaveDhcp(m_IsDhcpUsed); - - network::mdns_announcement(); - network::display_ip(); - network::display_netmask(); - network::display_gateway(); - - if (bWatchdog) { - Hardware::Get()->WatchdogInit(); - } + NetworkStore::SaveDhcp(true); DEBUG_EXIT - return m_IsDhcpUsed; } -void Network::SetQueuedStaticIp(uint32_t nLocalIp, uint32_t nNetmask) { +void Network::SetQueuedStaticIp(const uint32_t nStaticIp, const uint32_t nNetmask) { DEBUG_ENTRY - DEBUG_PRINTF(IPSTR ", nNetmask=" IPSTR, IP2STR(nLocalIp), IP2STR(nNetmask)); + DEBUG_PRINTF(IPSTR ", nNetmask=" IPSTR, IP2STR(nStaticIp), IP2STR(nNetmask)); - if (nLocalIp != 0) { - m_QueuedConfig.nLocalIp = nLocalIp; + if (nStaticIp != 0) { + m_QueuedConfig.nStaticIp = nStaticIp; + } else { + m_QueuedConfig.nStaticIp = GetIp(); } if (nNetmask != 0) { m_QueuedConfig.nNetmask = nNetmask; + } else { + m_QueuedConfig.nNetmask = GetNetmask(); } m_QueuedConfig.nMask |= QueuedConfig::STATIC_IP; - m_QueuedConfig.nMask |= QueuedConfig::NET_MASK; + m_QueuedConfig.nMask |= QueuedConfig::NETMASK; DEBUG_EXIT } +void Network::SetQueuedDefaultRoute(const uint32_t nGatewayIp) { + if (nGatewayIp != 0) { + m_QueuedConfig.nGateway = nGatewayIp; + } else { + m_QueuedConfig.nGateway = GetGatewayIp(); + } + + m_QueuedConfig.nMask |= QueuedConfig::GW; +} + bool Network::ApplyQueuedConfig() { DEBUG_ENTRY - DEBUG_PRINTF("m_QueuedConfig.nMask=%x, " IPSTR ", " IPSTR, m_QueuedConfig.nMask, IP2STR(m_QueuedConfig.nLocalIp), IP2STR(m_QueuedConfig.nNetmask)); + DEBUG_PRINTF("m_QueuedConfig.nMask=%x, " IPSTR ", " IPSTR, m_QueuedConfig.nMask, IP2STR(m_QueuedConfig.nStaticIp), IP2STR(m_QueuedConfig.nNetmask)); if (m_QueuedConfig.nMask == QueuedConfig::NONE) { DEBUG_EXIT return false; } - if ((isQueuedMaskSet(QueuedConfig::STATIC_IP)) || (isQueuedMaskSet(QueuedConfig::NET_MASK))) { - if (isQueuedMaskSet(QueuedConfig::NET_MASK)) { + if ((isQueuedMaskSet(QueuedConfig::STATIC_IP)) || (isQueuedMaskSet(QueuedConfig::NETMASK)) || (isQueuedMaskSet(QueuedConfig::GW))) { + // After SetIp all ip address might be zero. + if (isQueuedMaskSet(QueuedConfig::STATIC_IP)) { + SetIp(m_QueuedConfig.nStaticIp); + } + + if (isQueuedMaskSet(QueuedConfig::NETMASK)) { SetNetmask(m_QueuedConfig.nNetmask); - m_QueuedConfig.nMask &= ~(QueuedConfig::NET_MASK); } - if (isQueuedMaskSet(QueuedConfig::STATIC_IP)) { - SetIp(m_QueuedConfig.nLocalIp); - m_QueuedConfig.nMask &= ~(QueuedConfig::STATIC_IP); + if (isQueuedMaskSet(QueuedConfig::GW)) { + SetGatewayIp(m_QueuedConfig.nGateway); } + + m_QueuedConfig.nMask = QueuedConfig::NONE; + + DEBUG_EXIT + return true; } if (isQueuedMaskSet(QueuedConfig::DHCP)) { - EnableDhcp(); - m_QueuedConfig.nMask &= ~(QueuedConfig::DHCP); + if (m_QueuedConfig.mode == network::dhcp::Mode::ACTIVE) { + EnableDhcp(); + } else if (m_QueuedConfig.mode == network::dhcp::Mode::INACTIVE) { + + } + + m_QueuedConfig.mode = network::dhcp::Mode::UNKNOWN; + m_QueuedConfig.nMask = QueuedConfig::NONE; + + DEBUG_EXIT + return true; } if (isQueuedMaskSet(QueuedConfig::ZEROCONF)) { SetZeroconf(); - m_QueuedConfig.nMask &= ~(QueuedConfig::ZEROCONF); + m_QueuedConfig.nMask = QueuedConfig::NONE; + + DEBUG_EXIT + return true; } DEBUG_EXIT - return true; + return false; } -#include - void Network::Print() { printf("Network [%c]\n", GetAddressingMode()); printf(" Hostname : %s\n", m_aHostName); - printf(" IfName : %u: %s " MACSTR "\n", static_cast(m_nIfIndex), m_aIfName, MAC2STR(m_aNetMacaddr)); - printf(" Primary : " IPSTR "/%u (HTTP only " IPSTR ")\n", IP2STR(m_IpInfo.ip.addr), static_cast(GetNetmaskCIDR()), IP2STR(m_IpInfo.secondary_ip.addr)); - printf(" Gateway : " IPSTR "\n", IP2STR(m_IpInfo.gw.addr)); + printf(" IfName : %u: %s " MACSTR "\n", static_cast(GetIfIndex()), m_aIfName, MAC2STR(net::netif_hwaddr())); + printf(" Primary : " IPSTR "/%u (HTTP only " IPSTR ")\n", IP2STR(net::netif_ipaddr()), static_cast(GetNetmaskCIDR()), IP2STR(net::netif_secondary_ipaddr())); + printf(" Gateway : " IPSTR "\n", IP2STR(net::netif_gw())); printf(" Broadcast : " IPSTR "\n", IP2STR(GetBroadcastIp())); } diff --git a/lib-network/src/emac/phy/link_handle_change.cpp b/lib-network/src/emac/phy/link_handle_change.cpp index 08e8b2c4b..44bd517cc 100755 --- a/lib-network/src/emac/phy/link_handle_change.cpp +++ b/lib-network/src/emac/phy/link_handle_change.cpp @@ -25,6 +25,7 @@ #include "hardware.h" #include "network.h" +#include "netif.h" #include "debug.h" @@ -38,26 +39,25 @@ namespace net { void link_handle_change(const net::Link state) { DEBUG_PRINTF("net::Link %s", state == net::Link::STATE_UP ? "UP" : "DOWN"); - if (net::Link::STATE_UP == state) { + if (Link::STATE_UP == state) { const bool isWatchdog = Hardware::Get()->IsWatchdog(); if (isWatchdog) { Hardware::Get()->WatchdogStop(); } - net::PhyStatus phyStatus; - net::phy_start(PHY_ADDRESS, phyStatus); + PhyStatus phyStatus; + phy_start(PHY_ADDRESS, phyStatus); emac_adjust_link(phyStatus); - Network::Get()->Start(net::Link::STATE_UP); - - network::mdns_announcement(); - - Network::Get()->Print(); - if (isWatchdog) { Hardware::Get()->WatchdogInit(); } + + netif_set_link_up(); + return; } + + netif_set_link_down(); } } // namespace net diff --git a/lib-network/src/emac/phy/rtl8201f/net_phy.cpp b/lib-network/src/emac/phy/rtl8201f/net_phy.cpp index f8c543326..114a0d154 100755 --- a/lib-network/src/emac/phy/rtl8201f/net_phy.cpp +++ b/lib-network/src/emac/phy/rtl8201f/net_phy.cpp @@ -2,7 +2,7 @@ * phy.cpp * */ -/* Copyright (C) 2023 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -83,7 +83,11 @@ void phy_customized_timing() { # define RMSR_RX_TIMING_VAL 0x4 # define RMSR_TX_TIMING_SHIFT 8 # define RMSR_TX_TIMING_MASK 0xF00 -# define RMSR_TX_TIMING_VAL 0xF +# if defined (GD32F407) +# define RMSR_TX_TIMING_VAL 0x2 // The GD32F407 is now running at 200MHz +# else +# define RMSR_TX_TIMING_VAL 0xF +# endif constexpr uint16_t phy_value = (RMSR_RX_TIMING_VAL << RMSR_RX_TIMING_SHIFT) | (RMSR_TX_TIMING_VAL << RMSR_TX_TIMING_SHIFT); diff --git a/lib-network/src/esp8266/network.cpp b/lib-network/src/esp8266/network.cpp index a9b61f208..27d1819cc 100644 --- a/lib-network/src/esp8266/network.cpp +++ b/lib-network/src/esp8266/network.cpp @@ -106,14 +106,14 @@ void Network::JoinGroup([[maybe_unused]] int32_t nHandle, uint32_t nIp) { esp8266_write_word(nIp); } -uint16_t Network::RecvFrom([[maybe_unused]] int32_t nHandle, void *pBuffer, uint16_t nLength, uint32_t *from_ip, uint16_t* from_port) { +uint32_t Network::RecvFrom([[maybe_unused]] int32_t nHandle, void *pBuffer, uint32_t nLength, uint32_t *from_ip, uint16_t* from_port) { assert(pBuffer != nullptr); assert(from_ip != nullptr); assert(from_port != nullptr); esp8266_write_4bits(CMD_WIFI_UDP_RECEIVE); - auto nBytesReceived = esp8266_read_halfword(); + uint32_t nBytesReceived = esp8266_read_halfword(); if (nBytesReceived != 0) { *from_ip = esp8266_read_word(); @@ -131,12 +131,12 @@ uint16_t Network::RecvFrom([[maybe_unused]] int32_t nHandle, void *pBuffer, uint static uint8_t s_ReadBuffer[MAX_SEGMENT_LENGTH]; -uint16_t Network::RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort) { +uint32_t Network::RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort) { *ppBuffer = &s_ReadBuffer; return RecvFrom(nHandle, s_ReadBuffer, MAX_SEGMENT_LENGTH, pFromIp, pFromPort); } -void Network::SendTo([[maybe_unused]] int32_t nHandle, const void *pBuffer, uint16_t nLength, uint32_t to_ip, uint16_t remote_port) { +void Network::SendTo([[maybe_unused]] int32_t nHandle, const void *pBuffer, uint32_t nLength, uint32_t to_ip, uint16_t remote_port) { assert(pBuffer != nullptr); esp8266_write_4bits(CMD_WIFI_UDP_SEND); diff --git a/lib-network/src/linux/network.cpp b/lib-network/src/linux/network.cpp index 0c25192af..6281b0ff1 100644 --- a/lib-network/src/linux/network.cpp +++ b/lib-network/src/linux/network.cpp @@ -77,6 +77,7 @@ Network::Network(int argc, char **argv) { m_aHostName[0] = '\0'; m_aDomainName[0] = '\0'; m_aIfName[0] = '\0'; + memset(&m_nNameservers, 0, sizeof(m_nNameservers)); /** * BEGIN - needed H3 code compatibility @@ -380,7 +381,7 @@ void Network::LeaveGroup(int32_t nHandle, uint32_t ip) { } } -uint16_t Network::RecvFrom(int32_t nHandle, void *pPacket, uint16_t nSize, uint32_t *pFromIp, uint16_t *pFromPort) { +uint32_t Network::RecvFrom(int32_t nHandle, void *pPacket, uint32_t nSize, uint32_t *pFromIp, uint16_t *pFromPort) { assert(pPacket != nullptr); assert(pFromIp != nullptr); assert(pFromPort != nullptr); @@ -404,12 +405,12 @@ uint16_t Network::RecvFrom(int32_t nHandle, void *pPacket, uint16_t nSize, uint3 return recv_len; } -uint16_t Network::RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort) { +uint32_t Network::RecvFrom(int32_t nHandle, const void **ppBuffer, uint32_t *pFromIp, uint16_t *pFromPort) { *ppBuffer = &s_ReadBuffer; return RecvFrom(nHandle, s_ReadBuffer, MAX_SEGMENT_LENGTH, pFromIp, pFromPort); } -void Network::SendTo(int32_t nHandle, const void *pPacket, uint16_t nSize, uint32_t nToIp, uint16_t nRemotePort) { +void Network::SendTo(int32_t nHandle, const void *pPacket, uint32_t nSize, uint32_t nToIp, uint16_t nRemotePort) { struct sockaddr_in si_other; socklen_t slen = sizeof(si_other); @@ -575,57 +576,91 @@ void Network::SetHostName(const char *pHostName) { // COMMON -void Network::SetQueuedStaticIp(uint32_t nLocalIp, uint32_t nNetmask) { +void Network::SetQueuedStaticIp(const uint32_t nStaticIp, const uint32_t nNetmask) { DEBUG_ENTRY - DEBUG_PRINTF(IPSTR ", nNetmask=" IPSTR, IP2STR(nLocalIp), IP2STR(nNetmask)); + DEBUG_PRINTF(IPSTR ", nNetmask=" IPSTR, IP2STR(nStaticIp), IP2STR(nNetmask)); - if (nLocalIp != 0) { - m_QueuedConfig.nLocalIp = nLocalIp; + if (nStaticIp != 0) { + m_QueuedConfig.nStaticIp = nStaticIp; + } else { + m_QueuedConfig.nStaticIp = GetIp(); } if (nNetmask != 0) { m_QueuedConfig.nNetmask = nNetmask; + } else { + m_QueuedConfig.nNetmask = GetNetmask(); } m_QueuedConfig.nMask |= QueuedConfig::STATIC_IP; - m_QueuedConfig.nMask |= QueuedConfig::NET_MASK; + m_QueuedConfig.nMask |= QueuedConfig::NETMASK; DEBUG_EXIT } +void Network::SetQueuedDefaultRoute(const uint32_t nGatewayIp) { + if (nGatewayIp != 0) { + m_QueuedConfig.nGateway = nGatewayIp; + } else { + m_QueuedConfig.nGateway = GetGatewayIp(); + } + + m_QueuedConfig.nMask |= QueuedConfig::GW; +} + bool Network::ApplyQueuedConfig() { DEBUG_ENTRY - DEBUG_PRINTF("m_QueuedConfig.nMask=%x, " IPSTR ", " IPSTR, m_QueuedConfig.nMask, IP2STR(m_QueuedConfig.nLocalIp), IP2STR(m_QueuedConfig.nNetmask)); + DEBUG_PRINTF("m_QueuedConfig.nMask=%x, " IPSTR ", " IPSTR, m_QueuedConfig.nMask, IP2STR(m_QueuedConfig.nStaticIp), IP2STR(m_QueuedConfig.nNetmask)); if (m_QueuedConfig.nMask == QueuedConfig::NONE) { DEBUG_EXIT return false; } - if ((isQueuedMaskSet(QueuedConfig::STATIC_IP)) || (isQueuedMaskSet(QueuedConfig::NET_MASK))) { - if (isQueuedMaskSet(QueuedConfig::NET_MASK)) { + if ((isQueuedMaskSet(QueuedConfig::STATIC_IP)) || (isQueuedMaskSet(QueuedConfig::NETMASK)) || (isQueuedMaskSet(QueuedConfig::GW))) { + // After SetIp all ip address might be zero. + if (isQueuedMaskSet(QueuedConfig::STATIC_IP)) { + SetIp(m_QueuedConfig.nStaticIp); + } + + if (isQueuedMaskSet(QueuedConfig::NETMASK)) { SetNetmask(m_QueuedConfig.nNetmask); - m_QueuedConfig.nMask &= ~(QueuedConfig::NET_MASK); } - if (isQueuedMaskSet(QueuedConfig::STATIC_IP)) { - SetIp(m_QueuedConfig.nLocalIp); - m_QueuedConfig.nMask &= ~(QueuedConfig::STATIC_IP); + if (isQueuedMaskSet(QueuedConfig::GW)) { + SetGatewayIp(m_QueuedConfig.nGateway); } + + m_QueuedConfig.nMask = QueuedConfig::NONE; + + DEBUG_EXIT + return true; } if (isQueuedMaskSet(QueuedConfig::DHCP)) { - EnableDhcp(); - m_QueuedConfig.nMask &= ~(QueuedConfig::DHCP); + if (m_QueuedConfig.mode == network::dhcp::Mode::ACTIVE) { + EnableDhcp(); + } else if (m_QueuedConfig.mode == network::dhcp::Mode::INACTIVE) { + + } + + m_QueuedConfig.mode = network::dhcp::Mode::UNKNOWN; + m_QueuedConfig.nMask = QueuedConfig::NONE; + + DEBUG_EXIT + return true; } if (isQueuedMaskSet(QueuedConfig::ZEROCONF)) { SetZeroconf(); - m_QueuedConfig.nMask &= ~(QueuedConfig::ZEROCONF); + m_QueuedConfig.nMask = QueuedConfig::NONE; + + DEBUG_EXIT + return true; } DEBUG_EXIT - return true; + return false; } void Network::Print() { diff --git a/lib-network/src/net/acd.cpp b/lib-network/src/net/acd.cpp new file mode 100755 index 000000000..ea97ef630 --- /dev/null +++ b/lib-network/src/net/acd.cpp @@ -0,0 +1,328 @@ +/** + * @file acd.cpp + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* This code is inspired by the lwIP TCP/IP stack. + * https://savannah.nongnu.org/projects/lwip/ + */ +/** + * The acp.cpp aims to be conform to RFC 5227. + * https://datatracker.ietf.org/doc/html/rfc5227.html + * IPv4 Address Conflict Detection + */ + +#if defined (DEBUG_NET_ACD) +# undef NDEBUG +#endif + +#pragma GCC push_options +#pragma GCC optimize ("Os") + +#include +#include +#include +#include + +#include "../../config/net_config.h" + +#include "net/acd.h" +#include "net/protocol/acd.h" +#include "net/protocol/arp.h" +#include "net_memcpy.h" + +#include "hardware.h" +#include "debug.h" + +namespace net { +namespace acd { +static constexpr uint32_t ACD_TMR_INTERVAL = 100; +static constexpr uint32_t ACD_TICKS_PER_SECOND = (1000U / ACD_TMR_INTERVAL); +} // namespace acd + +static int32_t nTimerId; + +static void acd_timer() { + auto *acd = reinterpret_cast(globals::netif_default.acd); + assert(acd != nullptr); + + if (acd->lastconflict > 0) { + acd->lastconflict--; + } + + DEBUG_PRINTF("state=%u, ttw=%u", static_cast(acd->state), acd->ttw); + + if (acd->ttw > 0) { + acd->ttw--; + } + + switch (acd->state) { + case acd::State::ACD_STATE_PROBE_WAIT: + case acd::State::ACD_STATE_PROBING: + if (acd->ttw == 0) { + acd->state = acd::State::ACD_STATE_PROBING; + arp_acd_probe(acd->ipaddr); + DEBUG_PUTS("PROBING Sent Probe"); + acd->sent_num++; + if (acd->sent_num >= PROBE_NUM) { + acd->state = acd::State::ACD_STATE_ANNOUNCE_WAIT; + acd->sent_num = 0; + acd->ttw = static_cast(ANNOUNCE_WAIT * acd::ACD_TICKS_PER_SECOND); + } else { + acd->ttw = static_cast(random() % (((PROBE_MAX - PROBE_MIN) * acd::ACD_TICKS_PER_SECOND)) + (PROBE_MIN * acd::ACD_TICKS_PER_SECOND)); + } + } + break; + case acd::State::ACD_STATE_ANNOUNCE_WAIT: + case acd::State::ACD_STATE_ANNOUNCING: + if (acd->ttw == 0) { + if (acd->sent_num == 0) { + acd->state = acd::State::ACD_STATE_ANNOUNCING; + acd->num_conflicts = 0; + } + arp_acd_send_announcement(acd->ipaddr); + DEBUG_PUTS("ANNOUNCING Sent Announce"); + acd->ttw = static_cast(ANNOUNCE_INTERVAL * acd::ACD_TICKS_PER_SECOND); + acd->sent_num++; + + if (acd->sent_num >= ANNOUNCE_NUM) { + acd->state = acd::State::ACD_STATE_ONGOING; + acd->sent_num = 0; + acd->ttw = 0; + acd->acd_conflict_callback(acd::Callback::ACD_IP_OK); + } + } + break; + case acd::State::ACD_STATE_RATE_LIMIT: + if (acd->ttw == 0) { + acd_stop(acd); + acd->acd_conflict_callback(acd::Callback::ACD_RESTART_CLIENT); + } + break; + default: + break; + } +} + +static void acd_restart(struct acd::Acd *acd) { + acd->num_conflicts++; + acd->acd_conflict_callback(acd::Callback::ACD_DECLINE); + + if (acd->num_conflicts >= MAX_CONFLICTS) { + acd->state = acd::State::ACD_STATE_RATE_LIMIT; + acd->ttw = static_cast(RATE_LIMIT_INTERVAL * acd::ACD_TICKS_PER_SECOND); + DEBUG_PUTS("rate limiting initiated. too many conflicts"); + } + else { + acd_stop(acd); + acd->acd_conflict_callback(acd::Callback::ACD_RESTART_CLIENT); + } +} + +static void acd_handle_arp_conflict(struct acd::Acd *acd) { + /* RFC5227, 2.4 "Ongoing Address Conflict Detection and Address Defense" + allows three options where: + a) means retreat on the first conflict, + b) allows to keep an already configured address when having only one + conflict in DEFEND_INTERVAL seconds and + c) the host will not give up it's address and defend it indefinitely + + We use option b) when the acd module represents the netif address, since it + helps to improve the chance that one of the two conflicting hosts may be + able to retain its address. while we are flexible enough to help network + performance + + We use option a) when the acd module does not represent the netif address, + since we cannot have the acd module announcing or restarting. This + situation occurs for the LL acd module when a routable address is used on + the netif but the LL address is still open in the background. */ + + if (acd->state == acd::State::ACD_STATE_PASSIVE_ONGOING) { + DEBUG_PUTS("conflict when we are in passive mode -> back off"); + acd_stop(acd); + acd->acd_conflict_callback(acd::Callback::ACD_DECLINE); + } + else { + if (acd->lastconflict > 0) { + DEBUG_PUTS("conflict within DEFEND_INTERVAL -> retreating"); + acd_restart(acd); + } else { + DEBUG_PUTS("we are defending, send ARP Announce"); + arp_acd_send_announcement(acd->ipaddr); + acd->lastconflict = DEFEND_INTERVAL * acd::ACD_TICKS_PER_SECOND; + } + } +} + +static void acd_put_in_passive_mode() { + auto *acd = reinterpret_cast(globals::netif_default.acd); + assert(acd != nullptr); + + switch (acd->state) { + case acd::State::ACD_STATE_OFF: + case acd::State::ACD_STATE_PASSIVE_ONGOING: + default: + /* do nothing */ + break; + case acd::State::ACD_STATE_PROBE_WAIT: + case acd::State::ACD_STATE_PROBING: + case acd::State::ACD_STATE_ANNOUNCE_WAIT: + case acd::State::ACD_STATE_RATE_LIMIT: + acd_stop(acd); + acd->acd_conflict_callback(acd::Callback::ACD_DECLINE); + break; + case acd::State::ACD_STATE_ANNOUNCING: + case acd::State::ACD_STATE_ONGOING: + acd->state = acd::State::ACD_STATE_PASSIVE_ONGOING; + break; + } +} + +/* + * Public interface + */ + +void acd_start(struct acd::Acd *acd, const ip4_addr_t ipaddr) { + DEBUG_ENTRY + assert(acd != nullptr); + + acd->ipaddr.addr = ipaddr.addr; + acd->state = acd::State::ACD_STATE_PROBE_WAIT; + acd->ttw = static_cast(random() % (PROBE_WAIT * acd::ACD_TICKS_PER_SECOND)); + + nTimerId = Hardware::Get()->SoftwareTimerAdd(acd::ACD_TMR_INTERVAL, acd_timer); + assert(nTimerId >= 0); + + DEBUG_EXIT +} + +void acd_stop(struct acd::Acd *acd) { + DEBUG_ENTRY + assert(acd != nullptr); + + acd->state = acd::State::ACD_STATE_OFF; + + assert(nTimerId >= 0); + Hardware::Get()->SoftwareTimerDelete(nTimerId); + nTimerId = -1; + + DEBUG_EXIT +} + +void acd_network_changed_link_down() { + DEBUG_ENTRY + + auto *acd = reinterpret_cast(globals::netif_default.acd); + acd_stop(acd); + + DEBUG_EXIT +} + +void acd_arp_reply(struct t_arp *pArp) { + DEBUG_ENTRY + auto *acd = reinterpret_cast(globals::netif_default.acd); + + switch (acd->state) { + case acd::State::ACD_STATE_OFF: + case acd::State::ACD_STATE_RATE_LIMIT: + default: + break; + case acd::State::ACD_STATE_PROBE_WAIT: + case acd::State::ACD_STATE_PROBING: + case acd::State::ACD_STATE_ANNOUNCE_WAIT: + /* RFC 5227 Section 2.1.1: + * from beginning to after ANNOUNCE_WAIT seconds we have a conflict if + * ip.sender == ipaddr (someone is already using the address) + * OR + * ip.dst == ipaddr && hw.src != own macAddress (someone else is probing it) + */ + if (((memcpy_ip(pArp->arp.sender_ip) == acd->ipaddr.addr)) + || (!(memcpy_ip(pArp->arp.sender_ip) == 0) + && ((memcpy_ip(pArp->arp.target_ip)) == acd->ipaddr.addr) + && (memcmp(pArp->arp.sender_mac, globals::netif_default.hwaddr, ETH_ADDR_LEN) == 0))) + { + DEBUG_PUTS("Probe Conflict detected"); + acd_restart(acd); + } + break; + case acd::State::ACD_STATE_ANNOUNCING: + case acd::State::ACD_STATE_ONGOING: + case acd::State::ACD_STATE_PASSIVE_ONGOING: + /* RFC 5227 Section 2.4: + * in any state we have a conflict if + * ip.sender == ipaddr && hw.src != own macAddress (someone is using our address) + */ + if ((memcpy_ip(pArp->arp.sender_ip) == acd->ipaddr.addr) + && (memcmp(pArp->arp.sender_mac, globals::netif_default.hwaddr, ETH_ADDR_LEN) != 0)) { + DEBUG_PUTS("Conflicting ARP-Packet detected"); + acd_handle_arp_conflict(acd); + } + break; + } + + DEBUG_EXIT +} + +void acd_add(struct acd::Acd *pAcd, acd_conflict_callback_t acd_conflict_callback) { + DEBUG_ENTRY + assert(pAcd != nullptr); + assert(acd_conflict_callback != nullptr); + + pAcd->acd_conflict_callback = acd_conflict_callback; + + auto &netif = globals::netif_default; + netif.acd = pAcd; + + DEBUG_EXIT +} + +void acd_remove(struct acd::Acd *pAcd) { + DEBUG_ENTRY + + assert(pAcd != nullptr); + auto &netif = globals::netif_default; + + if (netif.acd == pAcd) { + netif.acd = nullptr; + + DEBUG_EXIT + return; + } + + DEBUG_EXIT +} + +void acd_netif_ip_addr_changed(const ip4_addr_t old_addr, const ip4_addr_t new_addr) { + if ((old_addr.addr == 0) || (new_addr.addr == 0)) { + return; + } + + auto *acd = reinterpret_cast(globals::netif_default.acd); + + if (acd->ipaddr.addr == old_addr.addr) { + /* Did we change from a LL address to a routable address? */ + if (network::is_linklocal_ip(old_addr.addr) && !network::is_linklocal_ip(new_addr.addr)) { + /* Put the module in passive conflict detection mode */ + acd_put_in_passive_mode(); + } + } +} +} // namespace net diff --git a/lib-network/src/apps/mdns/mdns.cpp b/lib-network/src/net/apps/mdns/mdns.cpp similarity index 88% rename from lib-network/src/apps/mdns/mdns.cpp rename to lib-network/src/net/apps/mdns/mdns.cpp index e09fc59f3..669588ce9 100755 --- a/lib-network/src/apps/mdns/mdns.cpp +++ b/lib-network/src/net/apps/mdns/mdns.cpp @@ -2,7 +2,7 @@ * @file mdns.cpp * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,13 +23,21 @@ * THE SOFTWARE. */ +#if defined (DEBUG_NET_APPS_MDNS) +# if defined (NDEBUG) +# undef NDEBUG +# endif +#endif + #include #include #include #include #include -#include "mdns.h" +#include "net/apps/mdns.h" +#include "net/protocol/ip4.h" +#include "net/protocol/iana.h" #include "network.h" #include "hardware.h" @@ -43,10 +51,6 @@ static constexpr auto SERVICE_RECORDS_MAX = 8; static constexpr auto SERVICE_RECORDS_MAX = MDNS_SERVICE_RECORDS_MAX; #endif -static constexpr uint32_t MULTICAST_MESSAGE_SIZE = 512; ///< The 1987 DNS specification [RFC1035] restricts DNS messages carried by UDP to no more than 512 bytes -static constexpr uint32_t MULTICAST_ADDRESS = network::convert_to_uint(224, 0, 0, 251); -static constexpr uint16_t UDP_PORT = 5353; - static constexpr uint32_t MDNS_RESPONSE_TTL = 3600; ///< (in seconds) static constexpr size_t DOMAIN_MAXLEN = 256; @@ -69,24 +73,6 @@ static constexpr char DOMAIN_OSC[] = { 4 , '_','o','s','c'}; static constexpr char DOMAIN_DDP[] = { 4 , '_','d','d','p'}; static constexpr char DOMAIN_PP[] = { 3 , '_','p','p'}; -enum class Flags1 : uint8_t { - RESPONSE = 0x80, ///< query (0), or a response (1). - OPCODE_STATUS = 0x10, ///< a server status request (STATUS) - OPCODE_IQUERY = 0x08, ///< an inverse query (IQUERY) - OPCODE_STANDARD = 0x00, ///< (RFC 6762, section 18.3) - AUTHORATIVE = 0x04, ///< Authoritative Answer - TRUNC = 0x02, ///< TrunCation - RD = 0x01 ///< If RD is set, it directs the name server to pursue the query recursively. -}; - -enum class Classes : uint16_t { - Internet = 1, Any = 255, Flush = 0x8000 -}; - -enum class Types : uint16_t { - A = 1, PTR = 12, TXT = 16, SRV = 33, ALL = 255 -}; - enum class HostReply : uint32_t { A = 0x01, PTR = 0x02 }; @@ -206,20 +192,12 @@ static constexpr Domain DOMAIN_DNSSD { static ServiceRecord s_ServiceRecords[mdns::SERVICE_RECORDS_MAX]; static HostReply s_HostReplies; static ServiceReply s_ServiceReplies; -static uint8_t s_RecordsData[MULTICAST_MESSAGE_SIZE]; +static uint8_t s_RecordsData[net::dns::MULTICAST_MESSAGE_SIZE]; static bool s_isUnicast; static bool s_bLegacyQuery; } // namespace mdns -static constexpr uint8_t operator| (mdns::Flags1 a, mdns::Flags1 b) { - return static_cast((static_cast(a) | static_cast(b))); -} - -static constexpr uint16_t operator| (mdns::Classes a, mdns::Classes b) { - return static_cast((static_cast(a) | static_cast(b))); -} - static constexpr mdns::HostReply operator| (mdns::HostReply a, mdns::HostReply b) { return static_cast((static_cast(a) | static_cast(b))); } @@ -239,7 +217,7 @@ static constexpr mdns::ServiceReply operator& (mdns::ServiceReply a, mdns::Servi int32_t MDNS::s_nHandle; uint32_t MDNS::s_nRemoteIp; uint16_t MDNS::s_nRemotePort; -uint16_t MDNS::s_nBytesReceived; +uint32_t MDNS::s_nBytesReceived; uint8_t *MDNS::s_pReceiveBuffer; MDNS *MDNS::s_pThis; @@ -303,7 +281,7 @@ static void create_reverse_domain(Domain &domain) { auto nIp = Network::Get()->GetIp(); const auto *pIp = reinterpret_cast(&nIp); - for (int32_t i = network::IP_SIZE - 1; i >= 0; i--) { + for (int32_t i = IPv4_ADDR_LEN - 1; i >= 0; i--) { char buffer[3]; uint32_t nLength = 1; @@ -439,12 +417,12 @@ static uint8_t *put_domain_name_as_labels(uint8_t *ptr, Domain const &domain) { return ptr; } -static uint8_t *add_question(uint8_t *pDestination, const Domain& domain, const Types type, const bool bFlush) { +static uint8_t *add_question(uint8_t *pDestination, const Domain& domain, const net::dns::RRType type, const bool bFlush) { auto *pDst = put_domain_name_as_labels(pDestination, domain); *reinterpret_cast(pDst) = __builtin_bswap16(static_cast(type)); pDst += 2; - *reinterpret_cast(pDst) = __builtin_bswap16((bFlush ? Classes::Flush : static_cast(0)) | Classes::Internet); + *reinterpret_cast(pDst) = __builtin_bswap16((bFlush ? net::dns::RRClass::RRCLASS_FLUSH : static_cast(0)) | net::dns::RRClass::RRCLASS_INTERNET); pDst += 2; return pDst; @@ -456,7 +434,7 @@ static uint32_t add_answer_srv(mdns::ServiceRecord const& serviceRecord, uint8_t Domain domain; create_service_domain(domain, serviceRecord, true); - auto *pDst = add_question(pDestination, domain, Types::SRV, true); + auto *pDst = add_question(pDestination, domain, net::dns::RRType::RRTYPE_SRV, true); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -483,7 +461,7 @@ static uint32_t add_answer_txt(mdns::ServiceRecord const& serviceRecord, uint8_t Domain domain; create_service_domain(domain, serviceRecord, true); - auto *pDst = add_question(pDestination, domain, Types::TXT, true); + auto *pDst = add_question(pDestination, domain, net::dns::RRType::RRTYPE_TXT, true); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -513,7 +491,7 @@ static uint32_t add_answer_ptr(mdns::ServiceRecord const& serviceRecord, uint8_t Domain domain; create_service_domain(domain, serviceRecord, false); - auto *pDst = add_question(pDestination, domain, Types::PTR, false); + auto *pDst = add_question(pDestination, domain, net::dns::RRType::RRTYPE_PTR, false); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -533,7 +511,7 @@ static uint32_t add_answer_ptr(mdns::ServiceRecord const& serviceRecord, uint8_t static uint32_t add_answer_dnsd_ptr(mdns::ServiceRecord const& serviceRecord, uint8_t *pDestination, const uint32_t nTTL) { DEBUG_ENTRY - auto *pDst = add_question(pDestination, DOMAIN_DNSSD, Types::PTR, false); + auto *pDst = add_question(pDestination, DOMAIN_DNSSD, net::dns::RRType::RRTYPE_PTR, false); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -558,7 +536,7 @@ static uint32_t add_answer_a(uint8_t *pDestination, const uint32_t nTTL) { Domain domain; create_host_domain(domain); - auto *pDst = add_question(pDestination, domain, Types::A, true); + auto *pDst = add_question(pDestination, domain, net::dns::RRType::RRTYPE_A, true); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -578,7 +556,7 @@ static uint32_t add_answer_hostv4_ptr(uint8_t *pDestination, const uint32_t nTTL Domain domain; create_reverse_domain(domain); - auto *pDst = add_question(pDestination, domain, Types::PTR, true); + auto *pDst = add_question(pDestination, domain, net::dns::RRType::RRTYPE_PTR, true); *reinterpret_cast(pDst) = __builtin_bswap32(nTTL); pDst += 4; @@ -675,14 +653,14 @@ void MDNS::SendAnswerLocalIpAddress(const uint16_t nTransActionID, const uint32_ DEBUG_ENTRY uint32_t nAnswers = 0; - uint8_t *pDst = reinterpret_cast(&s_RecordsData) + sizeof(struct Header); + uint8_t *pDst = reinterpret_cast(&s_RecordsData) + sizeof(struct net::dns::Header); #if defined (CONFIG_MDNS_DOMAIN_REVERSE) if ((HostReply::PTR & s_HostReplies) == HostReply::PTR) { if (s_bLegacyQuery) { Domain domain; create_reverse_domain(domain); - pDst = add_question(pDst, domain, Types::PTR, false); + pDst = add_question(pDst, domain, net::dns::RRType::RRTYPE_PTR, false); } } #endif @@ -698,10 +676,10 @@ void MDNS::SendAnswerLocalIpAddress(const uint16_t nTransActionID, const uint32_ } #endif - auto *pHeader = reinterpret_cast(&s_RecordsData); + auto *pHeader = reinterpret_cast< net::dns::Header *>(&s_RecordsData); pHeader->xid = nTransActionID; - pHeader->nFlag1 = Flags1::RESPONSE | Flags1::AUTHORATIVE; + pHeader->nFlag1 = net::dns::Flag1::FLAG1_RESPONSE | net::dns::Flag1::FLAG1_AUTHORATIVE; pHeader->nFlag2 = 0; #if defined (CONFIG_MDNS_DOMAIN_REVERSE) pHeader->nQueryCount = __builtin_bswap16(static_cast(s_bLegacyQuery)); @@ -726,10 +704,10 @@ MDNS::MDNS() { record.services = Services::LAST_NOT_USED; } - s_nHandle = Network::Get()->Begin(mdns::UDP_PORT); + s_nHandle = Network::Get()->Begin(net::iana::IANA_PORT_MDNS); assert(s_nHandle != -1); - Network::Get()->JoinGroup(s_nHandle, mdns::MULTICAST_ADDRESS); + Network::Get()->JoinGroup(s_nHandle, net::dns::MULTICAST_ADDRESS); Network::Get()->SetDomainName(&DOMAIN_LOCAL[1]); SendAnnouncement(MDNS_RESPONSE_TTL); @@ -748,15 +726,15 @@ MDNS::~MDNS() { } } - Network::Get()->LeaveGroup(s_nHandle, mdns::MULTICAST_ADDRESS); - Network::Get()->End(mdns::UDP_PORT); + Network::Get()->LeaveGroup(s_nHandle, net::dns::MULTICAST_ADDRESS); + Network::Get()->End(net::iana::IANA_PORT_MDNS); s_nHandle = -1; } void MDNS::SendAnnouncement(const uint32_t nTTL) { DEBUG_ENTRY - s_nRemotePort = mdns::UDP_PORT; //FIXME Hack ;-) + s_nRemotePort = net::iana::IANA_PORT_MDNS; //FIXME Hack ;-) s_HostReplies = HostReply::A; SendAnswerLocalIpAddress(0, nTTL); @@ -812,7 +790,7 @@ bool MDNS::ServiceRecordAdd(const char *pName, const mdns::Services services, co record.nTextContentLength = static_cast(nLength); } - s_nRemotePort = mdns::UDP_PORT; //FIXME Hack ;-) + s_nRemotePort = net::iana::IANA_PORT_MDNS; //FIXME Hack ;-) s_ServiceReplies = ServiceReply::TYPE_PTR | ServiceReply::NAME_PTR @@ -853,9 +831,9 @@ bool MDNS::ServiceRecordDelete(const mdns::Services service) { return false; } -void MDNS::SendTo(const uint16_t nLength) { +void MDNS::SendTo(const uint32_t nLength) { if (!s_isUnicast) { - Network::Get()->SendTo(s_nHandle, s_RecordsData, nLength, mdns::MULTICAST_ADDRESS, mdns::UDP_PORT); + Network::Get()->SendTo(s_nHandle, s_RecordsData, nLength, net::dns::MULTICAST_ADDRESS, net::iana::IANA_PORT_MDNS); return; } @@ -866,7 +844,7 @@ void MDNS::SendMessage(mdns::ServiceRecord const& serviceRecord, const uint16_t DEBUG_ENTRY uint32_t nAnswers = 0; - auto *pDst = reinterpret_cast(&s_RecordsData) + sizeof(struct Header); + auto *pDst = reinterpret_cast(&s_RecordsData) + sizeof(struct net::dns::Header); if ((s_ServiceReplies & ServiceReply::TYPE_PTR) == ServiceReply::TYPE_PTR) { nAnswers++; @@ -890,10 +868,10 @@ void MDNS::SendMessage(mdns::ServiceRecord const& serviceRecord, const uint16_t pDst += add_answer_a(pDst, nTT); - auto *pHeader = reinterpret_cast
(&s_RecordsData); + auto *pHeader = reinterpret_cast(&s_RecordsData); pHeader->xid = nTransActionID; - pHeader->nFlag1 = Flags1::RESPONSE | Flags1::AUTHORATIVE; + pHeader->nFlag1 = net::dns::Flag1::FLAG1_RESPONSE | net::dns::Flag1::FLAG1_AUTHORATIVE; pHeader->nFlag2 = 0; pHeader->nQueryCount = 0; pHeader->nAnswerCount = __builtin_bswap16(static_cast(nAnswers)); @@ -911,12 +889,12 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { DEBUG_PRINTF("nQuestions=%u", nQuestions); s_HostReplies = static_cast(0); - s_isUnicast = (s_nRemotePort != mdns::UDP_PORT); + s_isUnicast = (s_nRemotePort != net::iana::IANA_PORT_MDNS); s_bLegacyQuery = s_isUnicast && (nQuestions == 1); const auto nTransactionID = s_bLegacyQuery ? *reinterpret_cast(&s_pReceiveBuffer[0]) : static_cast(0); - uint32_t nOffset = sizeof(struct Header); + uint32_t nOffset = sizeof(struct net::dns::Header); for (uint32_t i = 0; i < nQuestions; i++) { Domain resourceDomain; @@ -930,10 +908,10 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { resourceDomain.nLength = static_cast(pResult - &s_pReceiveBuffer[nOffset]); nOffset += resourceDomain.nLength; - const auto nType = static_cast(__builtin_bswap16(*reinterpret_cast(&s_pReceiveBuffer[nOffset]))); + const auto nType = static_cast(__builtin_bswap16(*reinterpret_cast(&s_pReceiveBuffer[nOffset]))); nOffset += 2; - const auto nClass = static_cast(__builtin_bswap16(*reinterpret_cast(&s_pReceiveBuffer[nOffset])) & 0x7F); + const auto nClass = static_cast(__builtin_bswap16(*reinterpret_cast(&s_pReceiveBuffer[nOffset])) & 0x7F); nOffset += 2; #ifndef NDEBUG @@ -941,7 +919,7 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { printf(" ==> Type : %d, Class: %d\n", static_cast(nType), static_cast(nClass)); #endif - if ((nClass != Classes::Internet) && (nClass != Classes::Any)) { + if ((nClass != net::dns::RRClass::RRCLASS_INTERNET) && (nClass != net::dns::RRClass::RRCLASS_ANY)) { continue; } @@ -951,7 +929,7 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { Domain domainHost; - if ((nType == Types::A) || (nType == Types::ALL)) { + if ((nType == net::dns::RRType::RRTYPE_A) || (nType == net::dns::RRType::RRTYPE_ALL)) { DEBUG_PUTS(""); create_host_domain(domainHost); @@ -961,7 +939,7 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { } #if defined (CONFIG_MDNS_DOMAIN_REVERSE) - if (nType == Types::PTR || nType == Types::ALL) { + if (nType == net::dns::RRType::RRTYPE_PTR || nType == net::dns::RRType::RRTYPE_ALL) { DEBUG_PUTS(""); create_reverse_domain(domainHost); @@ -981,7 +959,7 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { s_ServiceReplies = static_cast(0); Domain serviceDomain; - if (nType == Types::PTR || nType == Types::ALL) { + if (nType == net::dns::RRType::RRTYPE_PTR || nType == net::dns::RRType::RRTYPE_ALL) { if (DOMAIN_DNSSD == resourceDomain) { s_ServiceReplies = s_ServiceReplies | ServiceReply::TYPE_PTR; } @@ -996,11 +974,11 @@ void MDNS::HandleQuestions(const uint32_t nQuestions) { create_service_domain(serviceDomain, record, true); if (serviceDomain == resourceDomain) { - if ((nType == Types::SRV) || (nType == Types::ALL)) { + if ((nType == net::dns::RRType::RRTYPE_SRV) || (nType == net::dns::RRType::RRTYPE_ALL)) { s_ServiceReplies = s_ServiceReplies | ServiceReply::SRV; } - if ((nType == Types::TXT) || (nType == Types::ALL)) { + if ((nType == net::dns::RRType::RRTYPE_TXT) || (nType == net::dns::RRType::RRTYPE_ALL)) { s_ServiceReplies = s_ServiceReplies | ServiceReply::TXT; } } diff --git a/lib-network/src/net/apps/ntp/gd32/ptp/net_ptp.cpp b/lib-network/src/net/apps/ntp/gd32/ptp/net_ptp.cpp new file mode 100644 index 000000000..4f69e6309 --- /dev/null +++ b/lib-network/src/net/apps/ntp/gd32/ptp/net_ptp.cpp @@ -0,0 +1,484 @@ +/** + * @file net_ptp.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * https://www.ietf.org/archive/id/draft-ietf-ntp-interleaved-modes-07.html#name-interleaved-client-server-m + */ +/* +Server t2 t3 t6 t7 t10 t11 + -----+----+----------------+----+----------------+----+----- + / \ / \ / \ +Client / \ / \ / \ + --+----------+----------+----------+----------+----------+-- + t1 t4 t5 t8 t9 t12 + +Mode: B B I I I I + +----+ +----+ +----+ +----+ +----+ +----+ +Org | 0 | | t1~| | t2 | | t4 | | t6 | | t8 | +Rx | 0 | | t2 | | t4 | | t6 | | t8 | |t10 | +Tx | t1~| | t3~| | t1 | | t3 | | t5 | | t7 | + +----+ +----+ +----+ +----+ +----+ +----+ + +T1 - local transmit timestamp of the latest request (t5) +T2 - remote receive timestamp from the latest response (t6) +T3 - remote transmit timestamp from the latest response (t3) +T4 - local receive timestamp of the previous response (t4) + */ + +#undef NDEBUG + +#if !defined (CONFIG_ENET_ENABLE_PTP) +# error +#endif +#if defined (ENABLE_NTP_CLIENT) +# error +#endif + +#pragma GCC push_options +#pragma GCC optimize ("O2") +#pragma GCC optimize ("no-tree-loop-distribute-patterns") + +#include +#include +#include +#include + +#include "hardware.h" +#include "network.h" +#include "networkparams.h" + +#include "net/protocol/ntp.h" + +#include "gd32_ptp.h" + +#include "debug.h" + +namespace net { +namespace globals { +extern uint32_t ptpTimestamp[2]; +} // namespace globals + +#define _NTPFRAC_(x) ( 4294U*static_cast(x) + ( (1981U*static_cast(x))>>11 ) + ((2911U*static_cast(x))>>28) ) +#define NTPFRAC(x) _NTPFRAC_(x / 1000) + +/** + * The reverse of the above, needed if we want to set our microsecond + * clock (via clock_settime) based on the incoming time in NTP format. + * Basically exact. + */ +#define USEC(x) ( ( (x) >> 12 ) - 759 * ( ( ( (x) >> 10 ) + 32768 ) >> 16 ) ) + +static constexpr uint32_t TIMEOUT_SECONDS = 3; +static constexpr uint8_t POLL_POWER = 3; +static constexpr uint32_t POLL_SECONDS = (1U << POLL_POWER); + +struct ntpClient { + uint32_t nServerIp; + int32_t nHandle; + ntp::Packet *pReply; + uint32_t nMillisRequest; + uint32_t nMillisLastPoll; + ntp::Status status; + ntp::Packet Request; + ntp::TimeStamp T1; // time request sent by client + ntp::TimeStamp T2; // time request received by server + ntp::TimeStamp T3; // time reply sent by server + ntp::TimeStamp T4; // time reply received by client + ntp::TimeStamp cookieBasic; + struct { + ntp::TimeStamp previousReceive; + ntp::TimeStamp dst; // destination timestamp + ntp::TimeStamp sentA; + ntp::TimeStamp sentB; + int32_t x; // interleave switch + uint32_t missedResponses; +#ifndef NDEBUG + ntp::Modes mode; +#endif + } state; +}; + +static ntpClient s_ntpClient; +static uint16_t s_id; +static constexpr uint16_t REQUEST_SIZE = sizeof s_ntpClient.Request; + +static void print(const char *pText, const struct ntp::TimeStamp *pNtpTime) { +#ifndef NDEBUG + const auto nSeconds = static_cast(pNtpTime->nSeconds - ntp::JAN_1970); + const auto *pTm = localtime(&nSeconds); + printf("%s %02d:%02d:%02d.%06d %04d [%u][0x%.8x]\n", pText, pTm->tm_hour, pTm->tm_min, pTm->tm_sec, USEC(pNtpTime->nFraction), pTm->tm_year + 1900, pNtpTime->nSeconds, pNtpTime->nFraction); +#endif +} + +void ptp_init() { + DEBUG_ENTRY + + memset(&s_ntpClient, 0, sizeof(struct ntpClient)); + s_ntpClient.state.previousReceive.nSeconds = ntp::JAN_1970; + s_ntpClient.state.dst.nSeconds = ntp::JAN_1970; + s_ntpClient.state.sentA.nSeconds = ntp::JAN_1970; + s_ntpClient.state.sentB.nSeconds = ntp::JAN_1970; + + s_ntpClient.state.missedResponses = 4; + + NetworkParams networkParams; + networkParams.Load(); + + s_ntpClient.nServerIp = networkParams.GetNtpServer(); + + if (s_ntpClient.nServerIp == 0) { + s_ntpClient.status = ntp::Status::STOPPED; + DEBUG_EXIT + return; + } + + struct timeval tv; + gettimeofday(&tv, nullptr); + srandom(static_cast(tv.tv_sec ^ tv.tv_usec)); + + s_ntpClient.Request.LiVnMode = ntp::VERSION | ntp::MODE_CLIENT; + s_ntpClient.Request.Poll = POLL_POWER; + + s_ntpClient.state.x = 1; + + s_ntpClient.nHandle = Network::Get()->Begin(ntp::UDP_PORT); + assert(s_ntpClient.nHandle != -1); + + s_ntpClient.status = ntp::Status::IDLE; + s_ntpClient.nMillisLastPoll = Hardware::Get()->Millis() - (1000U * POLL_SECONDS); + + DEBUG_PRINTF("Poll: %u", POLL_SECONDS); + DEBUG_EXIT +} + +void ptp_ntp_set_server_ip(const uint32_t nServerIp) { + s_ntpClient.nServerIp = nServerIp; +} + +void ptp_handle([[maybe_unused]] const uint8_t *pBuffer, [[maybe_unused]] const uint32_t nLength) { + /* Can only be used for PTP level 2 messages */ +} + +/** + * The interleaved client/server mode is similar to the basic client/ server mode. + * The difference between the two modes is in the values saved to the origin and transmit timestamp fields. + */ + +static bool send() { + s_ntpClient.state.missedResponses++; + + /** + * The first request from a client is always in the basic mode and so is the server response. + * It has a zero origin timestamp and zero receive timestamp. + * Only when the client receives a valid response from the server, + * it will be able to send a request in the interleaved mode + */ + if (s_ntpClient.state.missedResponses > 4) { + s_ntpClient.cookieBasic.nSeconds = random(); + s_ntpClient.cookieBasic.nFraction = 0; + + s_ntpClient.Request.OriginTimestamp_s = 0; + s_ntpClient.Request.OriginTimestamp_f = 0; + + s_ntpClient.Request.ReceiveTimestamp_s = 0; + s_ntpClient.Request.ReceiveTimestamp_f = 0; + + /** + * The origin timestamp is a cookie which is used to detect that a received packet + * is a response to the last packet sent in the other direction of the association. + */ + s_ntpClient.Request.TransmitTimestamp_s = __builtin_bswap32(s_ntpClient.cookieBasic.nSeconds); + s_ntpClient.Request.TransmitTimestamp_f = __builtin_bswap32(s_ntpClient.cookieBasic.nFraction); + } else { + /** + * A client request in the interleaved mode has an origin timestamp equal to + * the receive timestamp from the last valid server response. + */ + s_ntpClient.Request.OriginTimestamp_s = __builtin_bswap32(s_ntpClient.state.dst.nSeconds); + s_ntpClient.Request.OriginTimestamp_f = __builtin_bswap32(s_ntpClient.state.dst.nFraction); + + s_ntpClient.Request.ReceiveTimestamp_s = __builtin_bswap32(s_ntpClient.state.previousReceive.nSeconds); + s_ntpClient.Request.ReceiveTimestamp_f = __builtin_bswap32(s_ntpClient.state.previousReceive.nFraction); + + if (s_ntpClient.state.x > 0) { + s_ntpClient.Request.TransmitTimestamp_s = __builtin_bswap32(s_ntpClient.state.sentB.nSeconds); + s_ntpClient.Request.TransmitTimestamp_f = __builtin_bswap32(s_ntpClient.state.sentB.nFraction); + } else { + s_ntpClient.Request.TransmitTimestamp_s = __builtin_bswap32(s_ntpClient.state.sentA.nSeconds); + s_ntpClient.Request.TransmitTimestamp_f = __builtin_bswap32(s_ntpClient.state.sentA.nFraction); + } + } + + Network::Get()->SendToTimestamp(s_ntpClient.nHandle, &s_ntpClient.Request, REQUEST_SIZE, s_ntpClient.nServerIp, ntp::UDP_PORT); + +#ifndef NDEBUG + printf("Request: org=%.8x%.8x rx=%.8x%.8x tx=%.8x%.8x\n", + __builtin_bswap32(s_ntpClient.Request.OriginTimestamp_s), __builtin_bswap32(s_ntpClient.Request.OriginTimestamp_f), + __builtin_bswap32(s_ntpClient.Request.ReceiveTimestamp_s), __builtin_bswap32(s_ntpClient.Request.ReceiveTimestamp_f), + __builtin_bswap32(s_ntpClient.Request.TransmitTimestamp_s), __builtin_bswap32(s_ntpClient.Request.TransmitTimestamp_f)); +#endif + + if (s_ntpClient.state.x > 0) { + s_ntpClient.state.sentA.nSeconds = net::globals::ptpTimestamp[1] + ntp::JAN_1970; + s_ntpClient.state.sentA.nFraction = NTPFRAC(gd32::ptp_subsecond_2_nanosecond(net::globals::ptpTimestamp[0])); + } else { + s_ntpClient.state.sentB.nSeconds = net::globals::ptpTimestamp[1] + ntp::JAN_1970; + s_ntpClient.state.sentB.nFraction = NTPFRAC(gd32::ptp_subsecond_2_nanosecond(net::globals::ptpTimestamp[0])); + } + + s_ntpClient.state.x = -s_ntpClient.state.x; + s_id++; + + return true; +} + +static void difference(const ntp::TimeStamp& Start, const ntp::TimeStamp& Stop, int32_t& nDiffSeconds, int32_t& nDiffNanoSeconds) { + gd32::ptp::time_t r; + const gd32::ptp::time_t x = {.tv_sec = static_cast(Stop.nSeconds), .tv_nsec = static_cast(USEC(Stop.nFraction) * 1000)}; + const gd32::ptp::time_t y = {.tv_sec = static_cast(Start.nSeconds), .tv_nsec = static_cast(USEC(Start.nFraction) * 1000)}; + gd32::sub_time(&r, &x, &y); + + nDiffSeconds = r.tv_sec; + nDiffNanoSeconds = r.tv_nsec; +} + +static void update_ptp_time() { + int32_t nDiffSeconds1, nDiffNanoSeconds1; + difference(s_ntpClient.T1, s_ntpClient.T2, nDiffSeconds1, nDiffNanoSeconds1); + + int32_t nDiffSeconds2, nDiffNanoSeconds2; + difference(s_ntpClient.T4, s_ntpClient.T3, nDiffSeconds2, nDiffNanoSeconds2); + + auto nOffsetSeconds = static_cast(nDiffSeconds1) + static_cast(nDiffSeconds2); + auto nOffsetNanoSeconds = static_cast(nDiffNanoSeconds1) + static_cast(nDiffNanoSeconds2); + + const int32_t nOffsetSecondsAverage = nOffsetSeconds / 2; + const int32_t nOffsetNanosverage = nOffsetNanoSeconds / 2; + + gd32::ptp::time_t ptpOffset = {.tv_sec = nOffsetSecondsAverage, .tv_nsec = nOffsetNanosverage}; + gd32::normalize_time(&ptpOffset); + gd32_ptp_update_time(&ptpOffset); + + gd32::ptp::ptptime ptp_get; + gd32_ptp_get_time(&ptp_get); + + s_ntpClient.Request.ReferenceTimestamp_s = __builtin_bswap32(static_cast(ptp_get.tv_sec) + ntp::JAN_1970); + s_ntpClient.Request.ReferenceTimestamp_f = __builtin_bswap32(NTPFRAC(ptp_get.tv_nsec)); + +#ifndef NDEBUG + /** + * Network delay calculation + */ + gd32::ptp::time_t diff1; + gd32::ptp::time_t diff2; + + if (s_ntpClient.state.mode == ntp::Modes::BASIC) { + difference(s_ntpClient.T1, s_ntpClient.T4, diff1.tv_sec, diff1.tv_nsec); + difference(s_ntpClient.T2, s_ntpClient.T3, diff2.tv_sec, diff2.tv_nsec); + } else { + ntp::TimeStamp start; + start.nSeconds = __builtin_bswap32(s_ntpClient.Request.TransmitTimestamp_s); + start.nFraction = __builtin_bswap32(s_ntpClient.Request.TransmitTimestamp_f); + ntp::TimeStamp stop; + stop.nSeconds = __builtin_bswap32(s_ntpClient.Request.ReceiveTimestamp_s); + stop.nFraction = __builtin_bswap32(s_ntpClient.Request.ReceiveTimestamp_f); + difference(start, stop, diff1.tv_sec, diff1.tv_nsec); + + const auto *const pReply = s_ntpClient.pReply; + start.nSeconds = __builtin_bswap32(s_ntpClient.Request.OriginTimestamp_s); + start.nFraction = __builtin_bswap32(s_ntpClient.Request.OriginTimestamp_f); + stop.nSeconds = __builtin_bswap32(pReply->TransmitTimestamp_s); + stop.nFraction = __builtin_bswap32(pReply->TransmitTimestamp_f); + difference(start, stop, diff2.tv_sec, diff2.tv_nsec); + } + + gd32::ptp::time_t ptpDelay; + gd32::sub_time(&ptpDelay, &diff1, &diff2); + + char sign = '+'; + + if (ptpOffset.tv_sec < 0) { + ptpOffset.tv_sec = -ptpOffset.tv_sec; + sign = '-'; + } + + if (ptpOffset.tv_nsec < 0) { + ptpOffset.tv_nsec = -ptpOffset.tv_nsec; + sign = '-'; + } + + printf(" %s : offset=%c%d.%09d delay=%d.%09d\n", + s_ntpClient.state.mode == ntp::Modes::BASIC ? "Basic" : "Interleaved", + sign, ptpOffset.tv_sec, ptpOffset.tv_nsec, + ptpDelay.tv_sec, ptpDelay.tv_nsec); +#endif +} + +/** + * Two of the tests are modified for the interleaved mode: + * + * 1. The check for duplicate packets SHOULD compare both receive and + * transmit timestamps in order to not drop a valid response in the interleaved mode if + * it follows a response in the basic mode and they contain the same transmit timestamp. + * 2. The check for bogus packets SHOULD compare the origin timestamp with both transmit and + * receive timestamps from the request. + * If the origin timestamp is equal to the transmit timestamp, the response is in the basic mode. + * If the origin timestamp is equal to the receive timestamp, the response is in the interleaved mode. + */ + +static bool receive() { + uint32_t nFromIp; + uint16_t nFromPort; + + const auto nBytesReceived = Network::Get()->RecvFrom(s_ntpClient.nHandle, const_cast(reinterpret_cast(&s_ntpClient.pReply)), &nFromIp, &nFromPort); + + if (__builtin_expect((nBytesReceived != sizeof(struct ntp::Packet)), 1)) { + return false; + } + + if (__builtin_expect((nFromIp != s_ntpClient.nServerIp), 0)) { + DEBUG_PUTS("nFromIp != s_ntpClient.nServerIp"); + return false; + } + + if (s_ntpClient.state.missedResponses == 0) { + DEBUG_PUTS("Ignore duplicates"); + return false; + } + + return true; +} + +static void process() { + const auto *const pReply = s_ntpClient.pReply; +#ifndef NDEBUG + printf("Response: org=%.8x%.8x rx=%.8x%.8x tx=%.8x%.8x\n", + __builtin_bswap32(pReply->OriginTimestamp_s), __builtin_bswap32(pReply->OriginTimestamp_f), + __builtin_bswap32(pReply->ReceiveTimestamp_s), __builtin_bswap32(pReply->ReceiveTimestamp_f), + __builtin_bswap32(pReply->TransmitTimestamp_s), __builtin_bswap32(pReply->TransmitTimestamp_f)); +#endif + /** + * If the origin timestamp is equal to the transmit timestamp, + * the response is in the basic mode. + */ + if ((pReply->OriginTimestamp_s == s_ntpClient.Request.TransmitTimestamp_s) && (pReply->OriginTimestamp_f == s_ntpClient.Request.TransmitTimestamp_f)) { + if (s_ntpClient.state.x < 0) { + s_ntpClient.T1.nSeconds = s_ntpClient.state.sentA.nSeconds; + s_ntpClient.T1.nFraction = s_ntpClient.state.sentA.nFraction; + } else { + s_ntpClient.T1.nSeconds = s_ntpClient.state.sentB.nSeconds; + s_ntpClient.T1.nFraction = s_ntpClient.state.sentB.nFraction; + } + + s_ntpClient.T4.nSeconds = net::globals::ptpTimestamp[1] + ntp::JAN_1970; + s_ntpClient.T4.nFraction = NTPFRAC(gd32::ptp_subsecond_2_nanosecond(net::globals::ptpTimestamp[0])); +#ifndef NDEBUG + s_ntpClient.state.mode = ntp::Modes::BASIC; +#endif + } else + /** + * If the origin timestamp is equal to the receive timestamp, + * the response is in the interleaved mode. + */ + if ((pReply->OriginTimestamp_s == s_ntpClient.Request.ReceiveTimestamp_s) && (pReply->OriginTimestamp_f == s_ntpClient.Request.ReceiveTimestamp_f)) { + if (s_ntpClient.state.x > 0) { + s_ntpClient.T1.nSeconds = s_ntpClient.state.sentB.nSeconds; + s_ntpClient.T1.nFraction = s_ntpClient.state.sentB.nFraction; + } else { + s_ntpClient.T1.nSeconds = s_ntpClient.state.sentA.nSeconds; + s_ntpClient.T1.nFraction = s_ntpClient.state.sentA.nFraction; + } + + s_ntpClient.T4.nSeconds = s_ntpClient.state.previousReceive.nSeconds; + s_ntpClient.T4.nFraction = s_ntpClient.state.previousReceive.nFraction; +#ifndef NDEBUG + s_ntpClient.state.mode = ntp::Modes::INTERLEAVED; +#endif + } else { + DEBUG_PUTS("INVALID RESPONSE"); + return; + } + + s_ntpClient.T2.nSeconds = __builtin_bswap32(pReply->ReceiveTimestamp_s); + s_ntpClient.T2.nFraction = __builtin_bswap32(pReply->ReceiveTimestamp_f); + + s_ntpClient.T3.nSeconds = __builtin_bswap32(pReply->TransmitTimestamp_s); + s_ntpClient.T3.nFraction = __builtin_bswap32(pReply->TransmitTimestamp_f); + + s_ntpClient.state.dst.nSeconds = __builtin_bswap32(pReply->ReceiveTimestamp_s); + s_ntpClient.state.dst.nFraction = __builtin_bswap32(pReply->ReceiveTimestamp_f); + + s_ntpClient.state.previousReceive.nSeconds = net::globals::ptpTimestamp[1] + ntp::JAN_1970; + s_ntpClient.state.previousReceive.nFraction = NTPFRAC(gd32::ptp_subsecond_2_nanosecond(net::globals::ptpTimestamp[0])); + + update_ptp_time(); + + s_ntpClient.state.missedResponses = 0; + + print("T1: ", &s_ntpClient.T1); + print("T2: ", &s_ntpClient.T2); + print("T3: ", &s_ntpClient.T3); + print("T4: ", &s_ntpClient.T4); +} + +void ptp_run() { + if (s_ntpClient.status == ntp::Status::STOPPED) { + return; + } + + if ((s_ntpClient.status == ntp::Status::IDLE) || (s_ntpClient.status == ntp::Status::FAILED)) { + const auto nMillis = Hardware::Get()->Millis(); + if (__builtin_expect(((nMillis - s_ntpClient.nMillisLastPoll) > (1000U * POLL_SECONDS)), 0)) { + if (send()) { + s_ntpClient.status = ntp::Status::WAITING; + s_ntpClient.nMillisRequest = nMillis; + } else { + s_ntpClient.status = ntp::Status::FAILED; + s_ntpClient.nMillisLastPoll = nMillis; + } + } + return; + } + + if (s_ntpClient.status == ntp::Status::WAITING) { + if (__builtin_expect((!receive()), 1)) { + if (__builtin_expect(((Hardware::Get()->Millis() - s_ntpClient.nMillisRequest) > (1000U * TIMEOUT_SECONDS)), 0)) { + s_ntpClient.status = ntp::Status::FAILED; + DEBUG_PUTS("FAILED"); + } + return; + } + + if (__builtin_expect(((s_ntpClient.pReply->LiVnMode & ntp::MODE_SERVER) == ntp::MODE_SERVER), 1)) { + s_ntpClient.nMillisLastPoll = Hardware::Get()->Millis(); + process(); + } else { + DEBUG_PUTS("INVALID REPLY"); + } + + s_ntpClient.status = ntp::Status::IDLE; + } +} +} // namespace net diff --git a/lib-network/src/apps/ntp/ntpclient.cpp b/lib-network/src/net/apps/ntp/ntpclient.cpp similarity index 99% rename from lib-network/src/apps/ntp/ntpclient.cpp rename to lib-network/src/net/apps/ntp/ntpclient.cpp index 22bffdb4b..4db22dce1 100755 --- a/lib-network/src/apps/ntp/ntpclient.cpp +++ b/lib-network/src/net/apps/ntp/ntpclient.cpp @@ -35,8 +35,8 @@ #include #include -#include "ntpclient.h" -#include "ntp.h" +#include "net/apps/ntpclient.h" +#include "net/protocol/ntp.h" #include "utc.h" #include "network.h" diff --git a/lib-network/src/apps/tftp/tftpdaemon.cpp b/lib-network/src/net/apps/tftp/tftpdaemon.cpp similarity index 99% rename from lib-network/src/apps/tftp/tftpdaemon.cpp rename to lib-network/src/net/apps/tftp/tftpdaemon.cpp index e733718ca..3d0c3d9d1 100644 --- a/lib-network/src/apps/tftp/tftpdaemon.cpp +++ b/lib-network/src/net/apps/tftp/tftpdaemon.cpp @@ -31,7 +31,7 @@ #include #include -#include "tftpdaemon.h" +#include "net/apps/tftpdaemon.h" #include "network.h" diff --git a/lib-network/src/net/arp.cpp b/lib-network/src/net/arp.cpp index 10f5331f8..466e92357 100755 --- a/lib-network/src/net/arp.cpp +++ b/lib-network/src/net/arp.cpp @@ -2,7 +2,7 @@ * @file arp.cpp * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,180 +22,309 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/** + * https://datatracker.ietf.org/doc/html/rfc826 + * An Ethernet Address Resolution Protocol + * -- or -- + * Converting Network Protocol Addresses + */ -#pragma GCC push_options -#pragma GCC optimize ("O2") -#pragma GCC optimize ("no-tree-loop-distribute-patterns") +#if defined (DEBUG_NET_ARP) +# undef NDEBUG +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif #include #include +#include #include -#include "net.h" -#include "net_private.h" -#include "net_memcpy.h" #include "../../config/net_config.h" +#include "net_memcpy.h" +#include "net_private.h" + +#include "net/arp.h" +#include "net/acd.h" +#include "net/protocol/arp.h" +#include "net/protocol/udp.h" +#include "netif.h" + #include "hardware.h" -namespace net { -namespace arp { -enum class RequestType { - REQUEST, PROBE, ANNNOUNCEMENT -}; -} // namespace arp -} // namespace net +#include "debug.h" -static struct t_arp s_arp_request ALIGNED ; -static struct t_arp s_arp_reply ALIGNED; -static net::arp::RequestType s_requestType ALIGNED; -static bool s_isProbeReplyReceived ALIGNED; +#if !defined ARP_MAX_RECORDS +static constexpr auto MAX_RECORDS = 16; +#else +static constexpr auto MAX_RECORDS = ARP_MAX_RECORDS; +#endif namespace net { namespace globals { -extern struct IpInfo ipInfo; -extern uint8_t macAddress[ETH_ADDR_LEN]; +extern uint32_t nOnNetworkMask; } // namespace globals -} // namespace net -void __attribute__((cold)) arp_init() { - arp_cache_init(); +namespace arp { +static constexpr uint32_t TIMER_INTERVAL = 1000; ///< 1 second +static constexpr uint32_t MAX_PROBING = 2; ///< 2 * 1 second +static constexpr uint32_t MAX_REACHABLE = (10 * 60); ///< (10 * 60) * 1 second = 10 minutes +static constexpr uint32_t MAX_STALE = ( 5 * 60); ///< ( 5 * 60) * 1 second = 5 minutes - s_requestType = net::arp::RequestType::REQUEST; +enum class State { + STATE_EMPTY, STATE_PROBE, STATE_REACHABLE, STATE_STALE, +}; - // ARP Request template - // Ethernet header - memcpy(s_arp_request.ether.src, net::globals::macAddress, ETH_ADDR_LEN); - memset(s_arp_request.ether.dst, 0xFF , ETH_ADDR_LEN); - s_arp_request.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); +struct Packet { + uint8_t *p; + uint32_t nSize; +#if defined CONFIG_ENET_ENABLE_PTP + bool isTimestamp; +#endif +}; - // ARP Header - s_arp_request.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); - s_arp_request.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); - s_arp_request.arp.hardware_size = ARP_HARDWARE_SIZE; - s_arp_request.arp.protocol_size = ARP_PROTOCOL_SIZE; - s_arp_request.arp.opcode = __builtin_bswap16(ARP_OPCODE_RQST); +struct Record { + uint32_t nIp; + Packet packet; + uint8_t mac_address[ETH_ADDR_LEN]; + uint16_t nAge; + State state; +}; +} // namespace arp - memcpy(s_arp_request.arp.sender_mac, net::globals::macAddress, ETH_ADDR_LEN); - net::memcpy_ip(s_arp_request.arp.sender_ip, net::globals::ipInfo.ip.addr); - memset(s_arp_request.arp.target_mac, 0x00, ETH_ADDR_LEN); +static net::arp::Record s_ArpRecords[MAX_RECORDS] SECTION_NETWORK ALIGNED; - // ARP Reply Template - // Ethernet header - memcpy(s_arp_reply.ether.src, net::globals::macAddress, ETH_ADDR_LEN); - s_arp_reply.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); +static struct t_arp s_arp_request ALIGNED ; +static struct t_arp s_arp_reply ALIGNED; - // ARP Header - s_arp_reply.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); - s_arp_reply.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); - s_arp_reply.arp.hardware_size = ARP_HARDWARE_SIZE; - s_arp_reply.arp.protocol_size = ARP_PROTOCOL_SIZE; - s_arp_reply.arp.opcode = __builtin_bswap16(ARP_OPCODE_REPLY); +#ifndef NDEBUG +static constexpr char STATE[4][12] = { "EMPTY", "PROBE", "REACHABLE", "STALE", }; - memcpy(s_arp_reply.arp.sender_mac, net::globals::macAddress, ETH_ADDR_LEN); +void static arp_cache_record_dump(net::arp::Record *pRecord) { + printf("%p %-4d %c " MACSTR " %-10s " IPSTR "\n", pRecord, pRecord->nAge, pRecord->packet.p == nullptr ? '-' : 'Q' , MAC2STR(pRecord->mac_address), STATE[static_cast(pRecord->state)], IP2STR(pRecord->nIp)); } -bool arp_do_probe() { -#ifndef NDEBUG - static constexpr uint32_t TIMEOUT_MILLIS = 500; +void static arp_cache_dump() { + uint32_t nIndex = 0; + for (auto &record : s_ArpRecords) { + printf("%p %02d %-4d" MACSTR " %-10s " IPSTR "\n", &record, nIndex++, record.nAge, MAC2STR(record.mac_address), STATE[static_cast(record.state)], IP2STR(record.nIp)); + if (nIndex ==6) { + return; + } + } +} #else - static constexpr uint32_t TIMEOUT_MILLIS = 10; +void static arp_cache_record_dump([[maybe_unused]] net::arp::Record *pRecord) {} +void static arp_cache_dump() {} #endif - auto nRetries = 3; - - while (nRetries--) { - arp_send_probe(); +static net::arp::Record *arp_find_record(const uint32_t nDestinationIp, [[maybe_unused]] const arp::Flags flag) { + DEBUG_ENTRY - Hardware::Get()->WatchdogFeed(); + net::arp::Record *pStale = nullptr; + net::arp::Record *pReachable = nullptr; + uint32_t nAgeStale = 0; + uint32_t nAgeReachable = 0; + + for (auto &record : s_ArpRecords) { + if (record.nIp == nDestinationIp) { + DEBUG_EXIT + return &record; + } + + if (flag == arp::Flags::FLAG_UPDATE) { + continue; + } + + if (record.state == net::arp::State::STATE_EMPTY) { + record.nIp = nDestinationIp; + DEBUG_EXIT + return &record; + } + + if (record.state == net::arp::State::STATE_REACHABLE) { + if (record.nAge > nAgeReachable) { + nAgeReachable = record.nAge; + pReachable = &record; + } + continue; + } - const auto nMillis = Hardware::Get()->Millis(); - do { - net_handle(); - if (s_isProbeReplyReceived) { - return true; + if (record.state == net::arp::State::STATE_STALE) { + if (record.nAge > nAgeStale) { + nAgeStale = record.nAge; + pStale = &record; } - } while ((Hardware::Get()->Millis() - nMillis) < TIMEOUT_MILLIS); + continue; + } } - return false; + if (pStale != nullptr) { + DEBUG_EXIT + return pStale; + } + + if (pReachable != nullptr) { + DEBUG_EXIT + return pReachable; + } + + DEBUG_EXIT + return nullptr; } -void arp_send_request(uint32_t nIp) { +static void arp_cache_update(const uint8_t *pMacAddress, const uint32_t nIp, const arp::Flags flag) { DEBUG_ENTRY - DEBUG_PRINTF(IPSTR, IP2STR(nIp)); + DEBUG_PRINTF(MACSTR " " IPSTR " flag=%d", MAC2STR(pMacAddress), IP2STR(nIp), flag); - s_requestType = net::arp::RequestType::REQUEST; + auto *record = arp_find_record(nIp, flag); - net::memcpy_ip(s_arp_request.arp.target_ip, nIp); + if (record == nullptr) { + assert(flag == arp::Flags::FLAG_UPDATE); + DEBUG_EXIT + return; + } - emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); + record->state = net::arp::State::STATE_REACHABLE; + record->nAge = 0; + std::memcpy(record->mac_address, pMacAddress, ETH_ADDR_LEN); + + arp_cache_record_dump(record); + + if (record->packet.p != nullptr) { + auto *udp = reinterpret_cast(record->packet.p); + std::memcpy(udp->ether.dst, record->mac_address, ETH_ADDR_LEN); + udp->ip4.chksum = 0; +#if !defined (CHECKSUM_BY_HARDWARE) + udp->ip4.chksum = net_chksum(reinterpret_cast(&udp->ip4), sizeof(udp->ip4)); +#endif +#if defined CONFIG_ENET_ENABLE_PTP + if (!record->packet.isTimestamp) { +#endif + emac_eth_send(record->packet.p, record->packet.nSize); +#if defined CONFIG_ENET_ENABLE_PTP + } else { + emac_eth_send_timestamp(record->packet.p, record->packet.nSize); + } +#endif + delete [] record->packet.p; + record->packet.p = nullptr; + } DEBUG_EXIT } -/* - * The Sender IP is set to all zeros, - * which means it cannot map to the Sender MAC address. - * The Target MAC address is all zeros, - * which means it cannot map to the Target IP address. - */ -void arp_send_probe() { +static void arp_send_request(const uint32_t nIp) { + DEBUG_PRINTF(IPSTR, IP2STR(nIp)); + + net::memcpy_ip(s_arp_request.arp.target_ip, nIp); + + emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); +} + +template +static void arp_query(const uint32_t nDestinationIp, struct t_udp *pPacket, const uint32_t nSize, [[maybe_unused]] const arp::Flags flag) { DEBUG_ENTRY + DEBUG_PRINTF(IPSTR " %c", IP2STR(nDestinationIp), flag == arp::Flags::FLAG_UPDATE ? 'U' : 'I'); - s_requestType = net::arp::RequestType::PROBE; - s_isProbeReplyReceived = false; + auto *recordFound = arp_find_record(nDestinationIp, flag); + assert(recordFound != nullptr); - memset(s_arp_request.arp.sender_ip, 0, IPv4_ADDR_LEN); - net::memcpy_ip(s_arp_request.arp.target_ip, net::globals::ipInfo.ip.addr); + arp_cache_record_dump(recordFound); - emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); + if (recordFound->state == net::arp::State::STATE_EMPTY) { + recordFound->state = net::arp::State::STATE_PROBE; + recordFound->nAge = 0; + arp_send_request(nDestinationIp); + } + + if (recordFound->state == net::arp::State::STATE_PROBE) { + if (recordFound->packet.p != nullptr) { + delete[] recordFound->packet.p; + } + + recordFound->packet.p = new uint8_t[nSize]; + assert(recordFound->packet.p != nullptr); - net::memcpy_ip(s_arp_request.arp.sender_ip, net::globals::ipInfo.ip.addr); + net::memcpy(recordFound->packet.p, pPacket, nSize); + recordFound->packet.nSize = nSize; +#if defined CONFIG_ENET_ENABLE_PTP + recordFound->packet.isTimestamp = (S != net::arp::EthSend::IS_NORMAL); +#endif + } DEBUG_EXIT } -/* - * The packet structure is identical to the ARP Probe above, - * with the exception that a complete mapping exists. - * Both the Sender MAC address and the Sender IP address create a complete ARP mapping, - * and hosts on the network can use this pair of addresses in their ARP table. - */ -void arp_send_announcement() { - DEBUG_ENTRY +static void arp_cache_clean_record(net::arp::Record& record) { + if (record.packet.p != nullptr) { + delete[] record.packet.p; + } + memset(&record, 0, sizeof(struct net::arp::Record)); +} - s_requestType = net::arp::RequestType::ANNNOUNCEMENT; +static void arp_send_request_unicast(const uint32_t nIp, const uint8_t *pMacAddress) { + DEBUG_PRINTF(IPSTR, IP2STR(nIp)); - net::memcpy_ip(s_arp_request.arp.target_ip, net::globals::ipInfo.ip.addr); + net::memcpy(s_arp_request.ether.dst, pMacAddress , ETH_ADDR_LEN); + net::memcpy_ip(s_arp_request.arp.target_ip, nIp); emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); - DEBUG_EXIT + memset(s_arp_request.ether.dst, 0xFF , ETH_ADDR_LEN); } -void arp_handle_request(struct t_arp *p_arp) { - DEBUG_ENTRY - - const auto nIpTarget = net::memcpy_ip(p_arp->arp.target_ip); +static void arp_timer() { + for (auto &record : s_ArpRecords) { + const auto state = record.state; + if (state != net::arp::State::STATE_EMPTY) { + record.nAge++; + + switch (state) { + case net::arp::State::STATE_PROBE: + if (record.nAge > net::arp::MAX_PROBING) { + arp_cache_clean_record(record); + } + break; + + case net::arp::State::STATE_REACHABLE: + if (record.nAge > net::arp::MAX_REACHABLE) { + record.state = net::arp::State::STATE_STALE; + record.nAge = 0; + } + break; + + case net::arp::State::STATE_STALE: + if (record.nAge > net::arp::MAX_STALE) { + record.state = net::arp::State::STATE_PROBE; + arp_send_request_unicast(record.nIp, record.mac_address); + } + break; + + default: + break; + } + } + } -#ifndef NDEBUG - const auto nIpSender = net::memcpy_ip(p_arp->arp.sender_ip); - DEBUG_PRINTF("Sender " IPSTR " Target " IPSTR, IP2STR(nIpSender), IP2STR(nIpTarget)); -#endif + arp_cache_dump(); +} - if (!((nIpTarget == net::globals::ipInfo.ip.addr) || (nIpTarget == net::globals::ipInfo.secondary_ip.addr) || (nIpTarget == net::globals::ipInfo.broadcast_ip.addr))) { - DEBUG_PUTS("No for me."); - DEBUG_EXIT - return; - } +static void arp_send_reply(const struct t_arp *p_arp) { + DEBUG_ENTRY // Ethernet header - memcpy(s_arp_reply.ether.dst, p_arp->ether.src, ETH_ADDR_LEN); + std::memcpy(s_arp_reply.ether.dst, p_arp->ether.src, ETH_ADDR_LEN); // ARP Header - memcpy(s_arp_reply.arp.target_mac, p_arp->arp.sender_mac, ETH_ADDR_LEN); - memcpy(s_arp_reply.arp.target_ip, p_arp->arp.sender_ip, IPv4_ADDR_LEN); + const auto nIpTarget = net::memcpy_ip(p_arp->arp.target_ip); + std::memcpy(s_arp_reply.arp.target_mac, p_arp->arp.sender_mac, ETH_ADDR_LEN); + std::memcpy(s_arp_reply.arp.target_ip, p_arp->arp.sender_ip, IPv4_ADDR_LEN); net::memcpy_ip(s_arp_reply.arp.sender_ip, nIpTarget); emac_eth_send(reinterpret_cast(&s_arp_reply), sizeof(struct t_arp)); @@ -203,39 +332,187 @@ void arp_handle_request(struct t_arp *p_arp) { DEBUG_EXIT } -void arp_handle_reply(struct t_arp *p_arp) { +// Public interface + +void __attribute__((cold)) arp_init() { DEBUG_ENTRY - switch (s_requestType) { - case net::arp::RequestType::REQUEST: { - arp_cache_update(p_arp->arp.sender_mac, net::memcpy_ip(p_arp->arp.sender_ip)); + for (auto& record : s_ArpRecords) { + std::memset(&record, 0, sizeof(struct net::arp::Record)); } + + // ARP Request template + // Ethernet header + std::memcpy(s_arp_request.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); + std::memset(s_arp_request.ether.dst, 0xFF , ETH_ADDR_LEN); + s_arp_request.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); + + // ARP Header + s_arp_request.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); + s_arp_request.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); + s_arp_request.arp.hardware_size = ARP_HARDWARE_SIZE; + s_arp_request.arp.protocol_size = ARP_PROTOCOL_SIZE; + s_arp_request.arp.opcode = __builtin_bswap16(ARP_OPCODE_RQST); + + std::memcpy(s_arp_request.arp.sender_mac, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); + net::memcpy_ip(s_arp_request.arp.sender_ip, net::globals::netif_default.ip.addr); + std::memset(s_arp_request.arp.target_mac, 0x00, ETH_ADDR_LEN); + + // ARP Reply Template + // Ethernet header + std::memcpy(s_arp_reply.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); + s_arp_reply.ether.type = __builtin_bswap16(ETHER_TYPE_ARP); + + // ARP Header + s_arp_reply.arp.hardware_type = __builtin_bswap16(ARP_HWTYPE_ETHERNET); + s_arp_reply.arp.protocol_type = __builtin_bswap16(ARP_PRTYPE_IPv4); + s_arp_reply.arp.hardware_size = ARP_HARDWARE_SIZE; + s_arp_reply.arp.protocol_size = ARP_PROTOCOL_SIZE; + s_arp_reply.arp.opcode = __builtin_bswap16(ARP_OPCODE_REPLY); + + std::memcpy(s_arp_reply.arp.sender_mac, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); + + Hardware::Get()->SoftwareTimerAdd(net::arp::TIMER_INTERVAL, arp_timer); + + DEBUG_EXIT +} + +__attribute__((hot)) void arp_handle(struct t_arp *pArp) { + /* + * RFC 826 Packet Reception: + */ + if (__builtin_expect(((pArp->arp.hardware_type != __builtin_bswap16(ARP_HWTYPE_ETHERNET)) + || (pArp->arp.protocol_type != __builtin_bswap16(ARP_PRTYPE_IPv4)) + || (pArp->arp.hardware_size != ARP_HARDWARE_SIZE) + || (pArp->arp.protocol_size != ARP_PROTOCOL_SIZE)), 0)) { + DEBUG_EXIT + return; + } + + acd_arp_reply(pArp); + + /* ARP packet directed to us? */ + const auto nIpTarget = net::memcpy_ip(pArp->arp.target_ip); + const auto bToUs = ((nIpTarget == net::globals::netif_default.ip.addr) || (nIpTarget == net::globals::netif_default.secondary_ip.addr)); + /* ARP packet from us? */ + const auto bFromUs = (net::memcpy_ip(pArp->arp.sender_ip) == net::globals::netif_default.ip.addr); + + DEBUG_PRINTF("bToUs:%d, bFromUs:%d", bToUs, bFromUs); + + /* + * ARP message directed to us? + * -> add IP address in ARP cache; assume requester wants to talk to us, + * can result in directly sending the queued packets for this host. + * ARP message not directed to us? + * -> update the source IP address in the cache, if present + */ + arp_cache_update(pArp->arp.sender_mac, net::memcpy_ip(pArp->arp.sender_ip), bToUs ? arp::Flags::FLAG_INSERT : arp::Flags::FLAG_UPDATE); + + switch (pArp->arp.opcode) { + case __builtin_bswap16(ARP_OPCODE_RQST): + if (bToUs && !bFromUs) { + arp_send_reply(pArp); + } else { + DEBUG_PUTS("ARP request was not for us"); + } break; - case net::arp::RequestType::PROBE: - s_isProbeReplyReceived = true; + case __builtin_bswap16(ARP_OPCODE_REPLY): + /* Cache update is handled earlier */ break; default: - assert(0); + DEBUG_PRINTF("opcode %04x not handled", __builtin_bswap16(pArp->arp.opcode)); break; } +} + +template +static void arp_send_implementation(struct t_udp *pPacket, const uint32_t nSize, const uint32_t nRemoteIp) { + DEBUG_ENTRY + DEBUG_PRINTF(IPSTR, IP2STR(nRemoteIp)); + + net::memcpy_ip(pPacket->ip4.dst, nRemoteIp); + pPacket->ip4.chksum = 0; +#if !defined (CHECKSUM_BY_HARDWARE) + pPacket->ip4.chksum = net_chksum(reinterpret_cast(&pPacket->ip4), sizeof(pPacket->ip4)); +#endif + + auto nDestinationIp = nRemoteIp; + + if (__builtin_expect((net::globals::nOnNetworkMask != (nRemoteIp & net::globals::nOnNetworkMask)), 0)) { + /* According to RFC 3297, chapter 2.6.2 (Forwarding Rules), a packet with + a link-local source address must always be "directly to its destination + on the same physical link. The host MUST NOT send the packet to any + router for forwarding". */ + if (!network::is_linklocal_ip(nRemoteIp)) { + nDestinationIp = net::globals::netif_default.gw.addr; + DEBUG_PUTS(""); + } + } + + for (auto &record : s_ArpRecords) { + if (record.state >= net::arp::State::STATE_REACHABLE) { + if (record.nIp == nDestinationIp) { + std::memcpy(pPacket->ether.dst, record.mac_address, ETH_ADDR_LEN); + + if (S == net::arp::EthSend::IS_NORMAL) { + emac_eth_send(reinterpret_cast(pPacket), nSize); + } +#if defined CONFIG_ENET_ENABLE_PTP + else if (S == net::arp::EthSend::IS_TIMESTAMP) { + emac_eth_send_timestamp(reinterpret_cast(pPacket), nSize); + } +#endif + DEBUG_EXIT + return; + } + } + } + + arp_query(nDestinationIp, pPacket, nSize, arp::Flags::FLAG_INSERT); DEBUG_EXIT + return; } -__attribute__((hot)) void arp_handle(struct t_arp *pArp) { +void arp_send(struct t_udp *pPacket, const uint32_t nSize, const uint32_t nRemoteIp) { + arp_send_implementation(pPacket, nSize, nRemoteIp); +} + +#if defined CONFIG_ENET_ENABLE_PTP +void arp_send_timestamp(struct t_udp *pPacket, const uint32_t nSize, const uint32_t nRemoteIp) { + arp_send_implementation(pPacket, nSize, nRemoteIp); +} +#endif + +/* + * The Sender IP is set to all zeros, + * which means it cannot map to the Sender MAC address. + * The Target MAC address is all zeros, + * which means it cannot map to the Target IP address. + */ +void arp_acd_probe(const ip4_addr_t ipaddr) { DEBUG_ENTRY - switch (pArp->arp.opcode) { - case __builtin_bswap16(ARP_OPCODE_RQST): - arp_handle_request(pArp); - break; - case __builtin_bswap16(ARP_OPCODE_REPLY): - arp_handle_reply(pArp); - break; - default: - DEBUG_PRINTF("opcode %04x not handled", __builtin_bswap16(pArp->arp.opcode)); - break; - } + memset(s_arp_request.arp.sender_ip, 0, IPv4_ADDR_LEN); + net::memcpy_ip(s_arp_request.arp.target_ip, ipaddr.addr); + + emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); + + net::memcpy_ip(s_arp_request.arp.sender_ip, net::globals::netif_default.ip.addr); DEBUG_EXIT } + +/* + * The packet structure is identical to the ARP Probe above, + * with the exception that a complete mapping exists. + * Both the Sender MAC address and the Sender IP address create a complete ARP mapping, + * and hosts on the network can use this pair of addresses in their ARP table. + */ +void arp_acd_send_announcement(const ip4_addr_t ipaddr) { + net::memcpy_ip(s_arp_request.arp.target_ip, ipaddr.addr); + net::memcpy_ip(s_arp_request.arp.sender_ip, ipaddr.addr); + + emac_eth_send(reinterpret_cast(&s_arp_request), sizeof(struct t_arp)); +} +} // namespace net diff --git a/lib-network/src/net/arp_cache.cpp b/lib-network/src/net/arp_cache.cpp deleted file mode 100644 index 24597b3ab..000000000 --- a/lib-network/src/net/arp_cache.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/** - * @file arp_cache.cpp - * - */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma GCC push_options -#pragma GCC optimize ("O2") -#pragma GCC optimize ("no-tree-loop-distribute-patterns") - -#include -#include -#include - -#include "net_private.h" -#include "net_packets.h" -#include "net_platform.h" -#include "net_debug.h" - -#include "emac/net_link_check.h" - -#include "../../config/net_config.h" - -#if !defined ARP_MAX_RECORDS -static constexpr auto MAX_RECORDS = 32; -#else -static constexpr auto MAX_RECORDS = ARP_MAX_RECORDS; -#endif - -struct ArpRecord { - uint32_t nIp; - uint8_t mac_address[ETH_ADDR_LEN]; -}; - -static ArpRecord s_ArpRecords[MAX_RECORDS] SECTION_NETWORK ALIGNED; -static uint16_t s_Entries SECTION_NETWORK ALIGNED; - -#ifndef NDEBUG -# define TICKER_COUNT 100 ///< 10 seconds - static uint32_t s_ticker ; -#endif - -void __attribute__((cold)) arp_cache_init() { - s_Entries = 0; - - for (auto& record : s_ArpRecords) { - memset(&record, 0, sizeof(struct ArpRecord)); - } - -#ifndef NDEBUG - s_ticker = TICKER_COUNT; -#endif -} - -void arp_cache_update(const uint8_t *pMacAddress, uint32_t nIp) { - DEBUG_ENTRY - DEBUG_PRINTF(MACSTR " " IPSTR, MAC2STR(pMacAddress), IP2STR(nIp)); - - if (s_Entries == MAX_RECORDS) { - console_error("ARP cache is full\n"); - return; - } - - for (auto i = 0; i < s_Entries; i++) { - if (s_ArpRecords[i].nIp == nIp) { - DEBUG_EXIT - return; - } - } - - memcpy(s_ArpRecords[s_Entries].mac_address, pMacAddress, ETH_ADDR_LEN); - s_ArpRecords[s_Entries].nIp = nIp; - - s_Entries++; - - DEBUG_EXIT -} - -uint32_t arp_cache_lookup(uint32_t nIp, uint8_t *pMacAddress) { - DEBUG_ENTRY - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(nIp), MAC2STR(pMacAddress)); - - for (auto& record : s_ArpRecords) { - if (record.nIp == nIp) { - memcpy(pMacAddress, record.mac_address, ETH_ADDR_LEN); - DEBUG_EXIT - return nIp; - } - - if (record.nIp == 0) { - break; - } - } - - if (net::link_status_read() == net::Link::STATE_DOWN) { - DEBUG_EXIT - return 0; - } - - const auto nEntries = s_Entries; - int32_t nTimeout; - auto nRetries = 3; - - while (nRetries--) { - arp_send_request(nIp); - - nTimeout = 0x1FFFF; -#ifndef NDEBUG - nTimeout+= 0x40000; -#endif - - while ((nTimeout-- > 0) && (nEntries == s_Entries)) { - net_handle(); - } - - if (nEntries != s_Entries) { - memcpy(pMacAddress, s_ArpRecords[nEntries].mac_address, ETH_ADDR_LEN); - DEBUG_PRINTF("timeout=%x", nTimeout); - DEBUG_EXIT - return nIp; - } - - DEBUG_PRINTF("timeout=%d, current_entry=%d, s_entry_current=%d", nTimeout, nEntries, s_Entries); - } - - DEBUG_EXIT - return 0; -} - -void arp_cache_dump() { -#ifndef NDEBUG - printf("ARP Cache size=%d\n", s_Entries); - - for (auto i = 0; i < s_Entries; i++) { - printf("%02d " IPSTR " " MACSTR "\n", i, IP2STR(s_ArpRecords[i].nIp),MAC2STR(s_ArpRecords[i].mac_address)); - } -#endif -} - -#ifndef NDEBUG -void arp_cache_timer() { - s_ticker--; - - if (s_ticker == 0) { - s_ticker = TICKER_COUNT; - arp_cache_dump(); - } -} -#endif diff --git a/lib-network/src/net/autoip.cpp b/lib-network/src/net/autoip.cpp new file mode 100755 index 000000000..cb2fedfd0 --- /dev/null +++ b/lib-network/src/net/autoip.cpp @@ -0,0 +1,172 @@ +/** + * @file autoip.cpp + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +/* This code is inspired by the lwIP TCP/IP stack. + * https://savannah.nongnu.org/projects/lwip/ + */ +/** + * The autoip.cpp aims to be conform to RFC 3927. + * https://datatracker.ietf.org/doc/html/rfc3927 + * Dynamic Configuration of IPv4 Link-Local Addresses + */ + +#ifdef DEBUG_AUTOIP +# undef NDEBUG +#endif + +#include +#include + +#include "netif.h" +#include "net/autoip.h" +#include "net/protocol/autoip.h" +#include "net/acd.h" +#include "net/arp.h" + +#include "debug.h" + +namespace net { +static void autoip_bind(){ + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + assert(autoip != nullptr); + + autoip->state = autoip::State::AUTOIP_STATE_BOUND; + + ip4_addr_t sn_mask, gw_addr; + + sn_mask.addr = network::convert_to_uint(255,255,0,0); + gw_addr.addr = 0; + + netif_set_addr(autoip->llipaddr, sn_mask, gw_addr); +} + +static void autoip_restart() { + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + assert(autoip != nullptr); + + autoip->tried_llipaddr++; + autoip_start(); +} + +static void autoip_conflict_callback(net::acd::Callback state) { + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + assert(autoip != nullptr); + + switch (state) { + case net::acd::Callback::ACD_IP_OK: + autoip_bind(); + netif_set_flags(netif::NETIF_FLAG_AUTOIP_OK); + break; + case net::acd::Callback::ACD_RESTART_CLIENT: + autoip_restart(); + break; + case net::acd::Callback::ACD_DECLINE: + /* "delete" conflicting address so a new one will be selected in autoip_start() */ + autoip->llipaddr.addr = network::IP4_ANY; + autoip_stop(); + netif_clear_flags(netif::NETIF_FLAG_AUTOIP_OK); + break; + default: + break; + } +} + +static void autoip_create_addr(uint32_t &ipaddr) { + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + assert(autoip != nullptr); + + /* Here we create an IP-Address out of range 169.254.1.0 to 169.254.254.255 + * compliant to RFC 3927 Section 2.1 */ + const auto mask = globals::netif_default.hwaddr[3] + (globals::netif_default.hwaddr[4] << 8); + ipaddr = static_cast(mask << 16) | autoip::AUTOIP_RANGE_START; + ipaddr = __builtin_bswap32(ipaddr); + + ipaddr += autoip->tried_llipaddr; + ipaddr = __builtin_bswap32(autoip::AUTOIP_NET) | (ipaddr & 0xffff); + + if (ipaddr < __builtin_bswap32(autoip::AUTOIP_RANGE_START)) { + ipaddr += __builtin_bswap32(autoip::AUTOIP_RANGE_END) - __builtin_bswap32(autoip::AUTOIP_RANGE_START) + 1; + } + + if (ipaddr > __builtin_bswap32(autoip::AUTOIP_RANGE_END)) { + ipaddr -= __builtin_bswap32(autoip::AUTOIP_RANGE_END) - __builtin_bswap32(autoip::AUTOIP_RANGE_START) + 1; + } + + ipaddr = __builtin_bswap32(ipaddr); + + DEBUG_PRINTF(IPSTR, IP2STR(ipaddr)); +} + +/* + * Public interface + */ + +void autoip_start() { + DEBUG_ENTRY + + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + + if (autoip == nullptr) { + autoip = new (struct autoip::Autoip); + assert(autoip != nullptr); + memset(autoip, 0, sizeof(struct autoip::Autoip)); + } + + if (autoip->state == autoip::State::AUTOIP_STATE_OFF) { + acd_add(&autoip->acd, autoip_conflict_callback); + + /* In accordance to RFC3927 section 2.1: + * Keep using the same link local address as much as possible. + * Only when there is none or when there was a conflict, select a new one. + */ + if (!network::is_linklocal_ip(autoip->llipaddr.addr)) { + autoip_create_addr(autoip->llipaddr.addr); + } + + autoip->state = autoip::State::AUTOIP_STATE_CHECKING; + acd_start(&autoip->acd, autoip->llipaddr); + } else { + DEBUG_PUTS("Already started"); + } + + DEBUG_EXIT +} + +void autoip_stop() { + DEBUG_ENTRY + auto *autoip = reinterpret_cast(globals::netif_default.autoip); + + if (autoip != nullptr) { + autoip->state = autoip::State::AUTOIP_STATE_OFF; + + ip4_addr_t any; + any.addr = network::IP4_ANY; + + if (network::is_linklocal_ip(globals::netif_default.ip.addr)) { + netif_set_addr(any, any, any); + } + } + + DEBUG_EXIT +} +} // namespace net diff --git a/lib-network/src/net/dhcp.cpp b/lib-network/src/net/dhcp.cpp index f1133e489..7bc1f3095 100755 --- a/lib-network/src/net/dhcp.cpp +++ b/lib-network/src/net/dhcp.cpp @@ -1,8 +1,7 @@ /** * @file dhcp.cpp - * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,385 +21,852 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/* This code is inspired by the lwIP TCP/IP stack. + * https://savannah.nongnu.org/projects/lwip/ + */ + +#if defined (DEBUG_NET_DHCP) +# undef NDEBUG +#endif + +#pragma GCC push_options +#pragma GCC optimize ("Os") #include #include #include -#include "dhcp_internal.h" - #include "net.h" +#include "net_memcpy.h" #include "net_private.h" #include "hardware.h" +#include "network.h" #include "../../config/net_config.h" -namespace net { -namespace globals { -extern struct IpInfo ipInfo; -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net +#include "net/dhcp.h" +#include "net/protocol/dhcp.h" +#include "net/protocol/iana.h" +#include "net/acd.h" +#include "net/autoip.h" +#include "netif.h" -typedef union pcast32 { - uint32_t u32; - uint8_t u8[4]; -} _pcast32; +#define REBOOT_TRIES 2 + +static int32_t nTimerId; // https://tools.ietf.org/html/rfc1541 +namespace net { +static dhcp::Message s_dhcp_message SECTION_NETWORK ALIGNED; + +static void message_init() { + memset(&s_dhcp_message, 0, sizeof(dhcp::Message)); -namespace dhcp { -struct Message { - uint8_t op; - uint8_t htype; - uint8_t hlen; - uint8_t hops; - uint32_t xid; - uint16_t secs; - uint16_t flags; - uint8_t ciaddr[IPv4_ADDR_LEN]; - uint8_t yiaddr[IPv4_ADDR_LEN]; - uint8_t siaddr[IPv4_ADDR_LEN]; - uint8_t giaddr[IPv4_ADDR_LEN]; - uint8_t chaddr[16]; - uint8_t sname[64]; - uint8_t file[128]; - uint8_t options[DHCP_OPT_SIZE]; -}PACKED; -} // namespace dhcp - -enum OPTIONS { - OPTIONS_PAD_OPTION = 0, - OPTIONS_SUBNET_MASK = 1, - OPTIONS_ROUTERS_ON_SUBNET = 3, - OPTIONS_DNS = 6, - OPTIONS_HOSTNAME = 12, - OPTIONS_DOMAIN_NAME = 15, - OPTIONS_REQUESTED_IP = 50, - OPTIONS_MESSAGE_TYPE = 53, - OPTIONS_SERVER_IDENTIFIER = 54, - OPTIONS_PARAM_REQUEST = 55, - OPTIONS_DHCP_T1_VALUE = 58, - OPTIONS_DHCP_T2_VALUE = 59, - OPTIONS_CLIENT_IDENTIFIER = 61, - OPTIONS_END_OPTION = 255 -}; - -static dhcp::Message s_dhcp_message ALIGNED; - -static uint8_t s_dhcp_server_ip[IPv4_ADDR_LEN] ALIGNED = { 0, }; -static uint8_t s_dhcp_allocated_ip[IPv4_ADDR_LEN] ALIGNED = { 0, }; -static uint8_t s_dhcp_allocated_gw[IPv4_ADDR_LEN] ALIGNED = { 0, }; -static uint8_t s_dhcp_allocated_netmask[IPv4_ADDR_LEN] ALIGNED = { 0, }; - -static void message_init(const uint8_t *pMacAddress) { - auto *p = reinterpret_cast(&s_dhcp_message); - - for (uint32_t i = 0; i < sizeof(dhcp::Message); i++) { - *p++ = 0; - } - - s_dhcp_message.op = DHCP_OP_BOOTREQUEST; - s_dhcp_message.htype = DHCP_HTYPE_10MB; // This is the current default - s_dhcp_message.hlen = ETH_ADDR_LEN; - memcpy(s_dhcp_message.chaddr, pMacAddress, ETH_ADDR_LEN); - - s_dhcp_message.options[0] = static_cast((MAGIC_COOKIE & 0xFF000000) >> 24); - s_dhcp_message.options[1] = static_cast((MAGIC_COOKIE & 0x00FF0000) >> 16); - s_dhcp_message.options[2] = static_cast((MAGIC_COOKIE & 0x0000FF00) >> 8); - s_dhcp_message.options[3] = static_cast(MAGIC_COOKIE & 0x000000FF) >> 0; - - s_dhcp_message.options[4] = OPTIONS_MESSAGE_TYPE; + s_dhcp_message.op = dhcp::OpCode::BOOTREQUEST; + s_dhcp_message.htype = dhcp::HardwareType::HTYPE_10MB; // This is the current default + s_dhcp_message.hlen = network::MAC_SIZE; + memcpy(s_dhcp_message.chaddr, net::globals::netif_default.hwaddr, network::MAC_SIZE); + + s_dhcp_message.options[0] = static_cast((dhcp::MAGIC_COOKIE & 0xFF000000) >> 24); + s_dhcp_message.options[1] = static_cast((dhcp::MAGIC_COOKIE & 0x00FF0000) >> 16); + s_dhcp_message.options[2] = static_cast((dhcp::MAGIC_COOKIE & 0x0000FF00) >> 8); + s_dhcp_message.options[3] = static_cast(dhcp::MAGIC_COOKIE & 0x000000FF) >> 0; + + s_dhcp_message.options[4] = dhcp::Options::OPTION_MESSAGE_TYPE; s_dhcp_message.options[5] = 0x01; } -static void send_discover(int nHandle, const uint8_t *pMacAddress) { +static void dhcp_update_msg(const uint8_t message_type) { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + /* DHCP_REQUEST should reuse 'xid' from DHCPOFFER */ + if ((message_type != dhcp::Type::REQUEST) || (dhcp->state == dhcp::State::STATE_REBOOTING)) { + /* reuse transaction identifier in retransmissions */ + if (dhcp->tries == 0) { + auto xid = __builtin_bswap32(dhcp->xid); + xid++; + dhcp->xid = __builtin_bswap32(xid); + } + } + + s_dhcp_message.xid = dhcp->xid; + + if ((message_type == dhcp::Type::INFORM) + || (message_type == dhcp::Type::DECLINE) + || (message_type == dhcp::Type::RELEASE) + || ((message_type == dhcp::Type::REQUEST) + && /* DHCP_STATE_BOUND not used for sending! */ + ((dhcp->state == dhcp::State::STATE_RENEWING) || dhcp->state == dhcp::State::STATE_REBINDING))) { + + const auto &netif = net::globals::netif_default; + net::memcpy_ip(s_dhcp_message.ciaddr, netif.ip.addr); + } +} + +static void send_discover() { DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + dhcp_update_msg(dhcp::Type::DISCOVER); uint32_t k = 6; - s_dhcp_message.options[k++] = DCHP_TYPE_DISCOVER; + s_dhcp_message.options[k++] = dhcp::Type::DISCOVER; - s_dhcp_message.options[k++] = OPTIONS_CLIENT_IDENTIFIER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_CLIENT_IDENTIFIER; s_dhcp_message.options[k++] = 0x07; s_dhcp_message.options[k++] = 0x01; - s_dhcp_message.options[k++] = pMacAddress[0]; - s_dhcp_message.options[k++] = pMacAddress[1]; - s_dhcp_message.options[k++] = pMacAddress[2]; - s_dhcp_message.options[k++] = pMacAddress[3]; - s_dhcp_message.options[k++] = pMacAddress[4]; - s_dhcp_message.options[k++] = pMacAddress[5]; - - s_dhcp_message.options[k++] = OPTIONS_PARAM_REQUEST; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[0]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[1]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[2]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[3]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[4]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[5]; + + s_dhcp_message.options[k++] = dhcp::Options::OPTION_PARAM_REQUEST; s_dhcp_message.options[k++] = 0x06; // length of request - s_dhcp_message.options[k++] = OPTIONS_SUBNET_MASK; - s_dhcp_message.options[k++] = OPTIONS_ROUTERS_ON_SUBNET; - s_dhcp_message.options[k++] = OPTIONS_DNS; - s_dhcp_message.options[k++] = OPTIONS_DOMAIN_NAME; - s_dhcp_message.options[k++] = OPTIONS_DHCP_T1_VALUE; - s_dhcp_message.options[k++] = OPTIONS_DHCP_T2_VALUE; - s_dhcp_message.options[k++] = OPTIONS_END_OPTION; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_SUBNET_MASK; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_ROUTER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DOMAIN_NAME; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_LEASE_TIME; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DHCP_T1_VALUE; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DHCP_T2_VALUE; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_END; - udp_send(nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); + udp_send(dhcp->nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - dhcp::OPT_SIZE), network::IP4_BROADCAST, net::iana::IANA_PORT_DHCP_SERVER); DEBUG_EXIT } -static void send_request(int idx, const uint8_t *pMacAddress, const char *pHostname) { +static void send_request() { DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); uint32_t i; uint32_t k = 6; - s_dhcp_message.options[k++] = DCHP_TYPE_REQUEST; + s_dhcp_message.options[k++] = dhcp::Type::REQUEST; - s_dhcp_message.options[k++] = OPTIONS_CLIENT_IDENTIFIER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_CLIENT_IDENTIFIER; s_dhcp_message.options[k++] = 0x07; s_dhcp_message.options[k++] = 0x01; - s_dhcp_message.options[k++] = pMacAddress[0]; - s_dhcp_message.options[k++] = pMacAddress[1]; - s_dhcp_message.options[k++] = pMacAddress[2]; - s_dhcp_message.options[k++] = pMacAddress[3]; - s_dhcp_message.options[k++] = pMacAddress[4]; - s_dhcp_message.options[k++] = pMacAddress[5]; - - s_dhcp_message.options[k++] = OPTIONS_REQUESTED_IP; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[0]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[1]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[2]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[3]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[4]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[5]; + + s_dhcp_message.options[k++] = dhcp::Options::OPTION_REQUESTED_IP; s_dhcp_message.options[k++] = 0x04; - s_dhcp_message.options[k++] = s_dhcp_allocated_ip[0]; - s_dhcp_message.options[k++] = s_dhcp_allocated_ip[1]; - s_dhcp_message.options[k++] = s_dhcp_allocated_ip[2]; - s_dhcp_message.options[k++] = s_dhcp_allocated_ip[3]; + memcpy_ip(&s_dhcp_message.options[k], dhcp->offered.offered_ip_addr.addr); + k = k + 4; - s_dhcp_message.options[k++] = OPTIONS_SERVER_IDENTIFIER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_SERVER_IDENTIFIER; s_dhcp_message.options[k++] = 0x04; - s_dhcp_message.options[k++] = s_dhcp_server_ip[0]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[1]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[2]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[3]; + memcpy_ip(&s_dhcp_message.options[k], dhcp->server_ip_addr.addr); + k = k + 4; - s_dhcp_message.options[k++] = OPTIONS_HOSTNAME; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_HOSTNAME; s_dhcp_message.options[k++] = 0; // length of hostname - for (i = 0; pHostname[i] != 0; i++) { - s_dhcp_message.options[k++] = pHostname[i]; + for (i = 0; net::globals::netif_default.hostname[i] != 0; i++) { + s_dhcp_message.options[k++] = net::globals::netif_default.hostname[i]; } s_dhcp_message.options[k - (i + 1)] = static_cast(i); // length of hostname - s_dhcp_message.options[k++] = OPTIONS_PARAM_REQUEST; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_PARAM_REQUEST; s_dhcp_message.options[k++] = 0x06; // length of request - s_dhcp_message.options[k++] = OPTIONS_SUBNET_MASK; - s_dhcp_message.options[k++] = OPTIONS_ROUTERS_ON_SUBNET; - s_dhcp_message.options[k++] = OPTIONS_DNS; - s_dhcp_message.options[k++] = OPTIONS_DOMAIN_NAME; - s_dhcp_message.options[k++] = OPTIONS_DHCP_T1_VALUE; - s_dhcp_message.options[k++] = OPTIONS_DHCP_T2_VALUE; - s_dhcp_message.options[k++] = OPTIONS_END_OPTION; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_SUBNET_MASK; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_ROUTER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DNS_SERVER; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DOMAIN_NAME; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DHCP_T1_VALUE; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_DHCP_T2_VALUE; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_END; - udp_send(idx, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); + udp_send(dhcp->nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - dhcp::OPT_SIZE), network::IP4_BROADCAST, net::iana::IANA_PORT_DHCP_SERVER); DEBUG_EXIT } -static int parse_response(const int nHandle, const uint8_t *pMacAddress) { - uint8_t *pResponse; - uint32_t nSize = 0; - uint32_t nTimeOut = 0; +static void dhcp_send_release(const uint32_t nDestinationIp) { + DEBUG_ENTRY + DEBUG_PRINTF(IPSTR, IP2STR(nDestinationIp)); - const auto nMillis = Hardware::Get()->Millis(); + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); - do { - net_handle(); + uint32_t k = 6; - uint32_t nFromIp; - uint16_t nFromPort; + s_dhcp_message.options[k++] = dhcp::Type::RELEASE; - nSize = udp_recv2(nHandle, const_cast(&pResponse), &nFromIp, &nFromPort); + s_dhcp_message.options[k++] = dhcp::Options::OPTION_SERVER_IDENTIFIER; + s_dhcp_message.options[k++] = 0x04; + net::memcpy_ip(&s_dhcp_message.options[k], dhcp->server_ip_addr.addr); + k = k + 4; - if ((nSize > 0) && (nFromPort == DHCP_PORT_SERVER)) { + s_dhcp_message.options[k++] = dhcp::Options::OPTION_END; - const auto *const pDhcpMessage = reinterpret_cast(pResponse); + udp_send(dhcp->nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - dhcp::OPT_SIZE), nDestinationIp, net::iana::IANA_PORT_DHCP_SERVER); - if (memcmp(pDhcpMessage->chaddr, pMacAddress, ETH_ADDR_LEN) == 0) { - DEBUG_PUTS("break"); - break; - } - } + DEBUG_EXIT +} - nTimeOut = Hardware::Get()->Millis() - nMillis; - } while (nTimeOut < 500); +void dhcp_inform() { + DEBUG_ENTRY - DEBUG_PRINTF("timeout %u, nSize=%u", Hardware::Get()->Millis() - nMillis, nSize); + const auto nHandle = udp_begin(net::iana::IANA_PORT_DHCP_CLIENT); +#ifndef NDEBUG + if (nHandle < 0) { + console_error("DHCP Inform\n"); + return; + } +#endif - int type = 0; - uint8_t opt_len = 0; + message_init(); + net::memcpy_ip(&s_dhcp_message.ciaddr[0], net::globals::netif_default.ip.addr); - if (nSize > 0) { - auto *p = pResponse; - p = p + sizeof(dhcp::Message) - DHCP_OPT_SIZE + 4; - auto *e = pResponse + nSize; - - while (p < e) { - switch (*p) { - case OPTIONS_END_OPTION: - p = e; - break; - case OPTIONS_PAD_OPTION: - p++; - break; - case OPTIONS_MESSAGE_TYPE: - p++; - p++; - type = *p++; - break; - case OPTIONS_SUBNET_MASK: - p++; - p++; - s_dhcp_allocated_netmask[0] = *p++; - s_dhcp_allocated_netmask[1] = *p++; - s_dhcp_allocated_netmask[2] = *p++; - s_dhcp_allocated_netmask[3] = *p++; - break; - case OPTIONS_ROUTERS_ON_SUBNET: - p++; - opt_len = *p++; - s_dhcp_allocated_gw[0] = *p++; - s_dhcp_allocated_gw[1] = *p++; - s_dhcp_allocated_gw[2] = *p++; - s_dhcp_allocated_gw[3] = *p++; - p = p + (opt_len - 4); - break; - case OPTIONS_SERVER_IDENTIFIER : - p++; - opt_len = *p++; - s_dhcp_server_ip[0] = *p++; - s_dhcp_server_ip[1] = *p++; - s_dhcp_server_ip[2] = *p++; - s_dhcp_server_ip[3] = *p++; - break; - default: - p++; - opt_len = *p++; - p += opt_len; - break; - } - } + uint32_t k = 6; + + s_dhcp_message.options[k++] = dhcp::Type::INFORM; + + s_dhcp_message.options[k++] = dhcp::Options::OPTION_CLIENT_IDENTIFIER; + s_dhcp_message.options[k++] = 0x07; + s_dhcp_message.options[k++] = 0x01; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[0]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[1]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[2]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[3]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[4]; + s_dhcp_message.options[k++] = net::globals::netif_default.hwaddr[5]; + + s_dhcp_message.options[k++] = dhcp::Options::OPTION_END; + + udp_send(nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - dhcp::OPT_SIZE), network::IP4_BROADCAST, net::iana::IANA_PORT_DHCP_SERVER); + udp_end(net::iana::IANA_PORT_DHCP_CLIENT); + + DEBUG_EXIT +} + +#define SET_TIMEOUT_FROM_OFFERED(result, offered, min, max) do { \ + uint32_t timeout = (offered + dhcp::DHCP_COARSE_TIMER_SECS / 2) / dhcp::DHCP_COARSE_TIMER_SECS; \ + if (timeout > max) { \ + timeout = max; \ + } \ + if (timeout == min) { \ + timeout = 1; \ + } \ + result = static_cast(timeout); \ +} while(0) + +#define DHCP_SET_TIMEOUT_FROM_OFFERED_T0_LEASE(res, dhcp) SET_TIMEOUT_FROM_OFFERED(res, (dhcp)->offered.offered_t0_lease, 0, 0xffff) +#define DHCP_SET_TIMEOUT_FROM_OFFERED_T1_RENEW(res, dhcp) SET_TIMEOUT_FROM_OFFERED(res, (dhcp)->offered.offered_t1_renew, 0, 0xffff) +#define DHCP_SET_TIMEOUT_FROM_OFFERED_T2_REBIND(res, dhcp) SET_TIMEOUT_FROM_OFFERED(res, (dhcp)->offered.offered_t2_rebind, 0, 0xffff) + +#define DHCP_NEXT_TIMEOUT_THRESHOLD ((60 + net::dhcp::DHCP_COARSE_TIMER_SECS / 2) / net::dhcp::DHCP_COARSE_TIMER_SECS) +#define DHCP_REQUEST_BACKOFF_SEQUENCE(tries) (( (tries) < 6U ? 1U << (tries) : 60U) * 1000U) + +static void dhcp_set_state(struct dhcp::Dhcp *dhcp, dhcp::State new_state) { + if (new_state != dhcp->state) { + DEBUG_PRINTF("%u -> %u", static_cast(dhcp->state), static_cast(new_state)); + + dhcp->state = new_state; + dhcp->tries = 0; + dhcp->request_timeout = 0; + } +} + +static void dhcp_bind() { + DEBUG_ENTRY + + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + /* reset time used of lease */ + dhcp->lease_used = 0; + + if (dhcp->offered.offered_t0_lease != 0xffffffffUL) { + /* set renewal period timer */ + DHCP_SET_TIMEOUT_FROM_OFFERED_T0_LEASE(dhcp->t0_timeout, dhcp); + } - if (type == DCHP_TYPE_OFFER) { - const auto *const pDhcpMessage = reinterpret_cast(pResponse); - s_dhcp_allocated_ip[0] = pDhcpMessage->yiaddr[0]; - s_dhcp_allocated_ip[1] = pDhcpMessage->yiaddr[1]; - s_dhcp_allocated_ip[2] = pDhcpMessage->yiaddr[2]; - s_dhcp_allocated_ip[3] = pDhcpMessage->yiaddr[3]; + /* temporary DHCP lease? */ + if (dhcp->offered.offered_t1_renew != 0xffffffffUL) { + /* set renewal period timer */ + DHCP_SET_TIMEOUT_FROM_OFFERED_T1_RENEW(dhcp->t1_timeout, dhcp); + dhcp->t1_renew_time = dhcp->t1_timeout; + } + /* set renewal period timer */ + if (dhcp->offered.offered_t2_rebind != 0xffffffffUL) { + DHCP_SET_TIMEOUT_FROM_OFFERED_T2_REBIND(dhcp->t2_timeout, dhcp); + dhcp->t2_rebind_time = dhcp->t2_timeout; + } + + /* If we have sub 1 minute lease, t2 and t1 will kick in at the same time. */ + if ((dhcp->t1_timeout >= dhcp->t2_timeout) && (dhcp->t2_timeout > 0)) { + dhcp->t1_timeout = 0; + } + + ip4_addr_t sn_mask; + + if (dhcp->flags & DHCP_FLAG_SUBNET_MASK_GIVEN) { + /* copy offered network mask */ + sn_mask.addr = dhcp->offered.offered_sn_mask.addr; + } else { + /* subnet mask not given, choose a safe subnet mask given the network class */ + const uint8_t first_octet = dhcp->offered.offered_ip_addr.addr & 0xFF; + if (first_octet <= 127) { + sn_mask.addr = 0xFF; + } else if (first_octet >= 192) { + sn_mask.addr = 0xFFFFFF; + } else { + sn_mask.addr = 0xFFFF; } + } + + ip4_addr_t gw_addr; + gw_addr.addr = dhcp->offered.offered_gw_addr.addr; + + dhcp_set_state(dhcp, dhcp::State::STATE_BOUND); + + netif_set_flags(netif::NETIF_FLAG_DHCP_OK); + netif_set_addr(dhcp->offered.offered_ip_addr, sn_mask, gw_addr); + + DEBUG_EXIT +} + +static void dhcp_rebind() { + DEBUG_ENTRY + + DEBUG_EXIT +} + +#if defined (CONFIG_NET_DHCP_USE_ACD) +static void dhcp_send_decline() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + dhcp_update_msg(dhcp::Type::DECLINE); + + uint32_t k = 6; + + s_dhcp_message.options[k++] = dhcp::Type::DECLINE; + + s_dhcp_message.options[k++] = dhcp::Options::OPTION_REQUESTED_IP; + s_dhcp_message.options[k++] = 0x04; + net::memcpy_ip(&s_dhcp_message.options[k], dhcp->offered.offered_ip_addr.addr); + k = k + 4; + s_dhcp_message.options[k++] = dhcp::Options::OPTION_END; + + udp_send(dhcp->nHandle, reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - dhcp::OPT_SIZE), network::IP4_BROADCAST, net::iana::IANA_PORT_DHCP_SERVER); - return type; + DEBUG_EXIT +} + +static void dhcp_decline() { + DEBUG_ENTRY + + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + dhcp_set_state(dhcp, dhcp::State::STATE_BACKING_OFF); + /* per section 4.4.4, broadcast DECLINE messages */ + dhcp_send_decline(); + + DEBUG_EXIT + return; +} + +static void dhcp_conflict_callback(net::acd::Callback callback) { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + assert(dhcp->state != dhcp::State::STATE_OFF); + + uint16_t msecs; + + switch (callback) { + case net::acd::Callback::ACD_IP_OK: + dhcp_bind(); + break; + case net::acd::Callback::ACD_RESTART_CLIENT: + /* wait 10s before restarting + * According to RFC2131 section 3.1 point 5: + * If the client detects that the address is already in use (e.g., through + * the use of ARP), the client MUST send a DHCPDECLINE message to the + * server and restarts the configuration process. The client SHOULD wait + * a minimum of ten seconds before restarting the configuration process to + * avoid excessive network traffic in case of looping. */ + dhcp_set_state (dhcp, dhcp::State::STATE_BACKING_OFF); + msecs = 10U * 1000U; + dhcp->request_timeout = static_cast((msecs + dhcp::DHCP_FINE_TIMER_MSECS - 1) / dhcp::DHCP_FINE_TIMER_MSECS); + break; + case net::acd::Callback::ACD_DECLINE: + /* remove IP address from interface + * (prevents routing from selecting this interface) */ + ip4_addr_t any; + any.addr = 0; + netif_set_addr(any, any, any); + /* Let the DHCP server know we will not use the address */ + dhcp_decline(); + netif_clear_flags(netif::NETIF_FLAG_DHCP_OK); + break; + default: + break; } +} + +static void dhcp_check() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); - return -1; + dhcp_set_state(dhcp, dhcp::State::STATE_CHECKING); + + acd_start(&dhcp->acd, dhcp->offered.offered_ip_addr); + + DEBUG_EXIT } +#endif -int dhcp_client(const char *pHostname) { +static void dhcp_discover() { DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); - message_init(net::globals::macAddress); +#if defined (CONFIG_NET_DHCP_USE_AUTOIP) + if (dhcp->tries >= DHCP_AUTOIP_COOP_TRIES) { + autoip_start(); + } +#endif - auto nHandle = udp_begin(DHCP_PORT_CLIENT); + dhcp->offered.offered_ip_addr.addr = 0; - if (nHandle < 0) { - DEBUG_EXIT - return -1; + dhcp_set_state(dhcp, dhcp::State::STATE_SELECTING); + + send_discover(); + + if (dhcp->tries < 255) { + dhcp->tries++; } - net::globals::ipInfo.ip.addr = 0; - ip_set_ip(); + const auto msecs = DHCP_REQUEST_BACKOFF_SEQUENCE(dhcp->tries); + dhcp->request_timeout = static_cast((msecs + dhcp::DHCP_FINE_TIMER_MSECS - 1) / dhcp::DHCP_FINE_TIMER_MSECS); +} + +static void dhcp_reboot() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); - int32_t retries = 10; + dhcp_set_state(dhcp, dhcp::State::STATE_REBOOTING); - while (retries-- > 0) { - DEBUG_PRINTF("retries=%d", retries); + send_request(); - send_discover(static_cast(nHandle), net::globals::macAddress); + if (dhcp->tries < 255) { + dhcp->tries++; + } - int type; + const auto msecs = static_cast(dhcp->tries < 10U ? dhcp->tries * 1000U : 10U * 1000U); + dhcp->request_timeout = static_cast((msecs + dhcp::DHCP_FINE_TIMER_MSECS - 1) / dhcp::DHCP_FINE_TIMER_MSECS); - if ((type = parse_response(static_cast(nHandle), net::globals::macAddress)) < 0) { - continue; + DEBUG_EXIT +} + +static void dhcp_select() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + dhcp_set_state(dhcp, dhcp::State::STATE_REQUESTING); + + send_request(); + + if (dhcp->tries < 255) { + dhcp->tries++; + } + + const auto msecs = static_cast((dhcp->tries < 6 ? 1 << dhcp->tries : 60U) * 1000U); + dhcp->request_timeout = static_cast((msecs + dhcp::DHCP_FINE_TIMER_MSECS - 1) / dhcp::DHCP_FINE_TIMER_MSECS); +} + +static void dhcp_timeout() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + /* back-off period has passed, or server selection timed out */ + if ((dhcp->state == dhcp::State::STATE_BACKING_OFF) || (dhcp->state == dhcp::State::STATE_SELECTING)) { + dhcp_discover(); + /* receiving the requested lease timed out */ + } else if (dhcp->state == dhcp::State::STATE_REQUESTING) { + if (dhcp->tries <= 5) { + dhcp_select(); + } else { + dhcp_release_and_stop(); + dhcp_start(); + } + } else if (dhcp->state == dhcp::State::STATE_REBOOTING) { + if (dhcp->tries < REBOOT_TRIES) { + dhcp_reboot(); + } else { + dhcp_discover(); + } + } +} + +static void dhcp_t1_timeout() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if ((dhcp->state == dhcp::State::STATE_REQUESTING) + || (dhcp->state == dhcp::State::STATE_BOUND) + || (dhcp->state == dhcp::State::STATE_RENEWING)) { + /* just retry to renew - note that the rebind timer (t2) will + * eventually time-out if renew tries fail. */ + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_STATE_RENEWING, not DHCP_STATE_BOUND */ + dhcp_renew(); + /* Calculate next timeout */ + if (static_cast((dhcp->t2_timeout - dhcp->lease_used) / 2) >= DHCP_NEXT_TIMEOUT_THRESHOLD) { + dhcp->t1_renew_time = static_cast((dhcp->t2_timeout - dhcp->lease_used) / 2); } + } +} - DEBUG_PRINTF("type=%d", type); +static void dhcp_t2_timeout() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if ((dhcp->state == dhcp::State::STATE_REQUESTING) + || (dhcp->state == dhcp::State::STATE_BOUND) + || (dhcp->state == dhcp::State::STATE_RENEWING) + || (dhcp->state == dhcp::State::STATE_REBINDING)) { + /* just retry to rebind */ + /* This slightly different to RFC2131: DHCPREQUEST will be sent from state + DHCP_STATE_REBINDING, not DHCP_STATE_BOUND */ + dhcp_rebind(); + /* Calculate next timeout */ + if (static_cast((dhcp->t0_timeout - dhcp->lease_used) / 2) >= DHCP_NEXT_TIMEOUT_THRESHOLD) { + dhcp->t2_rebind_time = static_cast((dhcp->t0_timeout - dhcp->lease_used) / 2); + } + } +} - if (type == DCHP_TYPE_OFFER) { - DEBUG_PRINTF(IPSTR, s_dhcp_server_ip[0],s_dhcp_server_ip[1],s_dhcp_server_ip[2],s_dhcp_server_ip[3]); - break; +void dhcp_coarse_tmr() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if ((dhcp != nullptr) && (dhcp->state != dhcp::State::STATE_OFF)) { + /* compare lease time to expire timeout */ + if (dhcp->t0_timeout && (++dhcp->lease_used == dhcp->t0_timeout)) { + /* this clients' lease time has expired */ + dhcp_release_and_stop(); + dhcp_start(); + /* timer is active (non zero), and triggers (zeroes) now? */ + } else if (dhcp->t2_rebind_time && (dhcp->t2_rebind_time-- == 1)) { + /* this clients' rebind timeout triggered */ + dhcp_t2_timeout(); + /* timer is active (non zero), and triggers (zeroes) now */ + } else if (dhcp->t1_renew_time && (dhcp->t1_renew_time-- == 1)) { + /* this clients' renewal timeout triggered */ + dhcp_t1_timeout(); + } + } +} + +static void dhcp_fine_tmr() { + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if (dhcp != nullptr) { + /* timer is active (non zero), and is about to trigger now */ + if (dhcp->request_timeout > 1) { + dhcp->request_timeout--; + } else if (dhcp->request_timeout == 1) { + dhcp->request_timeout--; + /* this client's request timeout triggered */ + dhcp_timeout(); } } +} + +static void dhcp_handle_offer(const dhcp::Message *const pResponse) { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if (dhcp->server_ip_addr.addr != 0) { + dhcp->request_timeout = 0; /* stop timer */ + dhcp->offered.offered_ip_addr.addr = net::memcpy_ip(pResponse->yiaddr); + DEBUG_PRINTF(IPSTR " -> " IPSTR, IP2STR(dhcp->server_ip_addr.addr), IP2STR(dhcp->offered.offered_ip_addr.addr)); + dhcp_select(); + } else { + DEBUG_PUTS("did not get server ID!"); + } - auto bHaveIp = false; + DEBUG_EXIT +} - while (retries-- > 0) { - DEBUG_PRINTF("retries=%d", retries); +static void dhcp_handle_ack(const dhcp::Message *const pResponse) { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); - send_request(static_cast(nHandle), net::globals::macAddress, pHostname); + DEBUG_PRINTF("t0=%u, t1=%u, t2=%u", dhcp->offered.offered_t0_lease, dhcp->offered.offered_t1_renew, dhcp->offered.offered_t2_rebind); - int type; + if (dhcp->offered.offered_t1_renew == 0) { + /* calculate safe periods for renewal */ + dhcp->offered.offered_t1_renew = dhcp->offered.offered_t0_lease / 2; + } - if ((type =parse_response(static_cast(nHandle), net::globals::macAddress)) < 0) { - continue; - } + if (dhcp->offered.offered_t2_rebind == 0) { + /* calculate safe periods for rebinding (offered_t0_lease * 0.875 -> 87.5%)*/ + dhcp->offered.offered_t2_rebind = (dhcp->offered.offered_t0_lease * 7U) / 8U; + } - DEBUG_PRINTF("type=%d", type); + dhcp->offered.offered_ip_addr.addr = net::memcpy_ip(pResponse->yiaddr); - if (type == DCHP_TYPE_ACK) { - bHaveIp = true; - DEBUG_PUTS("bHaveIp = true"); - break; - } + if (dhcp->offered.offered_sn_mask.addr != 0) { + dhcp->flags |= DHCP_FLAG_SUBNET_MASK_GIVEN; + } else { + dhcp->flags &= ~DHCP_FLAG_SUBNET_MASK_GIVEN; + } + + DEBUG_PRINTF("t0=%u, t1=%u, t2=%u", dhcp->offered.offered_t0_lease, dhcp->offered.offered_t1_renew, dhcp->offered.offered_t2_rebind); + DEBUG_EXIT +} + +static void dhcp_handle_nak() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + // Change to a defined state - set this before assigning the address + // to ensure the callback can use dhcp_supplied_address() + dhcp_set_state(dhcp, dhcp::State::STATE_BACKING_OFF); + // remove IP address from interface (must no longer be used, as per RFC2131) + ip4_addr_t any; + any.addr = 0; + netif_set_addr(any, any, any); + // We can immediately restart discovery + dhcp_discover(); + + DEBUG_EXIT +} + +bool dhcp_start() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if (dhcp == nullptr) { + dhcp = new (struct dhcp::Dhcp); + assert(dhcp != nullptr); + globals::netif_default.dhcp = dhcp; + + nTimerId = Hardware::Get()->SoftwareTimerAdd(dhcp::DHCP_FINE_TIMER_MSECS, dhcp_fine_tmr); + assert(nTimerId >= 0); } - if (bHaveIp) { - _pcast32 ip; + memset(dhcp, 0, sizeof(struct dhcp::Dhcp)); + dhcp->nHandle = udp_begin(net::iana::IANA_PORT_DHCP_CLIENT); + +#ifndef NDEBUG + if (dhcp->nHandle < 0) { + console_error("DHCP Start\n"); + DEBUG_EXIT + return false; + } +#endif - memcpy(ip.u8, s_dhcp_allocated_ip, IPv4_ADDR_LEN); - net::globals::ipInfo.ip.addr = ip.u32; + message_init(); - memcpy(ip.u8, s_dhcp_allocated_gw, IPv4_ADDR_LEN); - net::globals::ipInfo.gw.addr = ip.u32; +#if defined (CONFIG_NET_DHCP_USE_ACD) + acd_add(&dhcp->acd, dhcp_conflict_callback); +#endif - memcpy(ip.u8, s_dhcp_allocated_netmask, IPv4_ADDR_LEN); - net::globals::ipInfo.netmask.addr = ip.u32; + if (!netif_is_link_up()) { + dhcp_set_state(dhcp, dhcp::State::STATE_INIT); + return false; } - udp_end(DHCP_PORT_CLIENT); + dhcp_discover(); DEBUG_EXIT - return bHaveIp ? 0 : -2; + return true; } -void dhcp_client_release() { +void dhcp_release_and_stop() { DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); - auto nHandle = udp_begin(DHCP_PORT_CLIENT); + if (dhcp == nullptr) { + DEBUG_EXIT + return; + } - if (nHandle < 0) { - console_error("dhcp_client_release\n"); + if (dhcp->state == dhcp::State::STATE_OFF) { return; } - uint32_t k = 6; + ip4_addr_t server_ip_addr; - s_dhcp_message.options[k++] = DCHP_TYPE_RELEASE; + server_ip_addr.addr = dhcp->server_ip_addr.addr; - s_dhcp_message.options[k++] = OPTIONS_SERVER_IDENTIFIER; - s_dhcp_message.options[k++] = 0x04; - s_dhcp_message.options[k++] = s_dhcp_server_ip[0]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[1]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[2]; - s_dhcp_message.options[k++] = s_dhcp_server_ip[3]; + /* clean old DHCP offer */ + dhcp->server_ip_addr.addr = 0; + memset(&dhcp->offered, 0, sizeof(struct dhcp::Dhcp::Offered)); + dhcp->t1_renew_time = dhcp->t2_rebind_time = dhcp->lease_used = dhcp->t0_timeout = 0; + + if (dhcp_supplied_address()) { + dhcp_set_state(dhcp, dhcp::State::STATE_OFF); + + dhcp_send_release(server_ip_addr.addr); + + udp_end(net::iana::IANA_PORT_DHCP_CLIENT); + + /* remove IP address from interface (prevents routing from selecting this interface) */ + ip4_addr_t any; + any.addr = 0; + netif_set_addr(any, any, any); + } + +#if defined (CONFIG_NET_DHCP_USE_ACD) + acd_remove(&dhcp->acd); +#endif + + delete reinterpret_cast(globals::netif_default.dhcp); + globals::netif_default.dhcp = nullptr; +} - s_dhcp_message.options[k++] = OPTIONS_END_OPTION; +void dhcp_network_changed_link_up() { + DEBUG_ENTRY + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + + if (dhcp == nullptr) { + DEBUG_EXIT + return; + } + + switch (dhcp->state) { + case dhcp::State::STATE_REBINDING: + case dhcp::State::STATE_RENEWING: + case dhcp::State::STATE_BOUND: + case dhcp::State::STATE_REBOOTING: + dhcp->tries = 0; + dhcp_reboot(); + break; + case dhcp::State::STATE_OFF: + break; + default: + dhcp->tries = 0; + dhcp_discover(); + break; + } +} + +void dhcp_process(const dhcp::Message *const pResponse, const uint32_t nSize) { + DEBUG_ENTRY + + assert(pResponse != nullptr); + + uint8_t msg_type = 0; + uint8_t opt_len = 0; - udp_send(static_cast(nHandle), reinterpret_cast(&s_dhcp_message), static_cast(k + sizeof(dhcp::Message) - DHCP_OPT_SIZE), IP_BROADCAST, DHCP_PORT_SERVER); - udp_end(DHCP_PORT_CLIENT); + auto *dhcp = reinterpret_cast(globals::netif_default.dhcp); + assert(dhcp != nullptr); + + memset(&dhcp->offered, 0, sizeof(struct dhcp::Dhcp::Offered)); + + dhcp->server_ip_addr.addr = 0; + + const auto *p = reinterpret_cast(pResponse); + p = p + sizeof(dhcp::Message) - dhcp::OPT_SIZE + 4; + auto *e = p + nSize; + + while (p < e) { + switch (*p) { + case dhcp::Options::OPTION_END: + p = e; + break; + case dhcp::Options::OPTION_PAD_OPTION: + p++; + break; + case dhcp::Options::OPTION_MESSAGE_TYPE: + p++; + p++; + msg_type = *p++; + break; + case dhcp::Options::OPTION_SUBNET_MASK: + p++; + p++; + dhcp->offered.offered_sn_mask.addr = net::memcpy_ip(p); + p = p + 4; + break; + case dhcp::Options::OPTION_ROUTER: + p++; + p++; + dhcp->offered.offered_gw_addr.addr = net::memcpy_ip(p); + p = p + 4; + break; + case dhcp::Options::OPTION_SERVER_IDENTIFIER: + p++; + p++; + dhcp->server_ip_addr.addr = net::memcpy_ip(p); + p += 4; + break; + case dhcp::Options::OPTION_LEASE_TIME: + p++; + p++; + dhcp->offered.offered_t0_lease = __builtin_bswap32(net::memcpy_ip(p)); + p += 4; + break; + case dhcp::Options::OPTION_DHCP_T1_VALUE: + p++; + p++; + dhcp->offered.offered_t1_renew = __builtin_bswap32(net::memcpy_ip(p)); + p += 4; + break; + case dhcp::Options::OPTION_DHCP_T2_VALUE: + p++; + p++; + dhcp->offered.offered_t2_rebind = __builtin_bswap32(net::memcpy_ip(p)); + p += 4; + break; + default: + p++; + opt_len = *p++; + p += opt_len; + break; + } + } + + if (msg_type == dhcp::Type::OFFER) { + dhcp->offered.offered_ip_addr.addr = net::memcpy_ip(pResponse->yiaddr); + } + + DEBUG_PRINTF("msg_type=%u", msg_type); + + if (msg_type == dhcp::Type::ACK) { + /* in requesting state or just reconnected to the network? */ + if ((dhcp->state == dhcp::State::STATE_REQUESTING) || + (dhcp->state == dhcp::State::STATE_REBOOTING)) { + dhcp_handle_ack(pResponse); +#if defined (CONFIG_NET_DHCP_USE_ACD) + dhcp_check(); +#else + dhcp_bind(); +#endif + } + else if ((dhcp->state == dhcp::State::STATE_REBINDING) || + (dhcp->state == dhcp::State::STATE_RENEWING)) { + dhcp_handle_ack(pResponse); + dhcp_bind(); + } + } + else if ((msg_type == dhcp::Type::NAK) && + ((dhcp->state == dhcp::State::STATE_REBOOTING) || (dhcp->state == dhcp::State::STATE_REQUESTING) || + (dhcp->state == dhcp::State::STATE_REBINDING) || (dhcp->state == dhcp::State::STATE_RENEWING ))) { + dhcp_handle_nak(); + } + else if ((msg_type == dhcp::Type::OFFER) && (dhcp->state == dhcp::State::STATE_SELECTING)) { + dhcp_handle_offer(pResponse); + } DEBUG_EXIT } +} // namespace net diff --git a/lib-network/src/net/icmp.cpp b/lib-network/src/net/icmp.cpp index d6d5345aa..51d8b2355 100755 --- a/lib-network/src/net/icmp.cpp +++ b/lib-network/src/net/icmp.cpp @@ -2,7 +2,7 @@ * @file icmp.cpp * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,43 +23,46 @@ * THE SOFTWARE. */ -#pragma GCC push_options -#pragma GCC optimize ("O2") -#pragma GCC optimize ("no-tree-loop-distribute-patterns") +#if defined (DEBUG_NET_ICMP) +# undef NDEBUG +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif #include #include -#include "net.h" +#include "../../config/net_config.h" + #include "net_memcpy.h" #include "net_private.h" -#include "../../config/net_config.h" +#include "net/protocol/icmp.h" -namespace net { -namespace globals { -extern struct IpInfo ipInfo; -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net +#include "debug.h" +namespace net { __attribute__((hot)) void icmp_handle(struct t_icmp *p_icmp) { if (p_icmp->icmp.type == ICMP_TYPE_ECHO) { if (p_icmp->icmp.code == ICMP_CODE_ECHO) { // Ethernet - memcpy(p_icmp->ether.dst, p_icmp->ether.src, ETH_ADDR_LEN); - memcpy(p_icmp->ether.src, net::globals::macAddress, ETH_ADDR_LEN); + std::memcpy(p_icmp->ether.dst, p_icmp->ether.src, ETH_ADDR_LEN); + std::memcpy(p_icmp->ether.src, globals::netif_default.hwaddr, ETH_ADDR_LEN); // IPv4 p_icmp->ip4.id = static_cast(~p_icmp->ip4.id); const auto nIpDestination = net::memcpy_ip(p_icmp->ip4.dst); - memcpy(p_icmp->ip4.dst, p_icmp->ip4.src, IPv4_ADDR_LEN); + std::memcpy(p_icmp->ip4.dst, p_icmp->ip4.src, IPv4_ADDR_LEN); - if (nIpDestination == net::globals::ipInfo.secondary_ip.addr) { - net::memcpy_ip(p_icmp->ip4.src, net::globals::ipInfo.secondary_ip.addr); + if (nIpDestination == globals::netif_default.secondary_ip.addr) { + net::memcpy_ip(p_icmp->ip4.src, globals::netif_default.secondary_ip.addr); } else { - net::memcpy_ip(p_icmp->ip4.src, net::globals::ipInfo.ip.addr); + net::memcpy_ip(p_icmp->ip4.src, globals::netif_default.ip.addr); } p_icmp->ip4.chksum = 0; @@ -72,7 +75,8 @@ __attribute__((hot)) void icmp_handle(struct t_icmp *p_icmp) { #if !defined (CHECKSUM_BY_HARDWARE) p_icmp->icmp.checksum = net_chksum(reinterpret_cast(&p_icmp->ip4), static_cast(__builtin_bswap16(p_icmp->ip4.len))); #endif - emac_eth_send(reinterpret_cast(p_icmp), (sizeof(struct ether_header) + __builtin_bswap16(p_icmp->ip4.len))); + emac_eth_send(reinterpret_cast(p_icmp), static_cast(sizeof(struct ether_header) + __builtin_bswap16(p_icmp->ip4.len))); } } } +} // namespace net diff --git a/lib-network/src/net/igmp.cpp b/lib-network/src/net/igmp.cpp index f45af97cb..35456eec4 100644 --- a/lib-network/src/net/igmp.cpp +++ b/lib-network/src/net/igmp.cpp @@ -2,7 +2,7 @@ * @file igmp.cpp * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,25 +23,44 @@ * THE SOFTWARE. */ -#pragma GCC push_options -#pragma GCC optimize ("O2") -#pragma GCC optimize ("no-tree-loop-distribute-patterns") +#if defined (DEBUG_NET_IGMP) +# undef NDEBUG +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif #include -#include +#include #include +#include + +#include "../../config/net_config.h" #include "net.h" +#include "netif.h" +#include "net/igmp.h" +#include "net/protocol/igmp.h" + #include "net_memcpy.h" #include "net_private.h" -#include "../../config/net_config.h" +#include "hardware.h" + +#include "debug.h" /* * https://www.rfc-editor.org/rfc/rfc2236.html * Internet Group Management Protocol, Version 2 */ +namespace net { +#define IGMP_TMR_INTERVAL 100 /* Milliseconds */ +#define IGMP_JOIN_DELAYING_MEMBER_TMR (500 /IGMP_TMR_INTERVAL) + enum State { NON_MEMBER, DELAYING_MEMBER, IDLE_MEMBER }; @@ -62,19 +81,68 @@ static struct t_igmp s_leave SECTION_NETWORK ALIGNED; static uint8_t s_multicast_mac[ETH_ADDR_LEN] SECTION_NETWORK ALIGNED; static struct t_group_info s_groups[IGMP_MAX_JOINS_ALLOWED] SECTION_NETWORK ALIGNED; static uint16_t s_id SECTION_NETWORK ALIGNED; +static int32_t nTimerId; -namespace net { -namespace globals { -extern struct IpInfo ipInfo; -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net +void igmp_set_ip() { + net::memcpy_ip(s_report.ip4.src, net::globals::netif_default.ip.addr); + net::memcpy_ip(s_leave.ip4.src, net::globals::netif_default.ip.addr); +} -static void _send_report(uint32_t nGroupAddress); +static void igmp_send_report(const uint32_t nGroupAddress) { + DEBUG_ENTRY + _pcast32 multicast_ip; -void igmp_set_ip() { - net::memcpy_ip(s_report.ip4.src, net::globals::ipInfo.ip.addr); - net::memcpy_ip(s_leave.ip4.src, net::globals::ipInfo.ip.addr); + multicast_ip.u32 = nGroupAddress; + + s_multicast_mac[3] = multicast_ip.u8[1] & 0x7F; + s_multicast_mac[4] = multicast_ip.u8[2]; + s_multicast_mac[5] = multicast_ip.u8[3]; + + DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(nGroupAddress),MAC2STR(s_multicast_mac)); + + // Ethernet + std::memcpy(s_report.ether.dst, s_multicast_mac, ETH_ADDR_LEN); + // IPv4 + s_report.ip4.id = s_id; + std::memcpy(s_report.ip4.dst, multicast_ip.u8, IPv4_ADDR_LEN); + s_report.ip4.chksum = 0; + s_report.ip4.chksum = net_chksum(reinterpret_cast(&s_report.ip4), 24); //TODO + // IGMP + std::memcpy(s_report.igmp.report.igmp.group_address, multicast_ip.u8, IPv4_ADDR_LEN); + s_report.igmp.report.igmp.checksum = 0; + s_report.igmp.report.igmp.checksum = net_chksum(reinterpret_cast(&s_report.ip4), IPv4_IGMP_REPORT_HEADERS_SIZE); + + emac_eth_send(reinterpret_cast(&s_report), IGMP_REPORT_PACKET_SIZE); + + s_id++; + + DEBUG_EXIT +} + +static void igmp_start_timer(struct t_group_info &group, const uint32_t max_time) { + group.nTimer = (max_time > 2 ? (random() % max_time) : 1); + + if (group.nTimer == 0) { + group.nTimer = 1; + } +} + +static void igmp_timeout(struct t_group_info &group) { + if ((group.state == DELAYING_MEMBER) && (group.nGroupAddress != 0x010000e0)) { //FIXME all-systems + group.state = IDLE_MEMBER; + igmp_send_report(group.nGroupAddress); + } +} + +static void igmp_timer() { + for (auto &group : s_groups) { + if (group.nTimer > 0) { + group.nTimer--; + if (group.nTimer == 0) { + igmp_timeout(group); + } + } + } } void __attribute__((cold)) igmp_init() { @@ -85,7 +153,7 @@ void __attribute__((cold)) igmp_init() { s_multicast_mac[2] = 0x5E; // Ethernet - memcpy(s_report.ether.src, net::globals::macAddress, ETH_ADDR_LEN); + std::memcpy(s_report.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); s_report.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); // IPv4 @@ -109,7 +177,7 @@ void __attribute__((cold)) igmp_init() { s_leave.ether.dst[3] = 0x00; s_leave.ether.dst[4] = 0x00; s_leave.ether.dst[5] = 0x02; - memcpy(s_leave.ether.src, net::globals::macAddress, ETH_ADDR_LEN); + std::memcpy(s_leave.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); s_leave.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); // IPv4 @@ -130,14 +198,8 @@ void __attribute__((cold)) igmp_init() { s_leave.igmp.report.igmp.type = IGMP_TYPE_LEAVE; s_leave.igmp.report.igmp.max_resp_time = 0; - /* - * https://tldp.org/HOWTO/Multicast-HOWTO-2.html - * 224.0.0.1 is the all-hosts group. If you ping that group, - * all multicast capable hosts on the network should answer, - * as every multicast capable host must join that group - * at start-up on all it's multicast capable interfaces. - */ - _send_report(0x010000e0); + nTimerId = Hardware::Get()->SoftwareTimerAdd(IGMP_TMR_INTERVAL, igmp_timer); + assert(nTimerId >= 0); } void __attribute__((cold)) igmp_shutdown() { @@ -154,38 +216,7 @@ void __attribute__((cold)) igmp_shutdown() { DEBUG_EXIT } -static void _send_report(const uint32_t nGroupAddress) { - DEBUG_ENTRY - _pcast32 multicast_ip; - - multicast_ip.u32 = nGroupAddress; - - s_multicast_mac[3] = multicast_ip.u8[1] & 0x7F; - s_multicast_mac[4] = multicast_ip.u8[2]; - s_multicast_mac[5] = multicast_ip.u8[3]; - - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(nGroupAddress),MAC2STR(s_multicast_mac)); - - // Ethernet - memcpy(s_report.ether.dst, s_multicast_mac, ETH_ADDR_LEN); - // IPv4 - s_report.ip4.id = s_id; - memcpy(s_report.ip4.dst, multicast_ip.u8, IPv4_ADDR_LEN); - s_report.ip4.chksum = 0; - s_report.ip4.chksum = net_chksum(reinterpret_cast(&s_report.ip4), 24); //TODO - // IGMP - memcpy(s_report.igmp.report.igmp.group_address, multicast_ip.u8, IPv4_ADDR_LEN); - s_report.igmp.report.igmp.checksum = 0; - s_report.igmp.report.igmp.checksum = net_chksum(reinterpret_cast(&s_report.ip4), IPv4_IGMP_REPORT_HEADERS_SIZE); - - emac_eth_send(reinterpret_cast(&s_report), IGMP_REPORT_PACKET_SIZE); - - s_id++; - - DEBUG_EXIT -} - -static void _send_leave(const uint32_t nGroupAddress) { +static void igmp_send_leave(const uint32_t nGroupAddress) { DEBUG_ENTRY DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(nGroupAddress), MAC2STR(s_multicast_mac)); @@ -248,16 +279,11 @@ __attribute__((hot)) void igmp_handle(struct t_igmp *p_igmp) { DEBUG_EXIT } -void igmp_timer() { - for (auto& group : s_groups) { - if ((group.state == DELAYING_MEMBER) && (group.nTimer > 0)) { - group.nTimer--; - - if (group.nTimer == 0) { - _send_report(group.nGroupAddress); - group.state = IDLE_MEMBER; - } - } +static void igmp_delaying_member(struct t_group_info &group, const uint32_t maxresp) { + if ((group.state == IDLE_MEMBER) + || ((group.state == DELAYING_MEMBER) && ((group.nTimer == 0) || (maxresp < group.nTimer)))) { + igmp_start_timer(group, maxresp); + group.state = DELAYING_MEMBER; } } @@ -283,7 +309,7 @@ void igmp_join(uint32_t nGroupAddress) { s_groups[i].state = DELAYING_MEMBER; s_groups[i].nTimer = 2; // TODO - _send_report(nGroupAddress); + igmp_send_report(nGroupAddress); DEBUG_EXIT return; @@ -303,7 +329,7 @@ void igmp_leave(uint32_t nGroupAddress) { for (auto& group : s_groups) { if (group.nGroupAddress == nGroupAddress) { - _send_leave(group.nGroupAddress); + igmp_send_leave(group.nGroupAddress); group.nGroupAddress = 0; group.state = NON_MEMBER; @@ -321,4 +347,10 @@ void igmp_leave(uint32_t nGroupAddress) { DEBUG_EXIT } +void igmp_report_groups() { + for (auto& group : s_groups) { + igmp_delaying_member(group, IGMP_JOIN_DELAYING_MEMBER_TMR); + } +} +} // namespace net // <--- diff --git a/lib-network/src/net/ip.cpp b/lib-network/src/net/ip.cpp index 40c735ce3..b2f3c6bf2 100644 --- a/lib-network/src/net/ip.cpp +++ b/lib-network/src/net/ip.cpp @@ -2,7 +2,7 @@ * @file ip.cpp * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,17 +23,26 @@ * THE SOFTWARE. */ -#pragma GCC push_options -#pragma GCC optimize ("O2") -#pragma GCC optimize ("no-tree-loop-distribute-patterns") +#if defined (DEBUG_NET_IP) +# undef NDEBUG +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif #include +#include "../../config/net_config.h" + #include "net.h" #include "net_private.h" -#include "../../config/net_config.h" +#include "debug.h" +namespace net { void ip_set_ip() { udp_set_ip(); igmp_set_ip(); @@ -51,17 +60,6 @@ void __attribute__((cold)) ip_init() { DEBUG_EXIT } -void __attribute__((cold)) ip_shutdown() { - DEBUG_ENTRY - -#if defined (ENABLE_HTTPD) - tcp_shutdown(); -#endif - igmp_shutdown(); - - DEBUG_EXIT -} - __attribute__((hot)) void ip_handle(struct t_ip4 *p_ip4) { if (__builtin_expect((p_ip4->ip4.ver_ihl != 0x45), 0)) { if (p_ip4->ip4.proto == IPv4_PROTO_IGMP) { @@ -93,3 +91,4 @@ __attribute__((hot)) void ip_handle(struct t_ip4 *p_ip4) { break; } } +} // namespace net diff --git a/lib-network/src/net/net.cpp b/lib-network/src/net/net.cpp index 23c9562be..ae8402e2f 100755 --- a/lib-network/src/net/net.cpp +++ b/lib-network/src/net/net.cpp @@ -23,196 +23,141 @@ * THE SOFTWARE. */ -#pragma GCC push_options -#pragma GCC optimize ("O2") -#pragma GCC optimize ("no-tree-loop-distribute-patterns") +#if defined (DEBUG_NET_NET) +# if defined (NDEBUG) +# undef NDEBUG +# endif +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif #include #include +#include "../../config/net_config.h" + #include "net.h" #include "net_private.h" -#include "net_packets.h" -#include "net_debug.h" -#include "../../config/net_config.h" +#include "netif.h" +#include "net/acd.h" +#include "net/dhcp.h" + +#include "debug.h" + +static struct net::acd::Acd s_acd; + +namespace network { +__attribute__((weak)) void mdns_shutdown() {} +} // namespace network namespace net { namespace globals { -struct IpInfo ipInfo ALIGNED; uint32_t nBroadcastMask; uint32_t nOnNetworkMask; -uint8_t macAddress[ETH_ADDR_LEN] ALIGNED; } // namespace globals #if defined (CONFIG_ENET_ENABLE_PTP) void ptp_init(); void ptp_handle(const uint8_t *, const uint32_t); #endif -} // namespace net - -static uint8_t *s_p; -static bool s_isDhcp; - -static void refresh_and_init(struct IpInfo *pIpInfo, const bool doInit) { - net::globals::ipInfo.broadcast_ip.addr = net::globals::ipInfo.ip.addr | ~net::globals::ipInfo.netmask.addr; - - net::globals::nBroadcastMask = ~(net::globals::ipInfo.netmask.addr); - net::globals::nOnNetworkMask = net::globals::ipInfo.ip.addr & net::globals::ipInfo.netmask.addr; - - if (doInit) { - arp_init(); - ip_set_ip(); - } - - const auto *pSrc = reinterpret_cast(&net::globals::ipInfo); - auto *pDst = reinterpret_cast(pIpInfo); - - memcpy(pDst, pSrc, sizeof(struct IpInfo)); -} -void set_secondary_ip() { - net::globals::ipInfo.ip.addr = net::globals::ipInfo.secondary_ip.addr; - net::globals::ipInfo.netmask.addr = 255; - net::globals::ipInfo.gw.addr = net::globals::ipInfo.ip.addr; -} - -void __attribute__((cold)) net_init(const uint8_t *const pMacAddress, struct IpInfo *pIpInfo, const char *pHostname, bool *bUseDhcp, bool *isZeroconfUsed) { +void net_shutdown() { DEBUG_ENTRY - memcpy(net::globals::macAddress, pMacAddress, ETH_ADDR_LEN); - - const auto *pSrc = reinterpret_cast(pIpInfo); - auto *pDst = reinterpret_cast(&net::globals::ipInfo); - - memcpy(pDst, pSrc, sizeof(struct IpInfo)); - - net::globals::ipInfo.secondary_ip.addr = 2 - + ((static_cast(net::globals::macAddress[3])) << 8) - + ((static_cast(net::globals::macAddress[4])) << 16) - + ((static_cast(net::globals::macAddress[5])) << 24); - - - if (net::globals::ipInfo.ip.addr == 0) { - set_secondary_ip(); - } - /* - * The macAddress is set - */ - ip_init(); - - *isZeroconfUsed = false; - - if (*bUseDhcp) { - if (dhcp_client(pHostname) < 0) { - *bUseDhcp = false; - DEBUG_PUTS("DHCP Client failed"); - *isZeroconfUsed = rfc3927(); - } - } - - refresh_and_init(pIpInfo, true); - - s_isDhcp = *bUseDhcp; - - if (!arp_do_probe()) { - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); - arp_send_announcement(); - } else { - console_error("IP Conflict!\n"); - } - -#if defined (CONFIG_ENET_ENABLE_PTP) - net::ptp_init(); -#endif + net::netif_set_link_down(); DEBUG_EXIT } -void __attribute__((cold)) net_shutdown() { - ip_shutdown(); +static void primary_ip_conflict_callback(net::acd::Callback callback) { + auto &netif = net::globals::netif_default; - if (s_isDhcp) { - dhcp_client_release(); + switch (callback) { + case net::acd::Callback::ACD_IP_OK: + if (s_acd.ipaddr.addr == netif.secondary_ip.addr) { + net_set_secondary_ip(); + } else { + net::netif_set_ipaddr(s_acd.ipaddr); + } + dhcp_inform(); + netif_set_flags(netif::NETIF_FLAG_STATICIP_OK); + break; + case net::acd::Callback::ACD_RESTART_CLIENT: + break; + case net::acd::Callback::ACD_DECLINE: + netif_clear_flags(netif::NETIF_FLAG_STATICIP_OK); + break; + default: + break; } } -void net_set_ip(struct IpInfo *pIpInfo) { - net::globals::ipInfo.ip.addr = pIpInfo->ip.addr; +void net_set_primary_ip(const ip4_addr_t ipaddr) { + auto &netif = net::globals::netif_default; - if (net::globals::ipInfo.ip.addr == 0) { - set_secondary_ip(); - } + net::dhcp_release_and_stop(); - refresh_and_init(pIpInfo, true); + acd_add(&s_acd, primary_ip_conflict_callback); - if (!arp_do_probe()) { - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); - arp_send_announcement(); + if (ipaddr.addr == 0) { + acd_start(&s_acd, netif.secondary_ip); } else { - console_error("IP Conflict!\n"); + acd_start(&s_acd, ipaddr); } } -void net_set_netmask(struct IpInfo *pIpInfo) { - net::globals::ipInfo.netmask.addr = pIpInfo->netmask.addr; - - refresh_and_init(pIpInfo, false); -} - -void net_set_gw(struct IpInfo *pIpInfo) { - net::globals::ipInfo.gw.addr = pIpInfo->gw.addr; - - ip_set_ip(); +void net_set_secondary_ip() { + auto &netif = net::globals::netif_default; + ip4_addr_t netmask; + netmask.addr = 255; + net::netif_set_addr(netif.secondary_ip, netmask, netif.secondary_ip); } -bool net_set_dhcp(struct IpInfo *pIpInfo, const char *const pHostname, bool *isZeroconfUsed) { - auto isDhcp = false; - *isZeroconfUsed = false; - - if (dhcp_client(pHostname) < 0) { - DEBUG_PUTS("DHCP Client failed"); - *isZeroconfUsed = rfc3927(); - } else { - isDhcp = true; - } +void __attribute__((cold)) net_init(const net::Link link, ip4_addr_t ipaddr, ip4_addr_t netmask, ip4_addr_t gw, bool &bUseDhcp) { + DEBUG_ENTRY + globals::netif_default.secondary_ip.addr = 2 + + ((static_cast(globals::netif_default.hwaddr[3])) << 8) + + ((static_cast(globals::netif_default.hwaddr[4])) << 16) + + ((static_cast(globals::netif_default.hwaddr[5])) << 24); - refresh_and_init(pIpInfo, true); + net::arp_init(); + ip_init(); - s_isDhcp = isDhcp; + if (net::Link::STATE_UP == link) { + net::netif_set_flags(net::netif::NETIF_FLAG_LINK_UP); - if (!arp_do_probe()) { - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); - arp_send_announcement(); + if (bUseDhcp) { + dhcp_start(); + } else { +// if (ipaddr.addr == 0) { +// net_set_secondary_ip(); +// } else { +// net::netif_set_addr(ipaddr, netmask, gw); +// } +// dhcp_inform(); + if (ipaddr.addr != 0) { + net::netif_set_netmask(netmask); + net::netif_set_gw(gw); + } + net_set_primary_ip(ipaddr); + } } else { - console_error("IP Conflict!\n"); - return false; + net::netif_clear_flags(net::netif::NETIF_FLAG_LINK_UP); } - return isDhcp; -} - -void net_dhcp_release() { - dhcp_client_release(); - s_isDhcp = false; -} - -bool net_set_zeroconf(struct IpInfo *pIpInfo) { - if (rfc3927()) { - refresh_and_init(pIpInfo, true); - - s_isDhcp = false; - - DEBUG_PRINTF(IPSTR " " MACSTR, IP2STR(net::globals::ipInfo.ip.addr), MAC2STR(net::globals::macAddress)); - arp_send_announcement(); - - return true; - } +#if defined (CONFIG_ENET_ENABLE_PTP) + net::ptp_init(); +#endif - DEBUG_PUTS("Zeroconf failed"); - return false; + DEBUG_EXIT } __attribute__((hot)) void net_handle() { + uint8_t *s_p; const auto nLength = emac_eth_recv(&s_p); if (__builtin_expect((nLength > 0), 0)) { @@ -223,16 +168,15 @@ __attribute__((hot)) void net_handle() { net::ptp_handle(const_cast(s_p), nLength); } else #endif - if (eth->type == __builtin_bswap16(ETHER_TYPE_IPv4)) { - ip_handle(reinterpret_cast(s_p)); - } else if (eth->type == __builtin_bswap16(ETHER_TYPE_ARP)) { - arp_handle(reinterpret_cast(s_p)); - } else { - DEBUG_PRINTF("type %04x is not implemented", __builtin_bswap16(eth->type)); - } + if (eth->type == __builtin_bswap16(ETHER_TYPE_IPv4)) { + ip_handle(reinterpret_cast(s_p)); + } else if (eth->type == __builtin_bswap16(ETHER_TYPE_ARP)) { + net::arp_handle(reinterpret_cast(s_p)); + } else { + DEBUG_PRINTF("type %04x is not implemented", __builtin_bswap16(eth->type)); + } emac_free_pkt(); } - - net_timers_run(); } +} // namespace net diff --git a/lib-network/src/net/net_chksum.cpp b/lib-network/src/net/net_chksum.cpp index c59592da5..408ebaa7c 100644 --- a/lib-network/src/net/net_chksum.cpp +++ b/lib-network/src/net/net_chksum.cpp @@ -2,7 +2,7 @@ * @file net_chksum.cpp * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,8 +29,7 @@ #include -#include "net_private.h" - +namespace net { uint16_t net_chksum(const void *data, uint32_t len) { auto *ptr = reinterpret_cast(data); uint32_t sum = 0; @@ -53,3 +52,4 @@ uint16_t net_chksum(const void *data, uint32_t len) { return static_cast(~sum); } +} // namespace net diff --git a/lib-network/src/net/net_memcpy.h b/lib-network/src/net/net_memcpy.h index 5943293d9..ca4f1d55c 100644 --- a/lib-network/src/net/net_memcpy.h +++ b/lib-network/src/net/net_memcpy.h @@ -2,7 +2,7 @@ * @file net_memcpy.h * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,7 +27,7 @@ #include #include -#include "net_packets.h" +#include "net/protocol/ip4.h" namespace net { inline void* memcpy(void *__restrict__ dest, void const *__restrict__ src, size_t n) { diff --git a/lib-network/src/net/net_packets.h b/lib-network/src/net/net_packets.h deleted file mode 100644 index 43b441ae4..000000000 --- a/lib-network/src/net/net_packets.h +++ /dev/null @@ -1,227 +0,0 @@ -/** - * @file net_packets.h - * - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef NET_PACKETS_H_ -#define NET_PACKETS_H_ - -#include - -#if !defined (PACKED) -# define PACKED __attribute__((packed)) -#endif - -enum MTU { - MTU_SIZE = 1500 -}; - -enum ETHER_TYPE { - ETHER_TYPE_IPv4 = 0x0800, - ETHER_TYPE_ARP = 0x0806, - ETHER_TYPE_PTP = 0x88F7 /* IEEE1588v2 (PTPv2) over Ethernet */ -}; - -enum ETH_ADDR { - ETH_ADDR_LEN = 6 -}; - -enum IPv4_ADDR { - IPv4_ADDR_LEN = 4 -}; - -enum IPv4_PROTO { - IPv4_PROTO_ICMP = 1, - IPv4_PROTO_IGMP = 2, - IPv4_PROTO_TCP = 6, - IPv4_PROTO_UDP = 17 -}; - -enum IPv4_FLAG { - IPv4_FLAG_LF = 0x0000, - IPv4_FLAG_MF = 0x2000, - IPv4_FLAG_DF = 0x4000 -}; - -#define IPv4_BROADCAST 0xffffffff - -enum ARP_HARDWARE_TYPE { - ARP_HWTYPE_ETHERNET = 1 -}; - -enum ARP_PROTOCOL_TYPE { - ARP_PRTYPE_IPv4 = ETHER_TYPE_IPv4 -}; - -enum ARP_HARDWARE { - ARP_HARDWARE_SIZE = ETH_ADDR_LEN -}; - -enum ARP_PROTOCOL { - ARP_PROTOCOL_SIZE = IPv4_ADDR_LEN -}; - -enum ARP_OPCODE { - ARP_OPCODE_RQST = 1, - ARP_OPCODE_REPLY = 2 -}; - -enum IGMP_TYPE { - IGMP_TYPE_QUERY = 0x11, - IGMP_TYPE_REPORT = 0x16, - IGMP_TYPE_LEAVE = 0x17 -}; - -enum ICMP_TYPE { - ICMP_TYPE_ECHO_REPLY = 0, - ICMP_TYPE_ECHO = 8 -}; - -enum ICMP_CODE { - ICMP_CODE_ECHO = 0 -}; - -struct ether_header { - uint8_t dst[ETH_ADDR_LEN]; /* 6 */ - uint8_t src[ETH_ADDR_LEN]; /* 12 */ - uint16_t type; /* 14 */ -} PACKED; - -struct arp_packet { - uint16_t hardware_type; /* 2 */ - uint16_t protocol_type; /* 4 */ - uint8_t hardware_size; /* 5 */ - uint8_t protocol_size; /* 6 */ - uint16_t opcode; /* 8 */ - uint8_t sender_mac[ETH_ADDR_LEN];/*14 */ - uint8_t sender_ip[IPv4_ADDR_LEN];/* 18 */ - uint8_t target_mac[ETH_ADDR_LEN];/*24 */ - uint8_t target_ip[IPv4_ADDR_LEN];/* 28 */ - uint8_t padding[18]; /* 46 */ /* +14 = 60 */ -} PACKED; - -struct ip4_header { - uint8_t ver_ihl; /* 1 */ - uint8_t tos; /* 2 */ - uint16_t len; /* 4 */ - uint16_t id; /* 6 */ - uint16_t flags_froff; /* 8 */ - uint8_t ttl; /* 9 */ - uint8_t proto; /* 10 */ - uint16_t chksum; /* 12 */ - uint8_t src[IPv4_ADDR_LEN]; /* 16 */ - uint8_t dst[IPv4_ADDR_LEN]; /* 20 */ -} PACKED; - -struct t_igmp_packet { - uint8_t type; - uint8_t max_resp_time; - uint16_t checksum; - uint8_t group_address[IPv4_ADDR_LEN]; -} PACKED; - -struct t_icmp_packet { - uint8_t type; /* 1 */ - uint8_t code; /* 2 */ - uint16_t checksum; /* 4 */ - uint8_t parameter[4]; /* 8 */ -#define ICMP_HEADER_SIZE 8 -#define ICMP_PAYLOAD_SIZE (MTU_SIZE - ICMP_HEADER_SIZE - sizeof(struct ip4_header)) - uint8_t payload[ICMP_PAYLOAD_SIZE]; -} PACKED; - -struct t_udp_packet { - uint16_t source_port; /* 2 */ - uint16_t destination_port; /* 4 */ - uint16_t len; /* 6 */ - uint16_t checksum; /* 8 */ -#define UDP_HEADER_SIZE 8 -#define UDP_DATA_SIZE (MTU_SIZE - UDP_HEADER_SIZE - sizeof(struct ip4_header)) - uint8_t data[UDP_DATA_SIZE]; -}PACKED; - -struct t_tcp_packet { - uint16_t srcpt; /* 2 */ - uint16_t dstpt; /* 4 */ - uint32_t seqnum; /* 8 */ - uint32_t acknum; /* 12 */ - uint8_t offset; /* 13 */ - uint8_t control; /* 14 */ - uint16_t window; /* 16 */ - uint16_t checksum; /* 18 */ - uint16_t urgent; /* 20 */ -#define TCP_HEADER_SIZE 20 -#define TCP_OPTIONS_SIZE 40 /* Assuming maximum TCP options size is 40 bytes */ -#define TCP_DATA_SIZE (MTU_SIZE - TCP_HEADER_SIZE - sizeof(struct ip4_header) - TCP_OPTIONS_SIZE) - uint8_t data[MTU_SIZE - TCP_HEADER_SIZE - sizeof(struct ip4_header)]; -} PACKED; - -struct t_arp { - struct ether_header ether; - struct arp_packet arp; -} PACKED; - -struct t_ip4 { - struct ether_header ether; - struct ip4_header ip4; -} PACKED; - -struct t_igmp { - struct ether_header ether; - struct ip4_header ip4; - union { - struct { - uint32_t ip4_options; - struct t_igmp_packet igmp; - } report; - struct t_igmp_packet igmp; - } igmp; -} PACKED; - -struct t_icmp { - struct ether_header ether; - struct ip4_header ip4; - struct t_icmp_packet icmp; -} PACKED; - -struct t_udp { - struct ether_header ether; - struct ip4_header ip4; - struct t_udp_packet udp; -} PACKED; - -struct t_tcp { - struct ether_header ether; - struct ip4_header ip4; - struct t_tcp_packet tcp; -} PACKED; - -#define IPv4_UDP_HEADERS_SIZE (sizeof(struct ip4_header) + UDP_HEADER_SIZE) /* IP | UDP */ -#define UDP_PACKET_HEADERS_SIZE (sizeof(struct ether_header) + IPv4_UDP_HEADERS_SIZE) /* ETH | IP | UDP */ - -#define IPv4_IGMP_REPORT_HEADERS_SIZE (sizeof(struct t_igmp) - sizeof(struct ether_header)) -#define IGMP_REPORT_PACKET_SIZE (sizeof(struct t_igmp)) - -#define IPv4_ICMP_HEADERS_SIZE (sizeof(struct t_icmp) - sizeof(struct ether_header)) - -#endif /* NET_PACKETS_H_ */ diff --git a/lib-network/src/net/net_private.h b/lib-network/src/net/net_private.h old mode 100755 new mode 100644 index 88a66c297..336c4c58d --- a/lib-network/src/net/net_private.h +++ b/lib-network/src/net/net_private.h @@ -2,7 +2,7 @@ * @file net_private.h * */ -/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,49 +28,47 @@ #include -#include "net_packets.h" #include "net_platform.h" -#include "net_debug.h" -#include "dhcp_internal.h" -#include "tftp_internal.h" -#include "ntp_internal.h" +#include "net/arp.h" +#include "net/protocol/icmp.h" +#include "net/protocol/igmp.h" +#include "net/protocol/udp.h" +#include "net/protocol/tcp.h" #ifndef ALIGNED # define ALIGNED __attribute__ ((aligned (4))) #endif -extern "C" int console_error(const char *); +namespace net::arp { +enum class EthSend { + IS_NORMAL +#if defined CONFIG_ENET_ENABLE_PTP + , IS_TIMESTAMP +#endif +}; +} // namespace net::arp + +extern "C" void console_error(const char *); -void emac_eth_send(void *, int); +void emac_eth_send(void *, uint32_t); +#if defined CONFIG_ENET_ENABLE_PTP +void emac_eth_send_timestamp(void *, uint32_t); +#endif int emac_eth_recv(uint8_t **); -void emac_free_pkt(void); +void emac_free_pkt(); +namespace net { void net_handle(); uint16_t net_chksum(const void *, uint32_t); void net_timers_run(); -void arp_init(); -void arp_handle(struct t_arp *); -bool arp_do_probe(); -void arp_cache_init(); -void arp_send_request(uint32_t); -void arp_send_probe(); -void arp_send_announcement(); -void arp_cache_update(const uint8_t *, uint32_t); -uint32_t arp_cache_lookup(uint32_t, uint8_t *); - void ip_init(); void ip_set_ip(); void ip_shutdown(); void ip_handle(struct t_ip4 *); -int dhcp_client(const char *); -void dhcp_client_release(); - -bool rfc3927(); - void udp_init(); void udp_set_ip(); void udp_handle(struct t_udp *); @@ -80,7 +78,6 @@ void igmp_init(); void igmp_set_ip(); void igmp_handle(struct t_igmp *); void igmp_shutdown(); -void igmp_timer(); void icmp_handle(struct t_icmp *); void icmp_shutdown(); @@ -89,5 +86,6 @@ void tcp_init(); void tcp_run(); void tcp_handle(struct t_tcp *); void tcp_shutdown(); +} // namespace net #endif /* NET_PRIVATE_H_ */ diff --git a/lib-network/src/net/netif.cpp b/lib-network/src/net/netif.cpp new file mode 100755 index 000000000..975b1e6f5 --- /dev/null +++ b/lib-network/src/net/netif.cpp @@ -0,0 +1,306 @@ +/** + * @file netif.cpp + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if defined (DEBUG_NET_NETIF) +# undef NDEBUG +#endif + +#include + +#include "netif.h" +#include "net/acd.h" +#include "net/autoip.h" +#include "net/dhcp.h" +#include "net/igmp.h" + +#include "debug.h" + +namespace net { +namespace globals { +struct netif netif_default; +extern uint32_t nBroadcastMask; +extern uint32_t nOnNetworkMask; +} // namespace globals + +extern void arp_init(); +extern void ip_set_ip(); + +static netif_ext_callback_fn callback_fn; + +static void default_callback([[maybe_unused]] const uint16_t reason, [[maybe_unused]] const netif_ext_callback_args_t* args) { + DEBUG_PRINTF("%u", reason); +} + +void netif_init() { + auto &netif = net::globals::netif_default; + + netif.ip.addr = 0; + netif.netmask.addr = 0; + netif.gw.addr = 0; + netif.broadcast_ip.addr = 0; + netif.secondary_ip.addr = 2 + + ((static_cast(netif.hwaddr[3])) << 8) + + ((static_cast(netif.hwaddr[4])) << 16) + + ((static_cast(netif.hwaddr[5])) << 24); + netif.flags = 0; + netif.dhcp = nullptr; + netif.acd = nullptr; + netif.autoip = nullptr; + + callback_fn = &default_callback; + + net::arp_init(); +} + +static void netif_do_update_globals() { + auto &netif = net::globals::netif_default; + netif.broadcast_ip.addr = (netif.ip.addr | ~netif.netmask.addr); + + globals::nBroadcastMask = ~(netif.netmask.addr); + globals::nOnNetworkMask =netif.ip.addr & netif.netmask.addr; + + ip_set_ip(); +} + +static void netif_do_ip_addr_changed([[maybe_unused]] const ip4_addr_t old_addr,[[maybe_unused]] const ip4_addr_t new_addr) { +// tcp_netif_ip_addr_changed(old_addr, new_addr); +// udp_netif_ip_addr_changed(old_addr, new_addr); + ip_set_ip(); +} + +static void netif_issue_reports() { + const auto &netif = net::globals::netif_default; + + if (!(netif.flags & netif::NETIF_FLAG_LINK_UP)) { + return; + } + + if (netif.ip.addr != 0) { + igmp_report_groups(); + } +} + +static bool netif_do_set_ipaddr(const ip4_addr_t ipaddr, ip4_addr_t &old_addr) { + DEBUG_ENTRY + auto &netif = net::globals::netif_default; + + DEBUG_PRINTF(IPSTR " " IPSTR, IP2STR(ipaddr.addr), IP2STR(netif.ip.addr)); + + // Update the address if it's different + if (ipaddr.addr != netif.ip.addr) { + old_addr.addr = netif.ip.addr; + + netif_do_ip_addr_changed(old_addr, ipaddr); + acd_netif_ip_addr_changed(old_addr, ipaddr); + + netif.ip.addr = ipaddr.addr; + + netif_do_update_globals(); + netif_issue_reports(); + + DEBUG_EXIT + return true; // address changed + } + + DEBUG_EXIT + return false; // address unchanged +} + +static bool netif_do_set_netmask(const ip4_addr_t netmask, ip4_addr_t &old_nm) { + DEBUG_ENTRY + auto &netif = net::globals::netif_default; + + if (netmask.addr != netif.netmask.addr) { + old_nm.addr = netif.netmask.addr; + netif.netmask.addr = netmask.addr; + + netif_do_update_globals(); + + DEBUG_EXIT + return true; // netmask changed + } + + DEBUG_EXIT + return false; // netmask unchanged +} + +static bool netif_do_set_gw(const ip4_addr_t gw, ip4_addr_t &old_gw) { + DEBUG_ENTRY + auto &netif = net::globals::netif_default; + + if (gw.addr != netif.gw.addr) { + old_gw.addr = netif.gw.addr; + netif.gw.addr = gw.addr; + + DEBUG_EXIT + return true; // gateway changed + } + + DEBUG_EXIT + return false; // gateway unchanged +} + +void netif_set_ipaddr(const ip4_addr_t ipaddr) { + ip4_addr_t old_addr; + + if (netif_do_set_ipaddr(ipaddr, old_addr)) { + netif_ext_callback_args_t args; + args.ipv4_changed.old_address.addr = old_addr.addr; + callback_fn(NetifReason::NSC_IPV4_ADDRESS_CHANGED, &args); + } +} + +void netif_set_netmask(const ip4_addr_t netmask) { + ip4_addr_t old_nm; + + if (netif_do_set_netmask(netmask, old_nm)) { + netif_ext_callback_args_t args; + args.ipv4_changed.old_netmask = old_nm; + callback_fn(NetifReason::NSC_IPV4_NETMASK_CHANGED, &args); + } +} + +void netif_set_gw(const ip4_addr_t gw) { + ip4_addr_t old_gw; + + if (netif_do_set_gw(gw, old_gw)) { + netif_ext_callback_args_t args; + args.ipv4_changed.old_gw = old_gw; + callback_fn(NetifReason::NSC_IPV4_GATEWAY_CHANGED, &args); + } +} + +void netif_set_addr(const ip4_addr_t ipaddr, const ip4_addr_t netmask, const ip4_addr_t gw) { + DEBUG_ENTRY + DEBUG_PRINTF(IPSTR " " IPSTR " " IPSTR, IP2STR(ipaddr.addr), IP2STR(netmask.addr), IP2STR(gw.addr)); + + auto change_reason = NetifReason::NSC_NONE; + netif_ext_callback_args_t cb_args; + + ip4_addr_t old_addr; + ip4_addr_t old_nm; + ip4_addr_t old_gw; + + const auto remove = (ipaddr.addr == 0); + + if (remove) { + /* when removing an address, we have to remove it *before* changing netmask/gw + to ensure that tcp RST segment can be sent correctly */ + if (netif_do_set_ipaddr(ipaddr, old_addr)) { + change_reason |= NetifReason::NSC_IPV4_ADDRESS_CHANGED; + cb_args.ipv4_changed.old_address.addr = old_addr.addr; + } + } + + if (netif_do_set_netmask(netmask, old_nm)) { + change_reason |= NetifReason::NSC_IPV4_NETMASK_CHANGED; + cb_args.ipv4_changed.old_netmask.addr = old_nm.addr; + } + + if (netif_do_set_gw(gw, old_gw)) { + change_reason |= NetifReason::NSC_IPV4_GATEWAY_CHANGED; + cb_args.ipv4_changed.old_gw = old_gw; + } + + if (!remove) { + /* set ipaddr last to ensure netmask/gw have been set when status callback is called */ + if (netif_do_set_ipaddr(ipaddr, old_addr)) { + change_reason |= NetifReason::NSC_IPV4_ADDRESS_CHANGED; + cb_args.ipv4_changed.old_address.addr = old_addr.addr; + } + } + + if (change_reason != NetifReason::NSC_NONE) { + change_reason |= NetifReason::NSC_IPV4_SETTINGS_CHANGED; + } + + if (!remove) { + /* Issue a callback even if the address hasn't changed, eg. DHCP reboot */ + change_reason |= NetifReason::NSC_IPV4_ADDR_VALID; + } + + DEBUG_PRINTF("change_reason=%u", change_reason); + + if (change_reason != NetifReason::NSC_NONE) { + callback_fn(change_reason, &cb_args); + } + + DEBUG_EXIT +} + +void netif_add_ext_callback(netif_ext_callback_fn fn) { + callback_fn = fn; +} + +/* + * Link + */ + +void netif_set_link_up() { + DEBUG_ENTRY + const auto &netif = net::globals::netif_default; + + if (!(netif.flags & netif::NETIF_FLAG_LINK_UP)) { + netif_set_flags(netif::NETIF_FLAG_LINK_UP); + + dhcp_network_changed_link_up(); + + autoip_network_changed_link_up(); + + netif_issue_reports(); + + netif_ext_callback_args_t args; + args.link_changed.state = 1; + callback_fn(NetifReason::NSC_LINK_CHANGED, &args); + + DEBUG_EXIT + return; + } + + DEBUG_EXIT +} + +void netif_set_link_down() { + DEBUG_ENTRY + const auto &netif = net::globals::netif_default; + + if (netif.flags & netif::NETIF_FLAG_LINK_UP) { + netif_clear_flags(netif::NETIF_FLAG_LINK_UP); + + autoip_network_changed_link_down(); + + acd_network_changed_link_down(); + + netif_ext_callback_args_t args; + args.link_changed.state = 0; + callback_fn(NetifReason::NSC_LINK_CHANGED, &args); + + DEBUG_EXIT + return; + } + + DEBUG_EXIT +} +} // namespace net diff --git a/lib-network/src/net/rfc3927.cpp b/lib-network/src/net/rfc3927.cpp deleted file mode 100644 index b96b7ad58..000000000 --- a/lib-network/src/net/rfc3927.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @file rfc3927.cpp - * - */ -/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#pragma GCC push_options -#pragma GCC optimize ("O2") -#pragma GCC optimize ("no-tree-loop-distribute-patterns") - -#include -#include - -#include "net.h" -#include "net_private.h" - -#include "hardware.h" - -#include "../../config/net_config.h" - -/* - * https://www.rfc-editor.org/rfc/rfc3927.html - * Dynamic Configuration of IPv4 Link-Local Addresses - */ - -static const uint32_t s_ip_begin = 0x0100FEA9; // 169.254.0.1 -static const uint32_t s_ip_end = 0xFFFEFEA9; // 169.254.254.255 - -namespace net { -namespace globals { -extern struct IpInfo ipInfo; -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net - -bool rfc3927() { - DEBUG_ENTRY - - const auto mask = net::globals::macAddress[3] + (net::globals::macAddress[4] << 8); - auto ip = s_ip_begin | static_cast(mask << 16); - - DEBUG_PRINTF("ip=" IPSTR, IP2STR(ip)); - - auto nCount = 0; - const auto nMillis = Hardware::Get()->Millis(); - - do { - DEBUG_PRINTF(IPSTR, IP2STR(ip)); - - net::globals::ipInfo.ip.addr = ip; - - if (!arp_do_probe()) { - net::globals::ipInfo.gw.addr = ip; - net::globals::ipInfo.netmask.addr = 0x0000FFFF; - - DEBUG_EXIT - return true; - } - - ip = __builtin_bswap32(__builtin_bswap32(ip) + 1); - - if (ip == s_ip_end) { - ip = s_ip_begin; - } - - nCount++; - } while ((nCount < 0xFF) && ((Hardware::Get()->Millis() - nMillis) < 500)); - - net::globals::ipInfo.ip.addr = 0; - net::globals::ipInfo.gw.addr = 0; - net::globals::ipInfo.netmask.addr = 0; - - DEBUG_EXIT - return false; -} diff --git a/lib-network/src/net/tcp.cpp b/lib-network/src/net/tcp.cpp index 1ee16cb31..9ff4a50b5 100644 --- a/lib-network/src/net/tcp.cpp +++ b/lib-network/src/net/tcp.cpp @@ -2,7 +2,7 @@ * @file tcp.cpp * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,6 +29,10 @@ * LISTEN -> ESTABLISHED -> CLOSE_WAIT -> LAST_ACK -> CLOSED:LISTEN */ +#if defined (DEBUG_NET_TCP) +# undef NDEBUG +#endif + #pragma GCC diagnostic push #if (__GNUC__ < 10) # pragma GCC diagnostic ignored "-Wconversion" @@ -43,28 +47,25 @@ #include #include +#include "../config/net_config.h" + #include "net.h" +#include "net/protocol/tcp.h" + #include "net_memcpy.h" #include "net_private.h" #include "hardware.h" -#include "../config/net_config.h" +#include "debug.h" +namespace net { #define TCP_RX_MSS (TCP_DATA_SIZE) #define TCP_RX_MAX_ENTRIES (1U << 1) // Must always be a power of 2 #define TCP_RX_MAX_ENTRIES_MASK (TCP_RX_MAX_ENTRIES - 1) #define TCP_MAX_RX_WND (TCP_RX_MAX_ENTRIES * TCP_RX_MSS); #define TCP_TX_MSS (TCP_DATA_SIZE) -namespace net { -namespace tcp { -} // namespace tcp -namespace globals { -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net - /** * Transmission control block (TCB) */ @@ -256,13 +257,13 @@ static constexpr bool SEQ_GT(const uint32_t x, const uint32_t y) { return static_cast(x - y) > 0; } -static constexpr bool SEQ_GEQ(const uint32_t x, const uint32_t y) { - return static_cast(x - y) >= 0; -} - -static constexpr bool SEQ_BETWEEN(const uint32_t l, const uint32_t x, const uint32_t h) { - return SEQ_LT(l, x) && SEQ_LT(x, h); -} +//static constexpr bool SEQ_GEQ(const uint32_t x, const uint32_t y) { +// return static_cast(x - y) >= 0; +//} +// +//static constexpr bool SEQ_BETWEEN(const uint32_t l, const uint32_t x, const uint32_t h) { +// return SEQ_LT(l, x) && SEQ_LT(x, h); +//} static constexpr bool SEQ_BETWEEN_L(const uint32_t l, const uint32_t x, const uint32_t h) { return SEQ_LEQ(l, x) && SEQ_LT(x, h); // low border inclusive @@ -325,7 +326,7 @@ __attribute__((cold)) void tcp_init() { DEBUG_ENTRY /* Ethernet */ - memcpy(s_tcp.ether.src, net::globals::macAddress, ETH_ADDR_LEN); + std::memcpy(s_tcp.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); s_tcp.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); /* IPv4 */ s_tcp.ip4.ver_ihl = 0x45; @@ -363,8 +364,8 @@ static uint16_t _chksum(struct t_tcp *pTcp, const struct tcb *pTcb, uint16_t nLe memcpy(buf, pseu, TCP_PSEUDO_LEN); // Generate TCP psuedo header - memcpy(pseu->srcIp, pTcb->localIp, IPv4_ADDR_LEN); - memcpy(pseu->dstIp, pTcb->remoteIp, IPv4_ADDR_LEN); + std::memcpy(pseu->srcIp, pTcb->localIp, IPv4_ADDR_LEN); + std::memcpy(pseu->dstIp, pTcb->remoteIp, IPv4_ADDR_LEN); pseu->zero = 0; pseu->proto = IPv4_PROTO_TCP; pseu->length = __builtin_bswap16(nLength); @@ -394,12 +395,12 @@ static void send_package(const struct tcb *pTcb, const struct SendInfo &sendInfo const auto tcplen = nHeaderLength + pTcb->TX.size; /* Ethernet */ - memcpy(s_tcp.ether.dst, pTcb->remoteEthAddr, ETH_ADDR_LEN); + std::memcpy(s_tcp.ether.dst, pTcb->remoteEthAddr, ETH_ADDR_LEN); /* IPv4 */ s_tcp.ip4.id = s_id++; s_tcp.ip4.len = __builtin_bswap16(static_cast(tcplen + sizeof(struct ip4_header))); - memcpy(s_tcp.ip4.src, pTcb->localIp, IPv4_ADDR_LEN); - memcpy(s_tcp.ip4.dst, pTcb->remoteIp, IPv4_ADDR_LEN); + std::memcpy(s_tcp.ip4.src, pTcb->localIp, IPv4_ADDR_LEN); + std::memcpy(s_tcp.ip4.dst, pTcb->remoteIp, IPv4_ADDR_LEN); s_tcp.ip4.chksum = 0; #if !defined (CHECKSUM_BY_HARDWARE) s_tcp.ip4.chksum = net_chksum(reinterpret_cast(&s_tcp.ip4), 20); @@ -644,14 +645,14 @@ __attribute__((hot)) void tcp_handle(struct t_tcp *pTcp) { if (nIndexPort == TCP_MAX_PORTS_ALLOWED) { struct tcb TCB; - memset(&TCB, 0, sizeof(struct tcb)); + std::memset(&TCB, 0, sizeof(struct tcb)); TCB.nLocalPort = pTcp->tcp.dstpt; - memcpy(TCB.localIp, pTcp->ip4.dst, IPv4_ADDR_LEN); + std::memcpy(TCB.localIp, pTcp->ip4.dst, IPv4_ADDR_LEN); TCB.nRemotePort = pTcp->tcp.srcpt; - memcpy(TCB.remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN); - memcpy(TCB.remoteEthAddr, pTcp->ether.src, ETH_ADDR_LEN); + std::memcpy(TCB.remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN); + std::memcpy(TCB.remoteEthAddr, pTcp->ether.src, ETH_ADDR_LEN); _bswap32(pTcp); @@ -698,11 +699,11 @@ __attribute__((hot)) void tcp_handle(struct t_tcp *pTcp) { // https://www.rfc-editor.org/rfc/rfc9293.html#name-listen-state if (pTCB->state == STATE_LISTEN) { - memcpy(pTCB->localIp, pTcp->ip4.dst, IPv4_ADDR_LEN); + std::memcpy(pTCB->localIp, pTcp->ip4.dst, IPv4_ADDR_LEN); pTCB->nRemotePort = pTcp->tcp.srcpt; - memcpy(pTCB->remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN); - memcpy(pTCB->remoteEthAddr, pTcp->ether.src, ETH_ADDR_LEN); + std::memcpy(pTCB->remoteIp, pTcp->ip4.src, IPv4_ADDR_LEN); + std::memcpy(pTCB->remoteEthAddr, pTcp->ether.src, ETH_ADDR_LEN); // First, check for a RST // An incoming RST should be ignored. @@ -1186,5 +1187,5 @@ void tcp_write(const int32_t nHandleListen, const uint8_t *pBuffer, uint16_t nLe nLength -= nWriteLength; } } - +} // namespace net // <--- diff --git a/lib-network/src/net/udp.cpp b/lib-network/src/net/udp.cpp index 1c5e148fd..f34f76889 100644 --- a/lib-network/src/net/udp.cpp +++ b/lib-network/src/net/udp.cpp @@ -2,7 +2,7 @@ * @file udp.cpp * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,26 +23,40 @@ * THE SOFTWARE. */ -#pragma GCC push_options -#pragma GCC optimize ("O2") -#pragma GCC optimize ("no-tree-loop-distribute-patterns") +#if defined (DEBUG_NET_UDP) +# undef NDEBUG +#endif + +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif #include #include -#include #include #include +#include "../../config/net_config.h" + +#include "net/protocol/udp.h" + #include "net.h" #include "net_private.h" #include "net_memcpy.h" -#include "../../config/net_config.h" +#include "debug.h" + +namespace net { +namespace globals { +extern uint32_t nBroadcastMask; +} // namespace globals struct data_entry { uint32_t from_ip; + uint32_t size; uint16_t from_port; - uint16_t size; uint8_t data[UDP_DATA_SIZE]; } ALIGNED; @@ -52,22 +66,8 @@ static struct t_udp s_send_packet SECTION_NETWORK ALIGNED; static uint16_t s_id SECTION_NETWORK ALIGNED; static uint8_t s_multicast_mac[ETH_ADDR_LEN] SECTION_NETWORK ALIGNED; -namespace net { -namespace globals { -extern struct IpInfo ipInfo; -extern uint32_t nBroadcastMask; -extern uint32_t nOnNetworkMask; -extern uint8_t macAddress[ETH_ADDR_LEN]; -} // namespace globals -} // namespace net - -typedef union pcast32 { - uint32_t u32; - uint8_t u8[4]; -} _pcast32; - void udp_set_ip() { - net::memcpy_ip(s_send_packet.ip4.src, net::globals::ipInfo.ip.addr); + net::memcpy_ip(s_send_packet.ip4.src, net::globals::netif_default.ip.addr); } void __attribute__((cold)) udp_init() { @@ -76,7 +76,7 @@ void __attribute__((cold)) udp_init() { s_multicast_mac[1] = 0x00; s_multicast_mac[2] = 0x5E; // Ethernet - memcpy(s_send_packet.ether.src, net::globals::macAddress, ETH_ADDR_LEN); + std::memcpy(s_send_packet.ether.src, net::globals::netif_default.hwaddr, ETH_ADDR_LEN); s_send_packet.ether.type = __builtin_bswap16(ETHER_TYPE_IPv4); // IPv4 s_send_packet.ip4.ver_ihl = 0x45; @@ -118,7 +118,76 @@ __attribute__((hot)) void udp_handle(struct t_udp *pUdp) { } } - DEBUG_PRINTF(IPSTR ":%d[%x]", pUdp->ip4.src[0],pUdp->ip4.src[1],pUdp->ip4.src[2],pUdp->ip4.src[3], nDestinationPort, nDestinationPort); + DEBUG_PRINTF(IPSTR ":%d[%x] " MACSTR, pUdp->ip4.src[0],pUdp->ip4.src[1],pUdp->ip4.src[2],pUdp->ip4.src[3], nDestinationPort, nDestinationPort, MAC2STR(pUdp->ether.dst)); +} + +template +static void udp_send_implementation(int nIndex, const uint8_t *pData, uint32_t nSize, uint32_t nRemoteIp, uint16_t nRemotePort) { + assert(nIndex >= 0); + assert(nIndex < UDP_MAX_PORTS_ALLOWED); + assert(s_Port[nIndex] != 0); + + //IPv4 + s_send_packet.ip4.id = s_id++; + s_send_packet.ip4.len = __builtin_bswap16(static_cast(nSize + IPv4_UDP_HEADERS_SIZE)); + s_send_packet.ip4.chksum = 0; + + //UDP + s_send_packet.udp.source_port = __builtin_bswap16( s_Port[nIndex]); + s_send_packet.udp.destination_port = __builtin_bswap16(nRemotePort); + s_send_packet.udp.len = __builtin_bswap16(static_cast(nSize + UDP_HEADER_SIZE)); + + nSize = std::min(static_cast(UDP_DATA_SIZE), nSize); + + net::memcpy(s_send_packet.udp.data, pData, nSize); + + if (nRemoteIp == network::IP4_BROADCAST) { + memset(s_send_packet.ether.dst, 0xFF, ETH_ADDR_LEN); + memset(s_send_packet.ip4.dst, 0xFF, IPv4_ADDR_LEN); + } else if ((nRemoteIp & net::globals::nBroadcastMask) == net::globals::nBroadcastMask) { + memset(s_send_packet.ether.dst, 0xFF, ETH_ADDR_LEN); + net::memcpy_ip(s_send_packet.ip4.dst, nRemoteIp); + } else { + if ((nRemoteIp & 0xF0) == 0xE0) { // Multicast, we know the MAC Address + typedef union pcast32 { + uint32_t u32; + uint8_t u8[4]; + } _pcast32; + _pcast32 multicast_ip; + + multicast_ip.u32 = nRemoteIp; + s_multicast_mac[3] = multicast_ip.u8[1] & 0x7F; + s_multicast_mac[4] = multicast_ip.u8[2]; + s_multicast_mac[5] = multicast_ip.u8[3]; + + std::memcpy(s_send_packet.ether.dst, s_multicast_mac, ETH_ADDR_LEN); + net::memcpy_ip(s_send_packet.ip4.dst, nRemoteIp); + } else { + if (S == net::arp::EthSend::IS_NORMAL) { + net::arp_send(&s_send_packet, nSize + UDP_PACKET_HEADERS_SIZE, nRemoteIp); + } +#if defined CONFIG_ENET_ENABLE_PTP + else if (S == net::arp::EthSend::IS_TIMESTAMP) { + net::arp_send_timestamp(&s_send_packet, nSize + UDP_PACKET_HEADERS_SIZE, nRemoteIp); + } +#endif + return; + } + } + +#if !defined (CHECKSUM_BY_HARDWARE) + s_send_packet.ip4.chksum = net_chksum(reinterpret_cast(&s_send_packet.ip4), sizeof(s_send_packet.ip4)); +#endif + + if (S == net::arp::EthSend::IS_NORMAL) { + emac_eth_send(reinterpret_cast(&s_send_packet), nSize + UDP_PACKET_HEADERS_SIZE); + } +#if defined CONFIG_ENET_ENABLE_PTP + else if (S == net::arp::EthSend::IS_TIMESTAMP) { + emac_eth_send_timestamp(reinterpret_cast(&s_send_packet), nSize); + } +#endif + return; } // --> @@ -160,7 +229,7 @@ int udp_end(uint16_t nLocalPort) { return -1; } -uint16_t udp_recv1(int nIndex, uint8_t *pData, uint16_t nSize, uint32_t *pFromIp, uint16_t *FromPort) { +uint32_t udp_recv1(int nIndex, uint8_t *pData, uint32_t nSize, uint32_t *pFromIp, uint16_t *FromPort) { assert(nIndex >= 0); assert(nIndex < UDP_MAX_PORTS_ALLOWED); @@ -181,97 +250,35 @@ uint16_t udp_recv1(int nIndex, uint8_t *pData, uint16_t nSize, uint32_t *pFromIp return i; } -uint16_t udp_recv2(int nIndex, const uint8_t **pData, uint32_t *pFromIp, uint16_t *pFromPort) { +uint32_t udp_recv2(int nIndex, const uint8_t **pData, uint32_t *pFromIp, uint16_t *pFromPort) { assert(nIndex >= 0); assert(nIndex < UDP_MAX_PORTS_ALLOWED); - if (__builtin_expect((s_data[nIndex].size == 0), 1)) { + auto &p_data = s_data[nIndex]; + + if (__builtin_expect((p_data.size == 0), 1)) { return 0; } - auto *p_data = &s_data[nIndex]; - - *pData = p_data->data; - *pFromIp = p_data->from_ip; - *pFromPort = p_data->from_port; + *pData = p_data.data; + *pFromIp = p_data.from_ip; + *pFromPort = p_data.from_port; - const auto nSize = p_data->size; + const auto nSize = p_data.size; - p_data->size = 0; + p_data.size = 0; return nSize; } -int udp_send(int nIndex, const uint8_t *pData, uint16_t nSize, uint32_t RemoteIp, uint16_t RemotePort) { - assert(nIndex >= 0); - assert(nIndex < UDP_MAX_PORTS_ALLOWED); - - if (__builtin_expect ((s_Port[nIndex] == 0), 0)) { - DEBUG_PUTS("ports_allowed[idx] == 0"); - return -1; - } - - if (RemoteIp == IPv4_BROADCAST) { - memset(s_send_packet.ether.dst, 0xFF, ETH_ADDR_LEN); - memset(s_send_packet.ip4.dst, 0xFF, IPv4_ADDR_LEN); - } else if ((RemoteIp & net::globals::nBroadcastMask) == net::globals::nBroadcastMask) { - memset(s_send_packet.ether.dst, 0xFF, ETH_ADDR_LEN); - net::memcpy_ip(s_send_packet.ip4.dst, RemoteIp); - } else { - if ((RemoteIp & 0xE0) == 0xE0) { // Multicast, we know the MAC Address - _pcast32 multicast_ip; - - multicast_ip.u32 = RemoteIp; - s_multicast_mac[3] = multicast_ip.u8[1] & 0x7F; - s_multicast_mac[4] = multicast_ip.u8[2]; - s_multicast_mac[5] = multicast_ip.u8[3]; - - memcpy(s_send_packet.ether.dst, s_multicast_mac, ETH_ADDR_LEN); - net::memcpy_ip(s_send_packet.ip4.dst, RemoteIp); - } else { - if (__builtin_expect((net::globals::nOnNetworkMask != (RemoteIp & net::globals::nOnNetworkMask)), 0)) { - if (net::globals::ipInfo.gw.addr == arp_cache_lookup(net::globals::ipInfo.gw.addr, s_send_packet.ether.dst)) { - net::memcpy_ip(s_send_packet.ip4.dst, RemoteIp); - } else { -#ifndef NDEBUG - console_error("ARP lookup failed -> default gateway :"); - printf(IPSTR " [%d]\n", IP2STR(RemoteIp), s_Port[nIndex]); -#endif - return -3; - } - } else { - if (RemoteIp == arp_cache_lookup(RemoteIp, s_send_packet.ether.dst)) { - net::memcpy_ip(s_send_packet.ip4.dst, RemoteIp); - } else { -#ifndef NDEBUG - console_error("ARP lookup failed: "); - printf(IPSTR "\n", IP2STR(RemoteIp)); -#endif - return -2; - } - } - } - } - - //IPv4 - s_send_packet.ip4.id = s_id; - s_send_packet.ip4.len = __builtin_bswap16((nSize + IPv4_UDP_HEADERS_SIZE)); - s_send_packet.ip4.chksum = 0; -#if !defined (CHECKSUM_BY_HARDWARE) - s_send_packet.ip4.chksum = net_chksum(reinterpret_cast(&s_send_packet.ip4), sizeof(s_send_packet.ip4)); -#endif - //UDP - s_send_packet.udp.source_port = __builtin_bswap16( s_Port[nIndex]); - s_send_packet.udp.destination_port = __builtin_bswap16(RemotePort); - s_send_packet.udp.len = __builtin_bswap16((nSize + UDP_HEADER_SIZE)); - - net::memcpy(s_send_packet.udp.data, pData, std::min(static_cast(UDP_DATA_SIZE), nSize)); - - emac_eth_send(reinterpret_cast(&s_send_packet), nSize + UDP_PACKET_HEADERS_SIZE); - - s_id++; - - return 0; +void udp_send(int nIndex, const uint8_t *pData, uint32_t nSize, uint32_t nRemoteIp, uint16_t nRemotePort) { + udp_send_implementation(nIndex, pData, nSize, nRemoteIp, nRemotePort); } +#if defined CONFIG_ENET_ENABLE_PTP +void udp_send_timestamp(int nIndex, const uint8_t *pData, uint32_t nSize, uint32_t nRemoteIp, uint16_t nRemotePort) { + udp_send_implementation(nIndex, pData, nSize, nRemoteIp, nRemotePort); +} +#endif +} // namespace net // <--- diff --git a/lib-network/src/noemac/network.cpp b/lib-network/src/noemac/network.cpp index dfb4c0d08..4ee0ffef5 100644 --- a/lib-network/src/noemac/network.cpp +++ b/lib-network/src/noemac/network.cpp @@ -2,7 +2,7 @@ * @file network.cpp * */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,6 +29,10 @@ #include "noemac/network.h" +namespace net { +void net_shutdown() {} +} // namespace net + void mac_address_get(uint8_t paddr[]); Network *Network::s_pThis = nullptr; From 19b064f6ea6f168bdaf586c6f88cc78ef6ae4e8c Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 16 Aug 2024 14:22:27 +0200 Subject: [PATCH 04/17] DMX single output issue fixed with OutputStyle --- lib-dmx/include/dmxconfigudp.h | 12 +- lib-dmx/include/dmxsend.h | 4 +- lib-dmx/include/gd32/board_gd32f207c_eval.h | 16 +- lib-dmx/include/gd32/dmx.h | 15 +- lib-dmx/include/gd32/dmx_config.h | 5 +- lib-dmx/include/h3/multi/dmx.h | 2 +- lib-dmx/include/h3/single/dmx.h | 2 +- lib-dmx/src/gd32/dmx.cpp | 2595 +++++++++++++++++++ lib-dmx/src/gd32/dmx_internal.h | 190 ++ lib-dmx/src/h3/multi/dmx.cpp | 2 +- lib-dmx/src/h3/single/dmx.cpp | 100 +- 11 files changed, 2868 insertions(+), 75 deletions(-) create mode 100755 lib-dmx/src/gd32/dmx.cpp create mode 100755 lib-dmx/src/gd32/dmx_internal.h diff --git a/lib-dmx/include/dmxconfigudp.h b/lib-dmx/include/dmxconfigudp.h index 06f64ab0a..a0b928310 100755 --- a/lib-dmx/include/dmxconfigudp.h +++ b/lib-dmx/include/dmxconfigudp.h @@ -2,7 +2,7 @@ * @file dmxconfigudp.h * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -83,7 +83,7 @@ class DmxConfigUdp { uint16_t nForeignPort; auto nBytesReceived = Network::Get()->RecvFrom(s_nHandle, const_cast(reinterpret_cast(&s_pUdpBuffer)), &nIPAddressFrom, &nForeignPort); - if (__builtin_expect((!dmxconfigudp::validate(static_cast(nBytesReceived), dmxconfigudp::MIN_SIZE, dmxconfigudp::MAX_SIZE)), 1)) { + if (__builtin_expect((!dmxconfigudp::validate(nBytesReceived, dmxconfigudp::MIN_SIZE, dmxconfigudp::MAX_SIZE)), 1)) { return; } @@ -99,7 +99,7 @@ class DmxConfigUdp { const auto *pCmd = &s_pUdpBuffer[4]; - if (dmxconfigudp::validate(nBytesReceived, static_cast(12), static_cast(13)) && (memcmp("break#", pCmd, 6) == 0)) { + if (dmxconfigudp::validate(nBytesReceived, static_cast(12), static_cast(13)) && (memcmp("break#", pCmd, 6) == 0)) { const auto nBreakTime = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[10]), nBytesReceived - 10U); if (nBreakTime >= dmx::transmit::BREAK_TIME_MIN) { Dmx::Get()->SetDmxBreakTime(nBreakTime); @@ -107,7 +107,7 @@ class DmxConfigUdp { return; } - if (dmxconfigudp::validate(nBytesReceived, static_cast(10), static_cast(16)) && (memcmp("mab#", pCmd, 4) == 0)) { + if (dmxconfigudp::validate(nBytesReceived, static_cast(10), static_cast(16)) && (memcmp("mab#", pCmd, 4) == 0)) { const auto nMapTime = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[8]), nBytesReceived - 8U); if (dmxconfigudp::validate(nMapTime, dmx::transmit::MAB_TIME_MIN, dmx::transmit::MAB_TIME_MAX)) { Dmx::Get()->SetDmxMabTime(nMapTime); @@ -115,7 +115,7 @@ class DmxConfigUdp { return; } - if (dmxconfigudp::validate(nBytesReceived, static_cast(13), static_cast(14)) && (memcmp("refresh#", pCmd, 8) == 0)) { + if (dmxconfigudp::validate(nBytesReceived, static_cast(13), static_cast(14)) && (memcmp("refresh#", pCmd, 8) == 0)) { const auto nRefreshRate = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[12]), nBytesReceived - 12U); uint32_t nPeriodTime = 0; if (nRefreshRate != 0) { @@ -125,7 +125,7 @@ class DmxConfigUdp { return; } - if (dmxconfigudp::validate(nBytesReceived, static_cast(11), static_cast(13)) && (memcmp("slots#", pCmd, 6) == 0)) { + if (dmxconfigudp::validate(nBytesReceived, static_cast(11), static_cast(13)) && (memcmp("slots#", pCmd, 6) == 0)) { const auto nSlots = dmxconfigudp::atoi(reinterpret_cast(&s_pUdpBuffer[10]), nBytesReceived - 10U); if (dmxconfigudp::validate(nSlots, dmx::min::CHANNELS, dmx::max::CHANNELS)) { Dmx::Get()->SetDmxSlots(static_cast(nSlots)); diff --git a/lib-dmx/include/dmxsend.h b/lib-dmx/include/dmxsend.h index a9920f39f..7377695e9 100755 --- a/lib-dmx/include/dmxsend.h +++ b/lib-dmx/include/dmxsend.h @@ -100,8 +100,8 @@ class DmxSend final: public LightSet { Dmx::Get()->SetSendDataWithoutSC(nPortIndex, lightset::Data::Backup(nPortIndex), lightset::Data::GetLength(nPortIndex)); } - void Sync(const bool doForce) override { - Dmx::Get()->SetOutput(doForce); + void Sync() override { + Dmx::Get()->Sync(); for (uint32_t nPortIndex = 0; nPortIndex < dmx::config::max::PORTS; nPortIndex++) { if (lightset::Data::GetLength(nPortIndex) != 0) { diff --git a/lib-dmx/include/gd32/board_gd32f207c_eval.h b/lib-dmx/include/gd32/board_gd32f207c_eval.h index a1520025f..689b28eb5 100644 --- a/lib-dmx/include/gd32/board_gd32f207c_eval.h +++ b/lib-dmx/include/gd32/board_gd32f207c_eval.h @@ -2,7 +2,7 @@ * @file board_gd32f207c_eval.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,7 +28,7 @@ #include "gd32_board.h" -#define DMX_MAX_PORTS 4 +#define DMX_MAX_PORTS 2 namespace max { static const uint32_t PORTS = DMX_MAX_PORTS; @@ -37,21 +37,21 @@ namespace max { //#define DMX_USE_USART0 #define DMX_USE_USART1 #define DMX_USE_USART2 -#define DMX_USE_UART3 -#define DMX_USE_UART4 +//#define DMX_USE_UART3 +//#define DMX_USE_UART4 //#define DMX_USE_USART5 //#define DMX_USE_UART6 //#define DMX_USE_UART7 -// + //static constexpr auto USART0_PORT = 0; static constexpr auto USART1_PORT = 0; static constexpr auto USART2_PORT = 1; -static constexpr auto UART3_PORT = 2; -static constexpr auto UART4_PORT = 3; +//static constexpr auto UART3_PORT = 2; +//static constexpr auto UART4_PORT = 3; //static constexpr auto USART5_PORT = 5; //static constexpr auto UART6_PORT = 6; //static constexpr auto UART7_PORT = 7; -// + static constexpr auto DIR_PORT_0_GPIO_PORT = GPIOE; static constexpr auto DIR_PORT_0_GPIO_PIN = GPIO_PIN_9; diff --git a/lib-dmx/include/gd32/dmx.h b/lib-dmx/include/gd32/dmx.h index e9bee311f..394b46e10 100644 --- a/lib-dmx/include/gd32/dmx.h +++ b/lib-dmx/include/gd32/dmx.h @@ -67,14 +67,10 @@ class Dmx { // DMX Send void SetDmxBreakTime(uint32_t nBreakTime); - uint32_t GetDmxBreakTime() const { - return m_nDmxTransmitBreakTime; - } + uint32_t GetDmxBreakTime() const; void SetDmxMabTime(uint32_t nMabTime); - uint32_t GetDmxMabTime() const { - return m_nDmxTransmitMabTime; - } + uint32_t GetDmxMabTime() const; void SetDmxPeriodTime(uint32_t nPeriodTime); uint32_t GetDmxPeriodTime() const { @@ -90,7 +86,7 @@ class Dmx { void SetSendDataWithoutSC(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength); void StartOutput(const uint32_t nPortIndex); - void SetOutput(const bool doForce); + void Sync(); void SetOutputStyle(const uint32_t nPortIndex, const dmx::OutputStyle outputStyle); dmx::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const; @@ -116,13 +112,12 @@ class Dmx { void StartDmxOutput(const uint32_t nPortIndex); private: - uint32_t m_nDmxTransmitBreakTime { dmx::transmit::BREAK_TIME_TYPICAL}; - uint32_t m_nDmxTransmitMabTime { dmx::transmit::MAB_TIME_MIN }; uint32_t m_nDmxTransmitPeriod { dmx::transmit::PERIOD_DEFAULT }; uint32_t m_nDmxTransmitPeriodRequested { dmx::transmit::PERIOD_DEFAULT }; uint32_t m_nDmxTransmissionLength[dmx::config::max::PORTS]; - uint16_t m_nDmxTransmitSlots { dmx::max::CHANNELS }; + uint32_t m_nDmxTransmitSlots { dmx::max::CHANNELS }; dmx::PortDirection m_dmxPortDirection[dmx::config::max::PORTS]; + bool m_bHasContinuosOutput { false }; static Dmx *s_pThis; }; diff --git a/lib-dmx/include/gd32/dmx_config.h b/lib-dmx/include/gd32/dmx_config.h index 862d936ba..440a29ca5 100644 --- a/lib-dmx/include/gd32/dmx_config.h +++ b/lib-dmx/include/gd32/dmx_config.h @@ -68,13 +68,16 @@ namespace config { namespace dmx { namespace buffer { -static constexpr auto SIZE = 514; // multiple of uint16_t +static constexpr auto SIZE = 516; // multiple of uint32_t } // namespace buffer } // namespace dmx #if defined(GD32F10X_HD) || defined (GD32F10X_CL) static_assert(DMX_MAX_PORTS <= 4, "Too many ports defined"); #endif +#if defined (GD32F20X_CL) + static_assert(DMX_MAX_PORTS <= 6, "Too many ports defined"); +#endif /** * DMA channel check diff --git a/lib-dmx/include/h3/multi/dmx.h b/lib-dmx/include/h3/multi/dmx.h index f6c53a2c4..f41093ec8 100644 --- a/lib-dmx/include/h3/multi/dmx.h +++ b/lib-dmx/include/h3/multi/dmx.h @@ -93,7 +93,7 @@ class Dmx { void SetSendDataWithoutSC(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength); void StartOutput(const uint32_t nPortIndex); - void SetOutput(const bool doForce); + void Sync(); void SetOutputStyle(const uint32_t nPortIndex, const dmx::OutputStyle outputStyle); dmx::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const; diff --git a/lib-dmx/include/h3/single/dmx.h b/lib-dmx/include/h3/single/dmx.h index 618585791..33849af31 100644 --- a/lib-dmx/include/h3/single/dmx.h +++ b/lib-dmx/include/h3/single/dmx.h @@ -91,7 +91,7 @@ class Dmx { void SetSendDataWithoutSC(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength); void StartOutput(const uint32_t nPortIndex); - void SetOutput(const bool doForce); + void Sync(); void SetOutputStyle(const uint32_t nPortIndex, const dmx::OutputStyle outputStyle); dmx::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const; diff --git a/lib-dmx/src/gd32/dmx.cpp b/lib-dmx/src/gd32/dmx.cpp new file mode 100755 index 000000000..f1a293efe --- /dev/null +++ b/lib-dmx/src/gd32/dmx.cpp @@ -0,0 +1,2595 @@ +/** + * @file dmx.cpp + * + */ +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if defined (CONFIG_TIMER6_HAVE_NO_IRQ_HANDLER) +# error +#endif + +#pragma GCC push_options +#pragma GCC optimize ("O3") +#pragma GCC optimize ("-fprefetch-loop-arrays") + +#include +#include +#include +#include + +#include "dmx.h" +#include "dmxconst.h" + +#include "rdm.h" +#include "rdm_e120.h" + +#include "gd32.h" +#include "gd32_dma.h" +#include "gd32_uart.h" +#include "gd32/dmx_config.h" +#include "dmx_internal.h" + +#include "logic_analyzer.h" + +#include "debug.h" + +#ifdef ALIGNED +#undef ALIGNED +#endif +#define ALIGNED __attribute__ ((aligned (4))) + +/** + * Needed for older GD32F firmware + */ +#if !defined(USART_TRANSMIT_DMA_ENABLE) +# define USART_TRANSMIT_DMA_ENABLE USART_DENT_ENABLE +#endif + +/** + * https://www.gd32-dmx.org/memory.html + */ +#if defined (GD32F20X) || defined (GD32F4XX) || defined (GD32H7XX) +# define SECTION_DMA_BUFFER __attribute__ ((section (".dmx"))) +#else +# define SECTION_DMA_BUFFER +#endif + +extern struct HwTimersSeconds g_Seconds; + +namespace dmx { +enum class TxRxState { + IDLE, BREAK, MAB, DMXDATA, DMXINTER, RDMDATA, CHECKSUMH, CHECKSUML, RDMDISC +}; + +enum class PortState { + IDLE, TX, RX +}; + +struct TxDmxPacket { + uint8_t data[dmx::buffer::SIZE]; // multiple of uint16_t + uint16_t nLength; + bool bDataPending; +}; + +struct TxData { + struct TxDmxPacket dmx; + OutputStyle outputStyle ALIGNED; + volatile TxRxState State; +}; + +struct RxDmxPackets { + uint32_t nPerSecond; + uint32_t nCount; + uint32_t nCountPrevious; + uint16_t nTimerCounterPrevious; +}; + +struct RxData { + struct { + uint8_t data[dmx::buffer::SIZE] ALIGNED; // multiple of uint16_t + uint32_t nSlotsInPacket; + } Dmx; + struct { + uint8_t data[sizeof(struct TRdmMessage)] ALIGNED; + uint32_t nIndex; + } Rdm; + TxRxState State; +} ALIGNED; + +struct DirGpio { + uint32_t nPort; + uint32_t nPin; +}; + +} // namespace dmx + +using namespace dmx; + +static constexpr DirGpio s_DirGpio[DMX_MAX_PORTS] = { + { config::DIR_PORT_0_GPIO_PORT, config::DIR_PORT_0_GPIO_PIN }, +#if DMX_MAX_PORTS >= 2 + { config::DIR_PORT_1_GPIO_PORT, config::DIR_PORT_1_GPIO_PIN }, +#endif +#if DMX_MAX_PORTS >= 3 + { config::DIR_PORT_2_GPIO_PORT, config::DIR_PORT_2_GPIO_PIN }, +#endif +#if DMX_MAX_PORTS >= 4 + { config::DIR_PORT_3_GPIO_PORT, config::DIR_PORT_3_GPIO_PIN }, +#endif +#if DMX_MAX_PORTS >= 5 + { config::DIR_PORT_4_GPIO_PORT, config::DIR_PORT_4_GPIO_PIN }, +#endif +#if DMX_MAX_PORTS >= 6 + { config::DIR_PORT_5_GPIO_PORT, config::DIR_PORT_5_GPIO_PIN }, +#endif +#if DMX_MAX_PORTS >= 7 + { config::DIR_PORT_6_GPIO_PORT, config::DIR_PORT_6_GPIO_PIN }, +#endif +#if DMX_MAX_PORTS == 8 + { config::DIR_PORT_7_GPIO_PORT, config::DIR_PORT_7_GPIO_PIN }, +#endif +}; + +static volatile PortState sv_PortState[dmx::config::max::PORTS] ALIGNED; + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) +static volatile dmx::TotalStatistics sv_TotalStatistics[dmx::config::max::PORTS] ALIGNED; +#endif + +// DMX RX + +[[maybe_unused]] static uint8_t sv_RxDmxPrevious[dmx::config::max::PORTS][dmx::buffer::SIZE] ALIGNED; +static volatile RxDmxPackets sv_nRxDmxPackets[dmx::config::max::PORTS] ALIGNED; + +// RDM RX +volatile uint32_t gsv_RdmDataReceiveEnd; + +// DMX RDM RX + +static volatile RxData sv_RxBuffer[dmx::config::max::PORTS] ALIGNED; + +// DMX TX + +static TxData s_TxBuffer[dmx::config::max::PORTS] ALIGNED SECTION_DMA_BUFFER; + +static uint32_t s_nDmxTransmitBreakTime; +static uint32_t s_nDmxTransmitMabTime; +static uint32_t s_nDmxTransmitInterTime; + +static void irq_handler_dmx_rdm_input(const uint32_t uart, const uint32_t nPortIndex) { + uint32_t nIndex; + uint16_t nCounter; + + if (RESET != (USART_REG_VAL(uart, USART_FLAG_FERR) & BIT(USART_BIT_POS(USART_FLAG_FERR)))) { + USART_REG_VAL(uart, USART_FLAG_FERR) &= ~BIT(USART_BIT_POS(USART_FLAG_FERR)); + static_cast(GET_BITS(USART_RDATA(uart), 0U, 8U)); + if (sv_RxBuffer[nPortIndex].State == TxRxState::IDLE) { + sv_RxBuffer[nPortIndex].State = TxRxState::BREAK; + } + return; + } + + const auto data = static_cast(GET_BITS(USART_RDATA(uart), 0U, 8U)); + + switch (sv_RxBuffer[nPortIndex].State) { + case TxRxState::IDLE: + sv_RxBuffer[nPortIndex].State = TxRxState::RDMDISC; + sv_RxBuffer[nPortIndex].Rdm.data[0] = data; + sv_RxBuffer[nPortIndex].Rdm.nIndex = 1; +#if DMX_MAX_PORTS >= 5 + if (nPortIndex < 4) { +#endif + sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = static_cast(TIMER_CNT(TIMER2)); +#if DMX_MAX_PORTS >= 5 + } else { + sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = static_cast(TIMER_CNT(TIMER3)); + } +#endif + break; + case TxRxState::BREAK: + switch (data) { + case START_CODE: + sv_RxBuffer[nPortIndex].Dmx.data[0] = START_CODE; + sv_RxBuffer[nPortIndex].Dmx.nSlotsInPacket = 1; + sv_nRxDmxPackets[nPortIndex].nCount++; + sv_RxBuffer[nPortIndex].State = TxRxState::DMXDATA; +#if DMX_MAX_PORTS >= 5 + if (nPortIndex < 4) { +#endif + sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = static_cast(TIMER_CNT(TIMER2)); +#if DMX_MAX_PORTS >= 5 + } else { + sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = static_cast(TIMER_CNT(TIMER3)); + } +#endif + break; + case E120_SC_RDM: + sv_RxBuffer[nPortIndex].Rdm.data[0] = E120_SC_RDM; + sv_RxBuffer[nPortIndex].Rdm.nIndex = 1; + sv_RxBuffer[nPortIndex].State = TxRxState::RDMDATA; + break; + default: + sv_RxBuffer[nPortIndex].Dmx.nSlotsInPacket = 0; + sv_RxBuffer[nPortIndex].Rdm.nIndex = 0; + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + break; + } + break; + case TxRxState::DMXDATA: + nIndex = sv_RxBuffer[nPortIndex].Dmx.nSlotsInPacket; + sv_RxBuffer[nPortIndex].Dmx.data[nIndex] = data; + sv_RxBuffer[nPortIndex].Dmx.nSlotsInPacket++; + + if (sv_RxBuffer[nPortIndex].Dmx.nSlotsInPacket > dmx::max::CHANNELS) { + sv_RxBuffer[nPortIndex].Dmx.nSlotsInPacket |= 0x8000; + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + break; + } + +#if DMX_MAX_PORTS >= 5 + if (nPortIndex < 4) { +#endif + nCounter = static_cast(TIMER_CNT(TIMER2)); +#if DMX_MAX_PORTS >= 5 + } else { + nCounter = static_cast(TIMER_CNT(TIMER3)); + } +#endif + { + const auto nDelta = nCounter - sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious; + sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = nCounter; + const auto nPulse = static_cast(nCounter + nDelta + 4); + + switch(nPortIndex){ + case 0: + TIMER_CH0CV(TIMER2) = nPulse; + break; +#if DMX_MAX_PORTS >= 2 + case 1: + TIMER_CH1CV(TIMER2) = nPulse; + break; +#endif +#if DMX_MAX_PORTS >= 3 + case 2: + TIMER_CH2CV(TIMER2) = nPulse; + break; +#endif +#if DMX_MAX_PORTS >= 4 + case 3: + TIMER_CH3CV(TIMER2) = nPulse; + break; +#endif +#if DMX_MAX_PORTS >= 5 + case 4: + TIMER_CH0CV(TIMER3) = nPulse; + break; +#endif +#if DMX_MAX_PORTS >= 6 + case 5: + TIMER_CH1CV(TIMER3) = nPulse; + break; +#endif +#if DMX_MAX_PORTS >= 7 + case 6: + TIMER_CH2CV(TIMER3) = nPulse; + break; +#endif +#if DMX_MAX_PORTS == 8 + case 7: + TIMER_CH3CV(TIMER3) = nPulse; + break; +#endif + default: + assert(0); + __builtin_unreachable(); + break; + } + } + break; + case TxRxState::RDMDATA: { + nIndex = sv_RxBuffer[nPortIndex].Rdm.nIndex; + sv_RxBuffer[nPortIndex].Rdm.data[nIndex] = data; + sv_RxBuffer[nPortIndex].Rdm.nIndex++; + + const auto *p = reinterpret_cast(&sv_RxBuffer[nPortIndex].Rdm.data[0]); + + nIndex = sv_RxBuffer[nPortIndex].Rdm.nIndex; + + if ((nIndex >= 24) && (nIndex <= sizeof(struct TRdmMessage)) && (nIndex == p->message_length)) { + sv_RxBuffer[nPortIndex].State = TxRxState::CHECKSUMH; + } else if (nIndex > sizeof(struct TRdmMessage)) { + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + } + } + break; + case TxRxState::CHECKSUMH: + nIndex = sv_RxBuffer[nPortIndex].Rdm.nIndex; + sv_RxBuffer[nPortIndex].Rdm.data[nIndex] = data; + sv_RxBuffer[nPortIndex].Rdm.nIndex++; + sv_RxBuffer[nPortIndex].State = TxRxState::CHECKSUML; + break; + case TxRxState::CHECKSUML: + nIndex = sv_RxBuffer[nPortIndex].Rdm.nIndex; + sv_RxBuffer[nPortIndex].Rdm.data[nIndex] = data; + sv_RxBuffer[nPortIndex].Rdm.nIndex |= 0x4000; + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + gsv_RdmDataReceiveEnd = DWT->CYCCNT; + break; + case TxRxState::RDMDISC: + nIndex = sv_RxBuffer[nPortIndex].Rdm.nIndex; + + if (nIndex < 24) { + sv_RxBuffer[nPortIndex].Rdm.data[nIndex] = data; + sv_RxBuffer[nPortIndex].Rdm.nIndex++; + } + +#if DMX_MAX_PORTS >= 5 + if (nPortIndex < 4) { +#endif + nCounter = static_cast(TIMER_CNT(TIMER2)); +#if DMX_MAX_PORTS >= 5 + } else { + nCounter = static_cast(TIMER_CNT(TIMER3)); + } +#endif + { + const auto nDelta = nCounter - sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious; + sv_nRxDmxPackets[nPortIndex].nTimerCounterPrevious = nCounter; + const auto nPulse = static_cast(nCounter + nDelta + 4); + + switch(nPortIndex){ + case 0: + TIMER_CH0CV(TIMER2) = nPulse; + break; +#if DMX_MAX_PORTS >= 2 + case 1: + TIMER_CH1CV(TIMER2) = nPulse; + break; +#endif +#if DMX_MAX_PORTS >= 3 + case 2: + TIMER_CH2CV(TIMER2) = nPulse; + break; +#endif +#if DMX_MAX_PORTS >= 4 + case 3: + TIMER_CH3CV(TIMER2) = nPulse; + break; +#endif +#if DMX_MAX_PORTS >= 5 + case 4: + TIMER_CH0CV(TIMER3) = nPulse; + break; +#endif +#if DMX_MAX_PORTS >= 6 + case 5: + TIMER_CH1CV(TIMER3) = nPulse; + break; +#endif +#if DMX_MAX_PORTS >= 7 + case 6: + TIMER_CH2CV(TIMER3) = nPulse; + break; +#endif +#if DMX_MAX_PORTS == 8 + case 7: + TIMER_CH3CV(TIMER3) = nPulse; + break; +#endif + default: + assert(0); + __builtin_unreachable(); + break; + } + } + break; + default: + sv_RxBuffer[nPortIndex].Dmx.nSlotsInPacket = 0; + sv_RxBuffer[nPortIndex].Rdm.nIndex = 0; + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + break; + } +} + +extern "C" { +#if !defined(CONFIG_DMX_TRANSMIT_ONLY) +#if defined (DMX_USE_USART0) +void USART0_IRQHandler(void) { + irq_handler_dmx_rdm_input(USART0, config::USART0_PORT); +} +#endif +#if defined (DMX_USE_USART1) +void USART1_IRQHandler(void) { + irq_handler_dmx_rdm_input(USART1, config::USART1_PORT); +} +#endif +#if defined (DMX_USE_USART2) +void USART2_IRQHandler(void) { + irq_handler_dmx_rdm_input(USART2, config::USART2_PORT); +} +#endif +#if defined (DMX_USE_UART3) +void UART3_IRQHandler(void) { + irq_handler_dmx_rdm_input(UART3, config::UART3_PORT); +} +#endif +#if defined (DMX_USE_UART4) +void UART4_IRQHandler(void) { + irq_handler_dmx_rdm_input(UART4, config::UART4_PORT); +} +#endif +#if defined (DMX_USE_USART5) +void USART5_IRQHandler(void) { + irq_handler_dmx_rdm_input(USART5, config::USART5_PORT); +} +#endif +#if defined (DMX_USE_UART6) +void UART6_IRQHandler(void) { + irq_handler_dmx_rdm_input(UART6, config::UART6_PORT); +} +#endif +#if defined (DMX_USE_UART7) +void UART7_IRQHandler(void) { + irq_handler_dmx_rdm_input(UART7, config::UART7_PORT); +} +#endif +#endif +} + +static void timer1_config() { + rcu_periph_clock_enable(RCU_TIMER1); + timer_deinit(TIMER1); + + timer_parameter_struct timer_initpara; + timer_struct_para_init(&timer_initpara); + + timer_initpara.prescaler = TIMER_PSC_1MHZ; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = ~0; + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_initpara.repetitioncounter = 0; + timer_init(TIMER1, &timer_initpara); + + timer_flag_clear(TIMER1, ~0); + timer_interrupt_flag_clear(TIMER1, ~0); + +#if defined (DMX_USE_USART0) + timer_channel_output_mode_config(TIMER1, TIMER_CH_0, TIMER_OC_MODE_ACTIVE); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0, ~0); + timer_interrupt_enable(TIMER1, TIMER_INT_CH0); +#endif + +#if defined (DMX_USE_USART1) + timer_channel_output_mode_config(TIMER1, TIMER_CH_1, TIMER_OC_MODE_ACTIVE); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1, ~0); + timer_interrupt_enable(TIMER1, TIMER_INT_CH1); +#endif + +#if defined (DMX_USE_USART2) + timer_channel_output_mode_config(TIMER1, TIMER_CH_2, TIMER_OC_MODE_ACTIVE); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2, ~0); + timer_interrupt_enable(TIMER1, TIMER_INT_CH2); +#endif + +#if defined (DMX_USE_UART3) + timer_channel_output_mode_config(TIMER1, TIMER_CH_3, TIMER_OC_MODE_ACTIVE); + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3, ~0); + timer_interrupt_enable(TIMER1, TIMER_INT_CH3); +#endif + + NVIC_SetPriority(TIMER1_IRQn, 0); + NVIC_EnableIRQ(TIMER1_IRQn); + + timer_enable(TIMER1); +} + +static void timer4_config() { + rcu_periph_clock_enable(RCU_TIMER4); + timer_deinit(TIMER4); + + timer_parameter_struct timer_initpara; + timer_struct_para_init(&timer_initpara); + + timer_initpara.prescaler = TIMER_PSC_1MHZ; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = ~0; + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_initpara.repetitioncounter = 0; + timer_init(TIMER4, &timer_initpara); + + timer_flag_clear(TIMER4, ~0); + timer_interrupt_flag_clear(TIMER4, ~0); + +#if defined (DMX_USE_UART4) + timer_channel_output_mode_config(TIMER4, TIMER_CH_0, TIMER_OC_MODE_ACTIVE); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0, ~0); + timer_interrupt_enable(TIMER4, TIMER_INT_CH0); +#endif + +#if defined (DMX_USE_USART5) + timer_channel_output_mode_config(TIMER4, TIMER_CH_1, TIMER_OC_MODE_ACTIVE); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_1, ~0); + timer_interrupt_enable(TIMER4, TIMER_INT_CH1); +#endif + +#if defined (DMX_USE_UART6) + timer_channel_output_mode_config(TIMER4, TIMER_CH_2, TIMER_OC_MODE_ACTIVE); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2, ~0); + timer_interrupt_enable(TIMER4, TIMER_INT_CH2); +#endif + +#if defined (DMX_USE_UART7) + timer_channel_output_mode_config(TIMER4, TIMER_CH_3, TIMER_OC_MODE_ACTIVE); + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3, ~0); + timer_interrupt_enable(TIMER4, TIMER_INT_CH3); +#endif + + NVIC_SetPriority(TIMER4_IRQn, 0); + NVIC_EnableIRQ(TIMER4_IRQn); + + timer_enable(TIMER4); +} + +#if !defined(CONFIG_DMX_TRANSMIT_ONLY) +static void timer2_config() { + rcu_periph_clock_enable(RCU_TIMER2); + timer_deinit(TIMER2); + + timer_parameter_struct timer_initpara; + timer_struct_para_init(&timer_initpara); + + timer_initpara.prescaler = TIMER_PSC_1MHZ; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = static_cast(~0); + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_initpara.repetitioncounter = 0; + timer_init(TIMER2, &timer_initpara); + + timer_flag_clear(TIMER2, ~0); + timer_interrupt_flag_clear(TIMER2, ~0); + + timer_channel_output_mode_config(TIMER2, TIMER_CH_0, TIMER_OC_MODE_ACTIVE); + timer_channel_output_mode_config(TIMER2, TIMER_CH_1, TIMER_OC_MODE_ACTIVE); + timer_channel_output_mode_config(TIMER2, TIMER_CH_2, TIMER_OC_MODE_ACTIVE); + timer_channel_output_mode_config(TIMER2, TIMER_CH_3, TIMER_OC_MODE_ACTIVE); + + NVIC_SetPriority(TIMER2_IRQn, 2); + NVIC_EnableIRQ(TIMER2_IRQn); + + timer_enable(TIMER2); +} + +static void timer3_config() { +#if DMX_MAX_PORTS >= 5 + rcu_periph_clock_enable(RCU_TIMER3); + timer_deinit(TIMER3); + + timer_parameter_struct timer_initpara; + timer_struct_para_init(&timer_initpara); + + timer_initpara.prescaler = TIMER_PSC_1MHZ; + timer_initpara.alignedmode = TIMER_COUNTER_EDGE; + timer_initpara.counterdirection = TIMER_COUNTER_UP; + timer_initpara.period = static_cast(~0); + timer_initpara.clockdivision = TIMER_CKDIV_DIV1; + timer_initpara.repetitioncounter = 0; + timer_init(TIMER3, &timer_initpara); + + timer_flag_clear(TIMER3, ~0); + timer_interrupt_flag_clear(TIMER3, ~0); + + timer_channel_output_mode_config(TIMER3, TIMER_CH_0, TIMER_OC_MODE_ACTIVE); + timer_channel_output_mode_config(TIMER3, TIMER_CH_1, TIMER_OC_MODE_ACTIVE); + timer_channel_output_mode_config(TIMER3, TIMER_CH_2, TIMER_OC_MODE_ACTIVE); + timer_channel_output_mode_config(TIMER3, TIMER_CH_3, TIMER_OC_MODE_ACTIVE); + + NVIC_SetPriority(TIMER3_IRQn, 2); + NVIC_EnableIRQ(TIMER3_IRQn); + + timer_enable(TIMER3); +#endif +} +#endif + +static void usart_dma_config(void) { + DMA_PARAMETER_STRUCT dma_init_struct; + rcu_periph_clock_enable(RCU_DMA0); + rcu_periph_clock_enable(RCU_DMA1); +#if defined (GD32H7XX) + rcu_periph_clock_enable(RCU_DMAMUX); +#endif + /* + * USART 0 + */ +#if defined (DMX_USE_USART0) + dma_deinit(USART0_DMAx, USART0_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_USART0_TX; +# endif + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; +# if defined (GD32F4XX) || defined (GD32H7XX) +# else + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(USART0>(); +# else + dma_init_struct.periph_addr = USART0 + 0x04U; +# endif + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; +# if defined (GD32F4XX) || defined (GD32H7XX) + dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; +# else + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; +# endif + dma_init_struct.priority = DMA_PRIORITY_HIGH; + dma_init(USART0_DMAx, USART0_TX_DMA_CHx, &dma_init_struct); + /* configure DMA mode */ + dma_circulation_disable(USART0_DMAx, USART0_TX_DMA_CHx); + dma_memory_to_memory_disable(USART0_DMAx, USART0_TX_DMA_CHx); +# if defined (GD32F4XX) + dma_channel_subperipheral_select(USART0_DMAx, USART0_TX_DMA_CHx, USART0_TX_DMA_SUBPERIx); +# endif + gd32_dma_interrupt_disable(); +# if !defined (GD32F4XX) + NVIC_SetPriority(DMA0_Channel3_IRQn, 1); + NVIC_EnableIRQ(DMA0_Channel3_IRQn); +# else + NVIC_SetPriority(DMA1_Channel7_IRQn, 1); + NVIC_EnableIRQ(DMA1_Channel7_IRQn); +# endif +#endif + /* + * USART 1 + */ +#if defined (DMX_USE_USART1) + dma_deinit(USART1_DMAx, USART1_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_USART1_TX; +# endif + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; +# if defined (GD32F4XX) || defined (GD32H7XX) +# else + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(USART1>(); +# else + dma_init_struct.periph_addr = USART1 + 0x04U; +# endif + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; +# if defined (GD32F4XX) || defined (GD32H7XX) + dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; +# else + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; +# endif + dma_init_struct.priority = DMA_PRIORITY_HIGH; + dma_init(USART1_DMAx, USART1_TX_DMA_CHx, &dma_init_struct); + /* configure DMA mode */ + dma_circulation_disable(USART1_DMAx, USART1_TX_DMA_CHx); + dma_memory_to_memory_disable(USART1_DMAx, USART1_TX_DMA_CHx); +# if defined (GD32F4XX) + dma_channel_subperipheral_select(USART1_DMAx, USART1_TX_DMA_CHx, USART1_TX_DMA_SUBPERIx); +# endif + gd32_dma_interrupt_disable(); + NVIC_SetPriority(DMA0_Channel6_IRQn, 1); + NVIC_EnableIRQ(DMA0_Channel6_IRQn); +#endif + /* + * USART 2 + */ +#if defined (DMX_USE_USART2) + dma_deinit(USART2_DMAx, USART2_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_USART2_TX; +# endif + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; +# if defined (GD32F4XX) || defined (GD32H7XX) +# else + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(USART2>(); +# else + dma_init_struct.periph_addr = USART2 + 0x04U; +# endif + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; +# if defined (GD32F4XX) || defined (GD32H7XX) + dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; +# else + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; +# endif + dma_init_struct.priority = DMA_PRIORITY_HIGH; + dma_init(USART2_DMAx, USART2_TX_DMA_CHx, &dma_init_struct); + /* configure DMA mode */ + dma_circulation_disable(USART2_DMAx, USART2_TX_DMA_CHx); + dma_memory_to_memory_disable(USART2_DMAx, USART2_TX_DMA_CHx); +# if defined (GD32F4XX) + dma_channel_subperipheral_select(USART2_DMAx, USART2_TX_DMA_CHx, USART2_TX_DMA_SUBPERIx); +# endif + gd32_dma_interrupt_disable(); +#if defined (GD32F4XX) || defined (GD32H7XX) + NVIC_SetPriority(DMA0_Channel3_IRQn, 1); + NVIC_EnableIRQ(DMA0_Channel3_IRQn); +# else + NVIC_SetPriority(DMA0_Channel1_IRQn, 1); + NVIC_EnableIRQ(DMA0_Channel1_IRQn); +# endif +#endif + /* + * UART 3 + */ +#if defined (DMX_USE_UART3) + dma_deinit(UART3_DMAx, UART3_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_UART3_TX; +# endif + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; +# if defined (GD32F4XX) || defined (GD32H7XX) +# else + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(UART3>(); +# else + dma_init_struct.periph_addr = UART3 + 0x04U; +# endif + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; +# if defined (GD32F4XX) || defined (GD32H7XX) + dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; +# else + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; +# endif + dma_init_struct.priority = DMA_PRIORITY_HIGH; + dma_init(UART3_DMAx, UART3_TX_DMA_CHx, &dma_init_struct); + /* configure DMA mode */ + dma_circulation_disable(UART3_DMAx, UART3_TX_DMA_CHx); + dma_memory_to_memory_disable(UART3_DMAx, UART3_TX_DMA_CHx); +# if defined (GD32F4XX) + dma_channel_subperipheral_select(UART3_DMAx, UART3_TX_DMA_CHx, UART3_TX_DMA_SUBPERIx); +# endif + gd32_dma_interrupt_disable(); +# if !defined (GD32F4XX) + NVIC_SetPriority(DMA1_Channel4_IRQn, 1); + NVIC_EnableIRQ(DMA1_Channel4_IRQn); +# else + NVIC_SetPriority(DMA0_Channel4_IRQn, 1); + NVIC_EnableIRQ(DMA0_Channel4_IRQn); +# endif +#endif + /* + * UART 4 + */ +#if defined (DMX_USE_UART4) + dma_deinit(UART4_DMAx, UART4_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_UART4_TX; +# endif + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; +# if defined (GD32F4XX) || defined (GD32H7XX) +# else + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(UART4>(); +# else + dma_init_struct.periph_addr = UART4 + 0x04U; +# endif + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; +#if defined (GD32F4XX) || defined (GD32H7XX) + dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; +#else + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; +#endif + dma_init_struct.priority = DMA_PRIORITY_HIGH; + dma_init(UART4_DMAx, UART4_TX_DMA_CHx, &dma_init_struct); + /* configure DMA mode */ + dma_circulation_disable(UART4_DMAx, UART4_TX_DMA_CHx); + dma_memory_to_memory_disable(UART4_DMAx, UART4_TX_DMA_CHx); +# if defined (GD32F4XX) + dma_channel_subperipheral_select(UART4_DMAx, UART4_TX_DMA_CHx, UART4_TX_DMA_SUBPERIx); +# endif + gd32_dma_interrupt_disable(); +# if !defined (GD32F4XX) + NVIC_SetPriority(DMA1_Channel3_IRQn, 1); + NVIC_EnableIRQ(DMA1_Channel3_IRQn); +# else + NVIC_SetPriority(DMA0_Channel7_IRQn, 1); + NVIC_EnableIRQ(DMA0_Channel7_IRQn); +# endif +#endif + /* + * USART 5 + */ +#if defined (DMX_USE_USART5) + dma_deinit(USART5_DMAx, USART5_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_USART5_TX; +# endif + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; +# if defined (GD32F20X) + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(USART5>(); +# else + dma_init_struct.periph_addr = USART5 + 0x04U; +# endif + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; +#if defined (GD32F20X) + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; +# else + dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; +#endif + dma_init_struct.priority = DMA_PRIORITY_HIGH; + dma_init(USART5_DMAx, USART5_TX_DMA_CHx, &dma_init_struct); + /* configure DMA mode */ + dma_circulation_disable(USART5_DMAx, USART5_TX_DMA_CHx); + dma_memory_to_memory_disable(USART5_DMAx, USART5_TX_DMA_CHx); +# if defined (GD32F4XX) + dma_channel_subperipheral_select(USART5_DMAx, USART5_TX_DMA_CHx, USART5_TX_DMA_SUBPERIx); +# endif + gd32_dma_interrupt_disable(); + NVIC_SetPriority(DMA1_Channel6_IRQn, 1); + NVIC_EnableIRQ(DMA1_Channel6_IRQn); +#endif + /* + * UART 6 + */ +#if defined (DMX_USE_UART6) + dma_deinit(UART6_DMAx, UART6_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_UART6_TX; +# endif + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; +# if defined (GD32F20X) + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(UART6>(); +# else + dma_init_struct.periph_addr = UART6 + 0x04U; +# endif + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; +# if defined (GD32F20X) + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; +# else + dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; +# endif + dma_init_struct.priority = DMA_PRIORITY_HIGH; + dma_init(UART6_DMAx, UART6_TX_DMA_CHx, &dma_init_struct); + /* configure DMA mode */ + dma_circulation_disable(UART6_DMAx, UART6_TX_DMA_CHx); + dma_memory_to_memory_disable(UART6_DMAx, UART6_TX_DMA_CHx); +# if defined (GD32F4XX) + dma_channel_subperipheral_select(UART6_DMAx, UART6_TX_DMA_CHx, UART6_TX_DMA_SUBPERIx); +# endif + gd32_dma_interrupt_disable(); +# if defined (GD32F20X) + NVIC_SetPriority(DMA1_Channel4_IRQn, 1); + NVIC_EnableIRQ(DMA1_Channel4_IRQn); +# else + NVIC_SetPriority(DMA0_Channel1_IRQn, 1); + NVIC_EnableIRQ(DMA0_Channel1_IRQn); +# endif +#endif + /* + * UART 7 + */ +#if defined (DMX_USE_UART7) + dma_deinit(UART7_DMAx, UART7_TX_DMA_CHx); +# if defined (GD32H7XX) + dma_init_struct.request = DMA_REQUEST_UART7_TX; +# endif + dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL; + dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE; +# if defined (GD32F20X) + dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT; +# endif +# if defined (GD32H7XX) + dma_init_struct.periph_addr = (uint32_t) &USART_TDATA(UART7>(); +# else + dma_init_struct.periph_addr = UART7 + 0x04U; +# endif + dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE; +# if defined (GD32F20X) + dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT; +# else + dma_init_struct.periph_memory_width = DMA_PERIPHERAL_WIDTH_8BIT; +# endif + dma_init_struct.priority = DMA_PRIORITY_HIGH; + dma_init(UART7_DMAx, UART7_TX_DMA_CHx, &dma_init_struct); + /* configure DMA mode */ + dma_circulation_disable(UART7_DMAx, UART7_TX_DMA_CHx); + dma_memory_to_memory_disable(UART7_DMAx, UART7_TX_DMA_CHx); +# if defined (GD32F4XX) + dma_channel_subperipheral_select(UART7_DMAx, UART7_TX_DMA_CHx, UART7_TX_DMA_SUBPERIx); +# endif +#if defined (GD32F20X) + NVIC_SetPriority(DMA1_Channel3_IRQn, 1); + NVIC_EnableIRQ(DMA1_Channel3_IRQn); +# else + NVIC_SetPriority(DMA0_Channel0_IRQn, 1); + NVIC_EnableIRQ(DMA0_Channel0_IRQn); +# endif +#endif +} + +extern "C" { +void TIMER1_IRQHandler() { + /* + * USART 0 + */ +#if defined (DMX_USE_USART0) + if ((TIMER_INTF(TIMER1) & TIMER_INT_FLAG_CH0) == TIMER_INT_FLAG_CH0) { + switch (s_TxBuffer[dmx::config::USART0_PORT].State) { + case TxRxState::DMXINTER: + gd32_gpio_mode_output(); + GPIO_BC(USART0_GPIOx) = USART0_TX_GPIO_PINx; + s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::BREAK; + TIMER_CH0CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime; + break; + case TxRxState::BREAK: + gd32_gpio_mode_af(); + s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::MAB; + TIMER_CH0CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitMabTime; + break; + case TxRxState::MAB: { + uint32_t dmaCHCTL = DMA_CHCTL(USART0_DMAx, USART0_TX_DMA_CHx); + dmaCHCTL &= ~DMA_CHXCTL_CHEN; + DMA_CHCTL(USART0_DMAx, USART0_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); + const auto *p = &s_TxBuffer[dmx::config::USART0_PORT].dmx; + DMA_CHMADDR(USART0_DMAx, USART0_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(USART0_DMAx, USART0_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); + dmaCHCTL |= DMA_CHXCTL_CHEN; + dmaCHCTL |= DMA_INTERRUPT_ENABLE; + DMA_CHCTL(USART0_DMAx, USART0_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(USART0) |= USART_TRANSMIT_DMA_ENABLE; + } + break; + default: + break; + } + + TIMER_INTF(TIMER1) = static_cast(~TIMER_INT_FLAG_CH0); + } +#endif + /* + * USART 1 + */ +#if defined (DMX_USE_USART1) + if ((TIMER_INTF(TIMER1) & TIMER_INT_FLAG_CH1) == TIMER_INT_FLAG_CH1) { + switch (s_TxBuffer[dmx::config::USART1_PORT].State) { + case TxRxState::DMXINTER: + gd32_gpio_mode_output(); + GPIO_BC(USART1_GPIOx) = USART1_TX_GPIO_PINx; + s_TxBuffer[dmx::config::USART1_PORT].State = TxRxState::BREAK; + TIMER_CH1CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime; + break; + case TxRxState::BREAK: + gd32_gpio_mode_af(); + s_TxBuffer[dmx::config::USART1_PORT].State = TxRxState::MAB; + TIMER_CH1CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitMabTime; + break; + case TxRxState::MAB: { + uint32_t dmaCHCTL = DMA_CHCTL(USART1_DMAx, USART1_TX_DMA_CHx); + dmaCHCTL &= ~DMA_CHXCTL_CHEN; + DMA_CHCTL(USART1_DMAx, USART1_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_cleardata; + DMA_CHCNT(USART1_DMAx, USART1_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); + dmaCHCTL |= DMA_CHXCTL_CHEN; + dmaCHCTL |= DMA_INTERRUPT_ENABLE; + DMA_CHCTL(USART1_DMAx, USART1_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(USART1) |= USART_TRANSMIT_DMA_ENABLE; + } + break; + default: + break; + } + + TIMER_INTF(TIMER1) = static_cast(~TIMER_INT_FLAG_CH1); + } +#endif + /* + * USART 2 + */ +#if defined (DMX_USE_USART2) + if ((TIMER_INTF(TIMER1) & TIMER_INT_FLAG_CH2) == TIMER_INT_FLAG_CH2) { + switch (s_TxBuffer[dmx::config::USART2_PORT].State) { + case TxRxState::DMXINTER: + gd32_gpio_mode_output(); + GPIO_BC(USART2_GPIOx) = USART2_TX_GPIO_PINx; + s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::BREAK; + TIMER_CH2CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime; + break; + case TxRxState::BREAK: + gd32_gpio_mode_af(); + s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::MAB; + TIMER_CH2CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitMabTime; + break; + case TxRxState::MAB: { + uint32_t dmaCHCTL = DMA_CHCTL(USART2_DMAx, USART2_TX_DMA_CHx); + dmaCHCTL &= ~DMA_CHXCTL_CHEN; + DMA_CHCTL(USART2_DMAx, USART2_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); + const auto *p = &s_TxBuffer[dmx::config::USART2_PORT].dmx; + DMA_CHMADDR(USART2_DMAx, USART2_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(USART2_DMAx, USART2_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); + dmaCHCTL |= DMA_CHXCTL_CHEN; + dmaCHCTL |= DMA_INTERRUPT_ENABLE; + DMA_CHCTL(USART2_DMAx, USART2_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(USART2) |= USART_TRANSMIT_DMA_ENABLE; + } + break; + default: + break; + } + + TIMER_INTF(TIMER1) = static_cast(~TIMER_INT_FLAG_CH2); + } +#endif + /* + * UART 3 + */ +#if defined (DMX_USE_UART3) + if ((TIMER_INTF(TIMER1) & TIMER_INT_FLAG_CH3) == TIMER_INT_FLAG_CH3) { + switch (s_TxBuffer[dmx::config::UART3_PORT].State) { + case TxRxState::DMXINTER: + gd32_gpio_mode_output(); + GPIO_BC(UART3_GPIOx) = UART3_TX_GPIO_PINx; + s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::BREAK; + TIMER_CH3CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime; + break; + case TxRxState::BREAK: + gd32_gpio_mode_af(); + s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::MAB; + TIMER_CH3CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitMabTime; + break; + case TxRxState::MAB: { + uint32_t dmaCHCTL = DMA_CHCTL(UART3_DMAx, UART3_TX_DMA_CHx); + dmaCHCTL &= ~DMA_CHXCTL_CHEN; + DMA_CHCTL(UART3_DMAx, UART3_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); + const auto *p = &s_TxBuffer[dmx::config::UART3_PORT].dmx; + DMA_CHMADDR(UART3_DMAx, UART3_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(UART3_DMAx, UART3_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); + dmaCHCTL |= DMA_CHXCTL_CHEN; + dmaCHCTL |= DMA_INTERRUPT_ENABLE; + DMA_CHCTL(UART3_DMAx, UART3_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(UART3) |= USART_TRANSMIT_DMA_ENABLE; + } + break; + default: + break; + } + + TIMER_INTF(TIMER1) = static_cast(~TIMER_INT_FLAG_CH3); + } +#endif + // Clear all remaining interrupt flags (safety measure) + TIMER_INTF(TIMER1) = static_cast(~0); +} + +void TIMER4_IRQHandler() { + /* + * UART 4 + */ +#if defined (DMX_USE_UART4) + if ((TIMER_INTF(TIMER4) & TIMER_INT_FLAG_CH0) == TIMER_INT_FLAG_CH0) { + switch (s_TxBuffer[dmx::config::UART4_PORT].State) { + case TxRxState::DMXINTER: + gd32_gpio_mode_output(); + GPIO_BC(UART4_TX_GPIOx) = UART4_TX_GPIO_PINx; + s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::BREAK; + TIMER_CH0CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime; + break; + case TxRxState::BREAK: + gd32_gpio_mode_af(); + s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::MAB; + TIMER_CH0CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitMabTime; + break; + case TxRxState::MAB: { + uint32_t dmaCHCTL = DMA_CHCTL(UART4_DMAx, UART4_TX_DMA_CHx); + dmaCHCTL &= ~DMA_CHXCTL_CHEN; + DMA_CHCTL(UART4_DMAx, UART4_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); + const auto *p = &s_TxBuffer[dmx::config::UART4_PORT].dmx; + DMA_CHMADDR(UART4_DMAx, UART4_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(UART4_DMAx, UART4_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); + dmaCHCTL |= DMA_CHXCTL_CHEN; + dmaCHCTL |= DMA_INTERRUPT_ENABLE; + DMA_CHCTL(UART4_DMAx, UART4_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(UART4) |= USART_TRANSMIT_DMA_ENABLE; + } + break; + default: + break; + } + + TIMER_INTF(TIMER4) = static_cast(~TIMER_INT_FLAG_CH0); + } +#endif + /* + * USART 5 + */ +#if defined (DMX_USE_USART5) + if ((TIMER_INTF(TIMER4) & TIMER_INT_FLAG_CH1) == TIMER_INT_FLAG_CH1) { + switch (s_TxBuffer[dmx::config::USART5_PORT].State) { + case TxRxState::DMXINTER: + gd32_gpio_mode_output(); + GPIO_BC(USART5_GPIOx) = USART5_TX_GPIO_PINx; + s_TxBuffer[dmx::config::USART5_PORT].State = TxRxState::BREAK; + TIMER_CH1CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime; + break; + case TxRxState::BREAK: + gd32_gpio_mode_af(); + s_TxBuffer[dmx::config::USART5_PORT].State = TxRxState::MAB; + TIMER_CH1CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitMabTime; + break; + case TxRxState::MAB: { + uint32_t dmaCHCTL = DMA_CHCTL(USART5_DMAx, USART5_TX_DMA_CHx); + dmaCHCTL &= ~DMA_CHXCTL_CHEN; + DMA_CHCTL(USART5_DMAx, USART5_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); + const auto *p = &s_TxBuffer[dmx::config::USART5_PORT].dmx; + DMA_CHMADDR(USART5_DMAx, USART5_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(USART5_DMAx, USART5_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); + dmaCHCTL |= DMA_CHXCTL_CHEN; + dmaCHCTL |= DMA_INTERRUPT_ENABLE; + DMA_CHCTL(USART5_DMAx, USART5_TX_DMA_CHx) = dmaCHCTL; + USART_CTL2(USART5) |= USART_TRANSMIT_DMA_ENABLE; + } + break; + default: + break; + } + + TIMER_INTF(TIMER4) = static_cast(~TIMER_INT_FLAG_CH1); + } +#endif + /* + * UART 6 + */ +#if defined (DMX_USE_UART6) + if ((TIMER_INTF(TIMER4) & TIMER_INT_FLAG_CH2) == TIMER_INT_FLAG_CH2) { + switch (s_TxBuffer[dmx::config::UART6_PORT].State) { + case TxRxState::DMXINTER: + gd32_gpio_mode_output(); + GPIO_BC(UART6_GPIOx) = UART6_TX_GPIO_PINx; + s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::BREAK; + TIMER_CH2CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime; + break; + case TxRxState::BREAK: + gd32_gpio_mode_af(); + s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::MAB; + TIMER_CH2CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitMabTime; + break; + case TxRxState::MAB: { + uint32_t dmaCHCTL = DMA_CHCTL(UART6_DMAx, UART6_TX_DMA_CHx); + dmaCHCTL &= ~DMA_CHXCTL_CHEN; + DMA_CHCTL(UART6_DMAx, UART6_TX_DMA_CHx)= dmaCHCTL; + gd32_dma_interrupt_flag_clear(); + const auto *p = &s_TxBuffer[dmx::config::UART6_PORT].dmx; + DMA_CHMADDR(UART6_DMAx, UART6_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(UART6_DMAx, UART6_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); + dmaCHCTL |= DMA_CHXCTL_CHEN; + dmaCHCTL |= DMA_INTERRUPT_ENABLE; + DMA_CHCTL(UART6_DMAx, UART6_TX_DMA_CHx)= dmaCHCTL; + USART_CTL2(UART6) |= USART_TRANSMIT_DMA_ENABLE; + } + break; + default: + break; + } + + TIMER_INTF(TIMER4) = static_cast(~TIMER_INT_FLAG_CH2); + } +#endif + /* + * UART 7 + */ +#if defined (DMX_USE_UART7) + if ((TIMER_INTF(TIMER4) & TIMER_INT_FLAG_CH3) == TIMER_INT_FLAG_CH3) { + switch (s_TxBuffer[dmx::config::UART7_PORT].State) { + case TxRxState::DMXINTER: + gd32_gpio_mode_output(); + GPIO_BC(UART7_GPIOx) = UART7_TX_GPIO_PINx; + s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::BREAK; + TIMER_CH3CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime; + break; + case TxRxState::BREAK: + gd32_gpio_mode_af(); + s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::MAB; + TIMER_CH3CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitMabTime; + break; + case TxRxState::MAB: { + uint32_t dmaCHCTL = DMA_CHCTL(UART7_DMAx, UART7_TX_DMA_CHx); + dmaCHCTL &= ~DMA_CHXCTL_CHEN; + DMA_CHCTL(UART7_DMAx, UART7_TX_DMA_CHx) = dmaCHCTL; + gd32_dma_interrupt_flag_clear(); + const auto *p = &s_TxBuffer[dmx::config::UART7_PORT].dmx; + DMA_CHMADDR(UART7_DMAx, UART7_TX_DMA_CHx) = (uint32_t) p->data; + DMA_CHCNT(UART7_DMAx, UART7_TX_DMA_CHx) = (p->nLength & DMA_CHXCNT_CNT); + dmaCHCTL |= DMA_CHXCTL_CHEN; + dmaCHCTL |= DMA_INTERRUPT_ENABLE; + DMA_CHCTL(UART7_DMAx, UART7_TX_DMA_CHx)= dmaCHCTL; + USART_CTL2(UART7) |= USART_TRANSMIT_DMA_ENABLE; + } + break; + default: + break; + } + + TIMER_INTF(TIMER4) = static_cast(~TIMER_INT_FLAG_CH3); + } +#endif + // Clear all remaining interrupt flags (safety measure) + TIMER_INTF(TIMER4) = static_cast(~0); +} + +void TIMER6_IRQHandler() { + const auto nIntFlag = TIMER_INTF(TIMER6); + + if ((nIntFlag & TIMER_INT_FLAG_UP) == TIMER_INT_FLAG_UP) { +#if !defined(CONFIG_DMX_TRANSMIT_ONLY) + for (size_t i = 0; i < DMX_MAX_PORTS; i++) { + auto &packet = sv_nRxDmxPackets[i]; + packet.nPerSecond = sv_nRxDmxPackets[i].nCount - packet.nCountPrevious; + packet.nCountPrevious = packet.nCount; + } +#endif + ++g_Seconds.nUptime; + } + + // Clear all remaining interrupt flags (safety measure) + TIMER_INTF(TIMER6) = static_cast(~nIntFlag); +} + +#if !defined(CONFIG_DMX_TRANSMIT_ONLY) +void TIMER2_IRQHandler() { + const auto nIntFlag = TIMER_INTF(TIMER2); + + if ((nIntFlag & TIMER_INT_FLAG_CH0) == TIMER_INT_FLAG_CH0) { + if (sv_RxBuffer[0].State == TxRxState::DMXDATA) { + sv_RxBuffer[0].State = TxRxState::IDLE; + sv_RxBuffer[0].Dmx.nSlotsInPacket |= 0x8000; + } else if (sv_RxBuffer[0].State == TxRxState::RDMDISC) { + sv_RxBuffer[0].State = TxRxState::IDLE; + sv_RxBuffer[0].Rdm.nIndex |= 0x4000; + } + } +#if DMX_MAX_PORTS >= 2 + else if ((nIntFlag & TIMER_INT_FLAG_CH1) == TIMER_INT_FLAG_CH1) { + if (sv_RxBuffer[1].State == TxRxState::DMXDATA) { + sv_RxBuffer[1].State = TxRxState::IDLE; + sv_RxBuffer[1].Dmx.nSlotsInPacket |= 0x8000; + } else if (sv_RxBuffer[1].State == TxRxState::RDMDISC) { + sv_RxBuffer[1].State = TxRxState::IDLE; + sv_RxBuffer[1].Rdm.nIndex |= 0x4000; + } + } +#endif +#if DMX_MAX_PORTS >= 3 + else if ((nIntFlag & TIMER_INT_FLAG_CH2) == TIMER_INT_FLAG_CH2) { + if (sv_RxBuffer[2].State == TxRxState::DMXDATA) { + sv_RxBuffer[2].State = TxRxState::IDLE; + sv_RxBuffer[2].Dmx.nSlotsInPacket |= 0x8000; + } else if (sv_RxBuffer[2].State == TxRxState::RDMDISC) { + sv_RxBuffer[2].State = TxRxState::IDLE; + sv_RxBuffer[2].Rdm.nIndex |= 0x4000; + } + } +#endif +#if DMX_MAX_PORTS >= 4 + else if ((nIntFlag & TIMER_INT_FLAG_CH3) == TIMER_INT_FLAG_CH3) { + if (sv_RxBuffer[3].State == TxRxState::DMXDATA) { + sv_RxBuffer[3].State = TxRxState::IDLE; + sv_RxBuffer[3].Dmx.nSlotsInPacket |= 0x8000; + } else if (sv_RxBuffer[3].State == TxRxState::RDMDISC) { + sv_RxBuffer[3].State = TxRxState::IDLE; + sv_RxBuffer[3].Rdm.nIndex |= 0x4000; + } + } +#endif + timer_interrupt_flag_clear(TIMER2, nIntFlag); +} + +void TIMER3_IRQHandler() { + const auto nIntFlag = TIMER_INTF(TIMER3); +#if DMX_MAX_PORTS >= 5 + if ((nIntFlag & TIMER_INT_FLAG_CH0) == TIMER_INT_FLAG_CH0) { + if (sv_RxBuffer[4].State == TxRxState::DMXDATA) { + sv_RxBuffer[4].State = TxRxState::IDLE; + sv_RxBuffer[4].Dmx.nSlotsInPacket |= 0x8000; + } else if (sv_RxBuffer[4].State == TxRxState::RDMDISC) { + sv_RxBuffer[4].State = TxRxState::IDLE; + sv_RxBuffer[4].Rdm.nIndex |= 0x4000; + } + } +# if DMX_MAX_PORTS >= 6 + else if ((nIntFlag & TIMER_INT_FLAG_CH1) == TIMER_INT_FLAG_CH1) { + if (sv_RxBuffer[5].State == TxRxState::DMXDATA) { + sv_RxBuffer[5].State = TxRxState::IDLE; + sv_RxBuffer[5].Dmx.nSlotsInPacket |= 0x8000; + } else if (sv_RxBuffer[5].State == TxRxState::RDMDISC) { + sv_RxBuffer[5].State = TxRxState::IDLE; + sv_RxBuffer[5].Rdm.nIndex |= 0x4000; + } + } +# endif +# if DMX_MAX_PORTS >= 7 + else if ((nIntFlag & TIMER_INT_FLAG_CH2) == TIMER_INT_FLAG_CH2) { + if (sv_RxBuffer[6].State == TxRxState::DMXDATA) { + sv_RxBuffer[6].State = TxRxState::IDLE; + sv_RxBuffer[6].Dmx.nSlotsInPacket |= 0x8000; + } else if (sv_RxBuffer[6].State == TxRxState::RDMDISC) { + sv_RxBuffer[6].State = TxRxState::IDLE; + sv_RxBuffer[6].Rdm.nIndex |= 0x4000; + } + } +# endif +# if DMX_MAX_PORTS == 8 + else if ((nIntFlag & TIMER_INT_FLAG_CH3) == TIMER_INT_FLAG_CH3) { + if (sv_RxBuffer[7].State == TxRxState::DMXDATA) { + sv_RxBuffer[7].State = TxRxState::IDLE; + sv_RxBuffer[7].Dmx.nSlotsInPacket |= 0x8000; + } else if (sv_RxBuffer[7].State == TxRxState::RDMDISC) { + sv_RxBuffer[7].State = TxRxState::IDLE; + sv_RxBuffer[7].Rdm.nIndex |= 0x4000; + } + } +# endif +#endif + timer_interrupt_flag_clear(TIMER3, nIntFlag); +} +#endif +} + +extern "C" { +/* + * USART 0 + */ +#if defined (DMX_USE_USART0) +# if defined (GD32F4XX) || defined (GD32H7XX) +void DMA1_Channel7_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::USART0_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART0_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +# else +void DMA0_Channel3_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::USART0_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_0 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART0_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +# endif +#endif +/* + * USART 1 + */ +#if defined (DMX_USE_USART1) +void DMA0_Channel6_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::USART1_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::USART1_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_1 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::USART1_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART1_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +#endif +/* + * USART 2 + */ +#if defined (DMX_USE_USART2) +# if defined (GD32F4XX) || defined (GD32H7XX) +void DMA0_Channel3_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::USART2_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART2_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +# else +void DMA0_Channel1_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::USART2_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_2 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART2_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +# endif +#endif +/* + * UART 3 + */ +#if defined (DMX_USE_UART3) +# if defined (GD32F4XX) || defined (GD32H7XX) +void DMA0_Channel4_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::UART3_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART3_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +# else +void DMA1_Channel4_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::UART3_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER1, TIMER_CH_3 , TIMER_CNT(TIMER1) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART3_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +# endif +#endif +/* + * UART 4 + */ +#if defined (DMX_USE_UART4) +# if defined (GD32F20X) +void DMA1_Channel3_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::UART4_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART4_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +# endif +# if defined (GD32F4XX) || defined (GD32H7XX) +void DMA0_Channel7_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::UART4_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_0 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::DMXINTER; + } + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART4_PORT].Dmx.Sent++; +#endif + + gd32_dma_interrupt_flag_clear(); +} +# endif +#endif +/* + * USART 5 + */ +#if defined (DMX_USE_USART5) +void DMA1_Channel6_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::USART5_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::USART5_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_1 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::USART5_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::USART5_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +#endif +/* + * UART 6 + */ +#if defined (DMX_USE_UART6) +# if defined (GD32F20X) +void DMA1_Channel4_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::UART6_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART6_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +# endif +# if defined (GD32F4XX) || defined (GD32H7XX) +void DMA0_Channel1_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::UART6_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_2 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART6_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +# endif +#endif +/* + * UART 7 + */ +#if defined (DMX_USE_UART7) +# if defined (GD32F20X) +void DMA1_Channel3_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::UART7_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART7_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +# endif +# if defined (GD32F4XX) || defined (GD32H7XX) +void DMA0_Channel0_IRQHandler() { + if (gd32_dma_interrupt_flag_get()) { + gd32_dma_interrupt_disable(); + + if (s_TxBuffer[dmx::config::UART7_PORT].outputStyle == dmx::OutputStyle::DELTA) { + s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::IDLE; + } else { + timer_channel_output_pulse_value_config(TIMER4, TIMER_CH_3 , TIMER_CNT(TIMER4) + s_nDmxTransmitInterTime); + s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::DMXINTER; + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[dmx::config::UART7_PORT].Dmx.Sent++; +#endif + } + + gd32_dma_interrupt_flag_clear(); +} +# endif +#endif +} + +static void uart_dmx_config(const uint32_t usart_periph) { + gd32_uart_begin(usart_periph, 250000U, GD32_UART_BITS_8, GD32_UART_PARITY_NONE, GD32_UART_STOP_2BITS); +} + +Dmx *Dmx::s_pThis; + +Dmx::Dmx() { + DEBUG_ENTRY + + assert(s_pThis == nullptr); + s_pThis = this; + + s_nDmxTransmitBreakTime = m_nDmxTransmitBreakTime; + s_nDmxTransmitMabTime = m_nDmxTransmitMabTime; + s_nDmxTransmitInterTime = dmx::transmit::PERIOD_DEFAULT - s_nDmxTransmitBreakTime - s_nDmxTransmitMabTime - (dmx::max::CHANNELS * 44) - 44; + + for (auto i = 0; i < DMX_MAX_PORTS; i++) { +#if defined (GPIO_INIT) + gpio_init(s_DirGpio[i].nPort, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, s_DirGpio[i].nPin); +#else + gpio_mode_set(s_DirGpio[i].nPort, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, s_DirGpio[i].nPin); + gpio_output_options_set(s_DirGpio[i].nPort, GPIO_OTYPE_PP, GPIO_OSPEED, s_DirGpio[i].nPin); + gpio_af_set(s_DirGpio[i].nPort, GPIO_AF_0, s_DirGpio[i].nPin); +#endif + m_nDmxTransmissionLength[i] = dmx::max::CHANNELS; + SetPortDirection(i, PortDirection::INP, false); + sv_RxBuffer[i].State = TxRxState::IDLE; + s_TxBuffer[i].State = TxRxState::IDLE; + s_TxBuffer[i].outputStyle = dmx::OutputStyle::DELTA; + ClearData(i); + } + + usart_dma_config(); // DMX Transmit +#if defined (DMX_USE_USART0) || defined (DMX_USE_USART1) || defined (DMX_USE_USART2) || defined (DMX_USE_UART3) + timer1_config(); // DMX Transmit -> USART0, USART1, USART2, UART3 +#endif +#if defined (DMX_USE_UART4) || defined (DMX_USE_USART5) || defined (DMX_USE_UART6) || defined (DMX_USE_UART7) + timer4_config(); // DMX Transmit -> UART4, USART5, UART6, UART7 +#endif +#if !defined(CONFIG_DMX_TRANSMIT_ONLY) + timer2_config(); // DMX Receive -> Slot time-out Port 0,1,2,3 + timer3_config(); // DMX Receive -> Slot time-out Port 4,5,6,7 +#endif + +#if defined (DMX_USE_USART0) + uart_dmx_config(USART0); + NVIC_SetPriority(USART0_IRQn, 0); + NVIC_EnableIRQ(USART0_IRQn); +#endif +#if defined (DMX_USE_USART1) + uart_dmx_config(USART1); + NVIC_SetPriority(USART1_IRQn, 0); + NVIC_EnableIRQ(USART1_IRQn); +#endif +#if defined (DMX_USE_USART2) + uart_dmx_config(USART2); + NVIC_SetPriority(USART2_IRQn, 0); + NVIC_EnableIRQ(USART2_IRQn); +#endif +#if defined (DMX_USE_UART3) + uart_dmx_config(UART3); + NVIC_SetPriority(UART3_IRQn, 0); + NVIC_EnableIRQ(UART3_IRQn); +#endif +#if defined (DMX_USE_UART4) + uart_dmx_config(UART4); + NVIC_SetPriority(UART4_IRQn, 0); + NVIC_EnableIRQ(UART4_IRQn); +#endif +#if defined (DMX_USE_USART5) + uart_dmx_config(USART5); + NVIC_SetPriority(USART5_IRQn, 0); + NVIC_EnableIRQ(USART5_IRQn); +#endif +#if defined (DMX_USE_UART6) + uart_dmx_config(UART6); + NVIC_SetPriority(UART6_IRQn, 0); + NVIC_EnableIRQ(UART6_IRQn); +#endif +#if defined (DMX_USE_UART7) + uart_dmx_config(UART7); + NVIC_SetPriority(UART7_IRQn, 0); + NVIC_EnableIRQ(UART7_IRQn); +#endif + + DEBUG_EXIT +} + +void Dmx::SetPortDirection(const uint32_t nPortIndex, PortDirection portDirection, bool bEnableData) { + assert(nPortIndex < dmx::config::max::PORTS); + + const auto nUart = dmx_port_to_uart(nPortIndex); + + if (m_dmxPortDirection[nPortIndex] != portDirection) { + m_dmxPortDirection[nPortIndex] = portDirection; + + StopData(nUart, nPortIndex); + + if (portDirection == PortDirection::OUTP) { + GPIO_BOP(s_DirGpio[nPortIndex].nPort) = s_DirGpio[nPortIndex].nPin; + } else if (portDirection == PortDirection::INP) { + GPIO_BC(s_DirGpio[nPortIndex].nPort) = s_DirGpio[nPortIndex].nPin; + } else { + assert(0); + } + } else if (!bEnableData) { + StopData(nUart, nPortIndex); + } + + if (bEnableData) { + StartData(nUart, nPortIndex); + } +} + +void Dmx::ClearData(const uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); + + auto *p = &s_TxBuffer[nPortIndex]; + p->dmx.nLength = 513; // Including START Code + memset(p->dmx.data, 0, dmx::buffer::SIZE); +} + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) +volatile dmx::TotalStatistics& Dmx::GetTotalStatistics(const uint32_t nPortIndex) { + sv_TotalStatistics[nPortIndex].Dmx.Received = sv_nRxDmxPackets[nPortIndex].nCount; + return sv_TotalStatistics[nPortIndex]; +} +#endif + +void Dmx::StartDmxOutput(const uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); + const auto nUart = dmx_port_to_uart(nPortIndex); + + /* + * USART_FLAG_TC is set after power on. + * The flag is cleared by DMA interrupt when maximum slots - 1 are transmitted. + */ + + //TODO Do we need a timeout just to be safe? + while (SET != usart_flag_get(nUart, USART_FLAG_TC)) + ; + + switch (nUart) { + /* TIMER 1 */ +#if defined (DMX_USE_USART0) + case USART0: + gd32_gpio_mode_output(); + GPIO_BC(USART0_GPIOx) = USART0_TX_GPIO_PINx; + TIMER_CH0CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime; + s_TxBuffer[dmx::config::USART0_PORT].State = TxRxState::BREAK; + return; + break; +#endif +#if defined (DMX_USE_USART1) + case USART1: + gd32_gpio_mode_output(); + GPIO_BC(USART1_GPIOx) = USART1_TX_GPIO_PINx; + TIMER_CH1CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime; + s_TxBuffer[dmx::config::USART1_PORT].State = TxRxState::BREAK; + return; + break; +#endif +#if defined (DMX_USE_USART2) + case USART2: + gd32_gpio_mode_output(); + GPIO_BC(USART2_GPIOx) = USART2_TX_GPIO_PINx; + TIMER_CH2CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime; + s_TxBuffer[dmx::config::USART2_PORT].State = TxRxState::BREAK; + return; + break; +#endif +#if defined (DMX_USE_UART3) + case UART3: + gd32_gpio_mode_output(); + GPIO_BC(UART3_GPIOx) = UART3_TX_GPIO_PINx; + TIMER_CH3CV(TIMER1) = TIMER_CNT(TIMER1) + s_nDmxTransmitBreakTime; + s_TxBuffer[dmx::config::UART3_PORT].State = TxRxState::BREAK; + return; + break; +#endif + /* TIMER 4 */ +#if defined (DMX_USE_UART4) + case UART4: + gd32_gpio_mode_output(); + GPIO_BC(UART4_TX_GPIOx) = UART4_TX_GPIO_PINx; + TIMER_CH0CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime; + s_TxBuffer[dmx::config::UART4_PORT].State = TxRxState::BREAK; + return; + break; +#endif +#if defined (DMX_USE_USART5) + case USART5: + gd32_gpio_mode_output(); + GPIO_BC(USART5_GPIOx) = USART5_TX_GPIO_PINx; + TIMER_CH1CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime; + s_TxBuffer[dmx::config::USART5_PORT].State = TxRxState::BREAK; + return; + break; +#endif +#if defined (DMX_USE_UART6) + case UART6: + gd32_gpio_mode_output(); + GPIO_BC(UART6_GPIOx) = UART6_TX_GPIO_PINx; + TIMER_CH2CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime; + s_TxBuffer[dmx::config::UART6_PORT].State = TxRxState::BREAK; + return; + break; +#endif +#if defined (DMX_USE_UART7) + case UART7: + gd32_gpio_mode_output(); + GPIO_BC(UART7_GPIOx) = UART7_TX_GPIO_PINx; + TIMER_CH3CV(TIMER4) = TIMER_CNT(TIMER4) + s_nDmxTransmitBreakTime; + s_TxBuffer[dmx::config::UART7_PORT].State = TxRxState::BREAK; + return; + break; +#endif + default: + assert(0); + __builtin_unreachable(); + break; + } + + assert(0); + __builtin_unreachable(); +} + + +void Dmx::StopData(const uint32_t nUart, const uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); + + if (sv_PortState[nPortIndex] == PortState::IDLE) { + return; + } + + sv_PortState[nPortIndex] = PortState::IDLE; + + if (m_dmxPortDirection[nPortIndex] == PortDirection::OUTP) { + do { + if (s_TxBuffer[nPortIndex].State == dmx::TxRxState::DMXINTER) { + gd32_usart_flag_clear(nUart); + do { + __DMB(); + } while (!gd32_usart_flag_get(nUart)); + + s_TxBuffer[nPortIndex].State = dmx::TxRxState::IDLE; + } + } while (s_TxBuffer[nPortIndex].State != dmx::TxRxState::IDLE); + + return; + } + + if (m_dmxPortDirection[nPortIndex] == PortDirection::INP) { + usart_interrupt_disable(nUart, USART_INT_RBNE); + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + +#if !defined(CONFIG_DMX_TRANSMIT_ONLY) + switch (nPortIndex) { + case 0: + TIMER_DMAINTEN(TIMER2) &= (~TIMER_INT_CH0); + break; +#if DMX_MAX_PORTS >= 2 + case 1: + TIMER_DMAINTEN(TIMER2) &= (~TIMER_INT_CH1); + break; +#endif +#if DMX_MAX_PORTS >= 3 + case 2: + TIMER_DMAINTEN(TIMER2) &= (~TIMER_INT_CH2); + break; +#endif +#if DMX_MAX_PORTS >= 4 + case 3: + TIMER_DMAINTEN(TIMER2) &= (~TIMER_INT_CH3); + break; +#endif +#if DMX_MAX_PORTS >= 5 + case 4: + TIMER_DMAINTEN(TIMER3) &= (~TIMER_INT_CH0); + break; +#endif +#if DMX_MAX_PORTS >= 6 + case 5: + TIMER_DMAINTEN(TIMER3) &= (~TIMER_INT_CH1); + break; +#endif +#if DMX_MAX_PORTS >= 7 + case 6: + TIMER_DMAINTEN(TIMER3) &= (~TIMER_INT_CH2); + break; +#endif +#if DMX_MAX_PORTS == 8 + case 7: + TIMER_DMAINTEN(TIMER3) &= (~TIMER_INT_CH3); + break; +#endif + default: + assert(0); + __builtin_unreachable(); + break; + } +#endif + return; + } + + assert(0); + __builtin_unreachable(); +} + +// DMX Send + +void Dmx::SetDmxBreakTime(uint32_t nBreakTime) { + s_nDmxTransmitBreakTime = std::max(transmit::BREAK_TIME_MIN, nBreakTime); + SetDmxPeriodTime(m_nDmxTransmitPeriodRequested); +} + +void Dmx::SetDmxMabTime(uint32_t nMabTime) { + s_nDmxTransmitMabTime = std::max(transmit::MAB_TIME_MIN, nMabTime); + SetDmxPeriodTime(m_nDmxTransmitPeriodRequested); +} + +void Dmx::SetDmxPeriodTime(uint32_t nPeriod) { + m_nDmxTransmitPeriodRequested = nPeriod; + + auto nLengthMax = s_TxBuffer[0].dmx.nLength; + + for (uint32_t nPortIndex = 1; nPortIndex < dmx::config::max::PORTS; nPortIndex++) { + const auto nLength = s_TxBuffer[nPortIndex].dmx.nLength; + if (nLength > nLengthMax) { + nLengthMax = nLength; + } + } + + auto nPackageLengthMicroSeconds = s_nDmxTransmitBreakTime + s_nDmxTransmitMabTime + (nLengthMax * 44U); + + // The GD32F4xx/GD32H7XX Timer 1 has a 32-bit counter +#if defined(GD32F4XX) || defined (GD32H7XX) +#else + if (nPackageLengthMicroSeconds > (static_cast(~0) - 44U)) { + s_nDmxTransmitBreakTime = std::min(transmit::BREAK_TIME_TYPICAL, s_nDmxTransmitBreakTime); + s_nDmxTransmitMabTime = transmit::MAB_TIME_MIN; + nPackageLengthMicroSeconds = s_nDmxTransmitBreakTime + s_nDmxTransmitMabTime + (nLengthMax * 44U); + } +#endif + + if (nPeriod != 0) { + if (nPeriod < nPackageLengthMicroSeconds) { + m_nDmxTransmitPeriod = std::max(transmit::BREAK_TO_BREAK_TIME_MIN, nPackageLengthMicroSeconds + 44U); + } else { + m_nDmxTransmitPeriod = nPeriod; + } + } else { + m_nDmxTransmitPeriod = std::max(transmit::BREAK_TO_BREAK_TIME_MIN, nPackageLengthMicroSeconds + 44U); + } + + s_nDmxTransmitInterTime = m_nDmxTransmitPeriod - nPackageLengthMicroSeconds; + + m_nDmxTransmitBreakTime = s_nDmxTransmitBreakTime; + m_nDmxTransmitMabTime = s_nDmxTransmitMabTime; + + DEBUG_PRINTF("nPeriod=%u, nLengthMax=%u, m_nDmxTransmitPeriod=%u, nPackageLengthMicroSeconds=%u -> s_nDmxTransmitInterTime=%u", nPeriod, nLengthMax, m_nDmxTransmitPeriod, nPackageLengthMicroSeconds, s_nDmxTransmitInterTime); +} + +void Dmx::SetDmxSlots(uint16_t nSlots) { + if ((nSlots >= 2) && (nSlots <= dmx::max::CHANNELS)) { + m_nDmxTransmitSlots = nSlots; + + for (uint32_t i = 0; i < dmx::config::max::PORTS; i++) { + m_nDmxTransmissionLength[i] = std::min(m_nDmxTransmissionLength[i], static_cast(nSlots)); + } + + SetDmxPeriodTime(m_nDmxTransmitPeriodRequested); + } +} + +#include + +void Dmx::SetOutputStyle(const uint32_t nPortIndex, const dmx::OutputStyle outputStyle) { + assert(nPortIndex < dmx::config::max::PORTS); + s_TxBuffer[nPortIndex].outputStyle = outputStyle; + + if (outputStyle == dmx::OutputStyle::CONTINOUS) { + if (!m_bHasContinuosOutput) { + m_bHasContinuosOutput = true; + if (m_dmxPortDirection[nPortIndex] == dmx::PortDirection::OUTP) { + StartDmxOutput(nPortIndex); + } + return; + } + + for (size_t nIndex = 0; nIndex < dmx::config::max::PORTS; nIndex++) { + if ((s_TxBuffer[nIndex].outputStyle == dmx::OutputStyle::CONTINOUS) && (m_dmxPortDirection[nIndex] == dmx::PortDirection::OUTP)) { + const auto nUart = dmx_port_to_uart(nIndex); + StopData(nUart, nIndex); + } + } + + for (size_t nIndex = 0; nIndex < dmx::config::max::PORTS; nIndex++) { + if ((s_TxBuffer[nIndex].outputStyle == dmx::OutputStyle::CONTINOUS) && (m_dmxPortDirection[nIndex] == dmx::PortDirection::OUTP)) { + StartDmxOutput(nIndex); + } + } + } else { + m_bHasContinuosOutput = false; + for (size_t nIndex = 0; nIndex < dmx::config::max::PORTS; nIndex++) { + if (s_TxBuffer[nIndex].outputStyle == dmx::OutputStyle::CONTINOUS) { + m_bHasContinuosOutput = true; + return; + } + } + } +} + +dmx::OutputStyle Dmx::GetOutputStyle(const uint32_t nPortIndex) const { + assert(nPortIndex < dmx::config::max::PORTS); + return s_TxBuffer[nPortIndex].outputStyle; +} + +void Dmx::SetSendData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength) { + assert(nPortIndex < dmx::config::max::PORTS); + + auto &p = s_TxBuffer[nPortIndex]; + auto *pDst = p.dmx.data; + + nLength = std::min(nLength, static_cast(m_nDmxTransmitSlots)); + p.dmx.nLength = static_cast(nLength + 1); + + memcpy(pDst, pData, nLength); + + if (nLength != m_nDmxTransmissionLength[nPortIndex]) { + m_nDmxTransmissionLength[nPortIndex] = nLength; + SetDmxPeriodTime(m_nDmxTransmitPeriodRequested); + } +} + +void Dmx::SetSendDataWithoutSC(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength) { + assert(nPortIndex < dmx::config::max::PORTS); + + auto &p = s_TxBuffer[nPortIndex]; + auto *pDst = p.dmx.data; + + nLength = std::min(nLength, static_cast(m_nDmxTransmitSlots)); + p.dmx.nLength = static_cast(nLength + 1); + p.dmx.bDataPending = true; + + pDst[0] = START_CODE; + memcpy(&pDst[1], pData, nLength); + + if (nLength != m_nDmxTransmissionLength[nPortIndex]) { + m_nDmxTransmissionLength[nPortIndex] = nLength; + SetDmxPeriodTime(m_nDmxTransmitPeriodRequested); + } +} + +void Dmx::Blackout() { + DEBUG_ENTRY + + for (uint32_t nPortIndex = 0; nPortIndex < DMX_MAX_PORTS; nPortIndex++) { + if (m_dmxPortDirection[nPortIndex] == dmx::PortDirection::OUTP) { + const auto nUart = dmx_port_to_uart(nPortIndex); + + StopData(nUart, nPortIndex); + ClearData(nPortIndex); + StartData(nUart, nPortIndex); + } + } + + DEBUG_EXIT +} + +void Dmx::FullOn() { + DEBUG_ENTRY + + for (uint32_t nPortIndex = 0; nPortIndex < DMX_MAX_PORTS; nPortIndex++) { + if (m_dmxPortDirection[nPortIndex] == dmx::PortDirection::OUTP) { + const auto nUart = dmx_port_to_uart(nPortIndex); + + StopData(nUart, nPortIndex); + + auto *p = &s_TxBuffer[nPortIndex]; + auto *p16 = reinterpret_cast(p->dmx.data); + + for (auto i = 0; i < dmx::buffer::SIZE / 2; i++) { + *p16++ = UINT16_MAX; + } + + p->dmx.data[0] = dmx::START_CODE; + p->dmx.nLength = 513; + + StartData(nUart, nPortIndex); + } + } + + DEBUG_EXIT +} + +void Dmx::StartOutput(const uint32_t nPortIndex) { + if ((sv_PortState[nPortIndex] == dmx::PortState::TX) + && (s_TxBuffer[nPortIndex].outputStyle == dmx::OutputStyle::DELTA) + && (s_TxBuffer[nPortIndex].State == dmx::TxRxState::IDLE)) { + StartDmxOutput(nPortIndex); + } +} + +void Dmx::Sync() { + logic_analyzer::ch0_set(); + + for (uint32_t nPortIndex = 0; nPortIndex < dmx::config::max::PORTS; nPortIndex++) { + auto &txBuffer = s_TxBuffer[nPortIndex]; + + if (!txBuffer.dmx.bDataPending) { + continue; + } + + txBuffer.dmx.bDataPending = false; + + if ((sv_PortState[nPortIndex] == dmx::PortState::TX)) { + if ((txBuffer.outputStyle == dmx::OutputStyle::DELTA) && (txBuffer.State == dmx::TxRxState::IDLE)) { + logic_analyzer::ch1_set(); + StartDmxOutput(nPortIndex); + logic_analyzer::ch1_clear(); + } + } + } + + logic_analyzer::ch0_clear(); +} + +void Dmx::StartData(const uint32_t nUart, const uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); + assert(sv_PortState[nPortIndex] == PortState::IDLE); + + if (m_dmxPortDirection[nPortIndex] == dmx::PortDirection::OUTP) { + sv_PortState[nPortIndex] = PortState::TX; + return; + } + + if (m_dmxPortDirection[nPortIndex] == dmx::PortDirection::INP) { + sv_RxBuffer[nPortIndex].State = TxRxState::IDLE; + + while (RESET == usart_flag_get(nUart, USART_FLAG_TBE)) + ; + + usart_interrupt_flag_clear(nUart, USART_INT_FLAG_RBNE); + usart_interrupt_enable(nUart, USART_INT_RBNE); + + sv_PortState[nPortIndex] = PortState::RX; + +#if !defined(CONFIG_DMX_TRANSMIT_ONLY) + switch (nPortIndex) { + case 0: + TIMER_DMAINTEN(TIMER2) |= TIMER_INT_CH0; + break; +#if DMX_MAX_PORTS >= 2 + case 1: + TIMER_DMAINTEN(TIMER2) |= TIMER_INT_CH1; + break; +#endif +#if DMX_MAX_PORTS >= 3 + case 2: + TIMER_DMAINTEN(TIMER2) |= TIMER_INT_CH2; + break; +#endif +#if DMX_MAX_PORTS >= 4 + case 3: + TIMER_DMAINTEN(TIMER2) |= TIMER_INT_CH3; + break; +#endif +#if DMX_MAX_PORTS >= 5 + case 4: + TIMER_DMAINTEN(TIMER3) |= TIMER_INT_CH0; + break; +#endif +#if DMX_MAX_PORTS >= 6 + case 5: + TIMER_DMAINTEN(TIMER3) |= TIMER_INT_CH1; + break; +#endif +#if DMX_MAX_PORTS >= 7 + case 6: + TIMER_DMAINTEN(TIMER3) |= TIMER_INT_CH2; + break; +#endif +#if DMX_MAX_PORTS == 8 + case 7: + TIMER_DMAINTEN(TIMER3) |= TIMER_INT_CH3; + break; +#endif + default: + assert(0); + __builtin_unreachable(); + break; + } +#endif + return; + } + + assert(0); + __builtin_unreachable(); +} + + +// DMX Receive + +const uint8_t *Dmx::GetDmxChanged([[maybe_unused]] uint32_t nPortIndex) { +#if !defined(CONFIG_DMX_TRANSMIT_ONLY) + const auto *p = GetDmxAvailable(nPortIndex); + + if (p == nullptr) { + return nullptr; + } + + const auto *pSrc16 = reinterpret_cast(p); + auto *pDst16 = reinterpret_cast(&sv_RxDmxPrevious[nPortIndex][0]); + + auto isChanged = false; + + for (auto i = 0; i < buffer::SIZE / 2; i++) { + if (*pDst16 != *pSrc16) { + *pDst16 = *pSrc16; + isChanged = true; + } + pDst16++; + pSrc16++; + } + + return (isChanged ? p : nullptr); +#else + return nullptr; +#endif +} + +const uint8_t *Dmx::GetDmxAvailable([[maybe_unused]] uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); +#if !defined(CONFIG_DMX_TRANSMIT_ONLY) + if ((sv_RxBuffer[nPortIndex].Dmx.nSlotsInPacket & 0x8000) != 0x8000) { + return nullptr; + } + + sv_RxBuffer[nPortIndex].Dmx.nSlotsInPacket &= ~0x8000; + sv_RxBuffer[nPortIndex].Dmx.nSlotsInPacket--; // Remove SC from length + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[nPortIndex].Dmx.Received++; +#endif + return const_cast(sv_RxBuffer[nPortIndex].Dmx.data); +#else + return nullptr; +#endif +} + +const uint8_t *Dmx::GetDmxCurrentData(const uint32_t nPortIndex) { + return const_cast(sv_RxBuffer[nPortIndex].Dmx.data); +} + +uint32_t Dmx::GetDmxUpdatesPerSecond([[maybe_unused]] uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); +#if !defined(CONFIG_DMX_TRANSMIT_ONLY) + return sv_nRxDmxPackets[nPortIndex].nPerSecond; +#else + return 0; +#endif +} + +// RDM Send + +void Dmx::RdmSendRaw(const uint32_t nPortIndex, const uint8_t* pRdmData, uint32_t nLength) { + assert(nPortIndex < dmx::config::max::PORTS); + assert(pRdmData != nullptr); + assert(nLength != 0); + + const auto nUart = dmx_port_to_uart(nPortIndex); + + while (SET != usart_flag_get(nUart, USART_FLAG_TC)) + ; + + switch (nUart) { +#if defined (DMX_USE_USART0) + case USART0: + gd32_gpio_mode_output(); + GPIO_BC(USART0_GPIOx) = USART0_TX_GPIO_PINx; + break; +#endif +#if defined (DMX_USE_USART1) + case USART1: + gd32_gpio_mode_output(); + GPIO_BC(USART1_GPIOx) = USART1_TX_GPIO_PINx; + break; +#endif +#if defined (DMX_USE_USART2) + case USART2: + gd32_gpio_mode_output(); + GPIO_BC(USART2_GPIOx) = USART2_TX_GPIO_PINx; + break; +#endif +#if defined (DMX_USE_UART3) + case UART3: + gd32_gpio_mode_output(); + GPIO_BC(UART3_GPIOx) = UART3_TX_GPIO_PINx; + break; +#endif +#if defined (DMX_USE_UART4) + case UART4: + gd32_gpio_mode_output(); + GPIO_BC(UART4_TX_GPIOx) = UART4_TX_GPIO_PINx; + break; +#endif +#if defined (DMX_USE_USART5) + case USART5: + gd32_gpio_mode_output(); + GPIO_BC(USART5_GPIOx) = USART5_TX_GPIO_PINx; + break; +#endif +#if defined (DMX_USE_UART6) + case UART6: + gd32_gpio_mode_output(); + GPIO_BC(UART6_GPIOx) = UART6_TX_GPIO_PINx; + break; +#endif +#if defined (DMX_USE_UART7) + case UART7: + gd32_gpio_mode_output(); + GPIO_BC(UART7_GPIOx) = UART7_TX_GPIO_PINx; + break; +#endif + default: + assert(0); + __builtin_unreachable(); + break; + } + + TIMER_CNT(TIMER5) = 0; + do { + __DMB(); + } while (TIMER_CNT(TIMER5) < RDM_TRANSMIT_BREAK_TIME); + + switch (nUart) { +#if defined (DMX_USE_USART0) + case USART0: + gd32_gpio_mode_af(); + break; +#endif +#if defined (DMX_USE_USART1) + case USART1: + gd32_gpio_mode_af(); + break; +#endif +#if defined (DMX_USE_USART2) + case USART2: + gd32_gpio_mode_af(); + break; +#endif +#if defined (DMX_USE_UART3) + case UART3: + gd32_gpio_mode_af(); + break; +#endif +#if defined (DMX_USE_UART4) + case UART4: + gd32_gpio_mode_af(); + break; +#endif +#if defined (DMX_USE_USART5) + case USART5: + gd32_gpio_mode_af(); + break; +#endif +#if defined (DMX_USE_UART6) + case UART6: + gd32_gpio_mode_af(); + break; +#endif +#if defined (DMX_USE_UART7) + case UART7: + gd32_gpio_mode_af(); + break; +#endif + default: + assert(0); + __builtin_unreachable(); + break; + } + + TIMER_CNT(TIMER5) = 0; + do { + __DMB(); + } while (TIMER_CNT(TIMER5) < RDM_TRANSMIT_MAB_TIME); + + for (uint32_t i = 0; i < nLength; i++) { + while (RESET == usart_flag_get(nUart, USART_FLAG_TBE)) + ; + USART_TDATA(nUart) = USART_TDATA_TDATA & pRdmData[i]; + } + + while (SET != usart_flag_get(nUart, USART_FLAG_TC)) { + static_cast(GET_BITS(USART_RDATA(nUart), 0U, 8U)); + } + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[nPortIndex].Rdm.Sent.Class++; +#endif +} + +void Dmx::RdmSendDiscoveryRespondMessage(uint32_t nPortIndex, const uint8_t *pRdmData, uint32_t nLength) { + assert(nPortIndex < dmx::config::max::PORTS); + assert(pRdmData != nullptr); + assert(nLength != 0); + + // 3.2.2 Responder Packet spacing + udelay(RDM_RESPONDER_PACKET_SPACING, gsv_RdmDataReceiveEnd); + + SetPortDirection(nPortIndex, dmx::PortDirection::OUTP, false); + + const auto nUart = dmx_port_to_uart(nPortIndex); + + for (uint32_t i = 0; i < nLength; i++) { + while (RESET == usart_flag_get(nUart, USART_FLAG_TBE)) + ; + USART_TDATA(nUart) = USART_TDATA_TDATA & pRdmData[i]; + } + + while (SET != usart_flag_get(nUart, USART_FLAG_TC)) { + static_cast(GET_BITS(USART_RDATA(nUart), 0U, 8U)); + } + + TIMER_CNT(TIMER5) = 0; + do { + __DMB(); + } while (TIMER_CNT(TIMER5) < RDM_RESPONDER_DATA_DIRECTION_DELAY); + + + SetPortDirection(nPortIndex, dmx::PortDirection::INP, true); + +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[nPortIndex].Rdm.Sent.DiscoveryResponse++; +#endif +} + +// RDM Receive + +const uint8_t *Dmx::RdmReceive(const uint32_t nPortIndex) { + assert(nPortIndex < dmx::config::max::PORTS); + + if ((sv_RxBuffer[nPortIndex].Rdm.nIndex & 0x4000) != 0x4000) { + return nullptr; + } + + sv_RxBuffer[nPortIndex].Rdm.nIndex = 0; + + const auto *p = const_cast(sv_RxBuffer[nPortIndex].Rdm.data); + + if (p[0] == E120_SC_RDM) { + const auto *pRdmCommand = reinterpret_cast(p); + + uint32_t i; + uint16_t nChecksum = 0; + + for (i = 0; i < 24; i++) { + nChecksum = static_cast(nChecksum + p[i]); + } + + for (; i < pRdmCommand->message_length; i++) { + nChecksum = static_cast(nChecksum + p[i]); + } + + if (p[i++] == static_cast(nChecksum >> 8)) { + if (p[i] == static_cast(nChecksum)) { +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[nPortIndex].Rdm.Received.Good++; +#endif + return p; + } + } +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[nPortIndex].Rdm.Received.Bad++; +#endif + return nullptr; + } else { +#if !defined (CONFIG_DMX_DISABLE_STATISTICS) + sv_TotalStatistics[nPortIndex].Rdm.Received.DiscoveryResponse++; +#endif + } + + return p; +} + +const uint8_t *Dmx::RdmReceiveTimeOut(const uint32_t nPortIndex, uint16_t nTimeOut) { + assert(nPortIndex < dmx::config::max::PORTS); + + uint8_t *p = nullptr; + TIMER_CNT(TIMER5) = 0; + + do { + if ((p = const_cast(RdmReceive(nPortIndex))) != nullptr) { + return p; + } + } while (TIMER_CNT(TIMER5) < nTimeOut); + + return nullptr; +} diff --git a/lib-dmx/src/gd32/dmx_internal.h b/lib-dmx/src/gd32/dmx_internal.h new file mode 100755 index 000000000..ce75a38d8 --- /dev/null +++ b/lib-dmx/src/gd32/dmx_internal.h @@ -0,0 +1,190 @@ +/** + * @file dmx_internal.h + * + */ +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of thnDmxDataDirecte Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef GD32_DMX_INTERNAL_H_ +#define GD32_DMX_INTERNAL_H_ + +#include +#include + +#include "gd32.h" +#include "gd32_gpio.h" +#include "gd32/dmx_config.h" + +#ifdef ALIGNED +#undef ALIGNED +#endif +#define ALIGNED __attribute__ ((aligned (4))) + +/** + * Needed for older GD32F firmware + */ +#if !defined(USART_TRANSMIT_DMA_ENABLE) +# define USART_TRANSMIT_DMA_ENABLE USART_DENT_ENABLE +#endif + +/** + * https://www.gd32-dmx.org/memory.html + */ +#if defined (GD32F20X) || defined (GD32F4XX) || defined (GD32H7XX) +# define SECTION_DMA_BUFFER __attribute__ ((section (".dmx"))) +#else +# define SECTION_DMA_BUFFER +#endif + +#if defined (GD32F4XX) || defined (GD32H7XX) +# define DMA_INTERRUPT_ENABLE (DMA_CHXCTL_FTFIE) +# define DMA_INTERRUPT_DISABLE (DMA_CHXCTL_FTFIE | DMA_CHXCTL_HTFIE | DMA_CHXFCTL_FEEIE) +# define DMA_INTERRUPT_FLAG_GET (DMA_INT_FLAG_FTF) +# define DMA_INTERRUPT_FLAG_CLEAR (DMA_INT_FLAG_FTF | DMA_INT_FLAG_TAE) +#else +# define DMA_INTERRUPT_ENABLE (DMA_INT_FTF) +# define DMA_INTERRUPT_DISABLE (DMA_INT_FTF | DMA_INT_HTF | DMA_INT_ERR) +# define DMA_INTERRUPT_FLAG_GET (DMA_INT_FLAG_FTF) +# define DMA_INTERRUPT_FLAG_CLEAR (DMA_INT_FLAG_FTF | DMA_INT_FLAG_G) +#endif + +inline uint32_t dmx_port_to_uart(const uint32_t nPort) { + switch (nPort) { +#if defined (DMX_USE_USART0) + case dmx::config::USART0_PORT: + return USART0; + break; +#endif +#if defined (DMX_USE_USART1) + case dmx::config::USART1_PORT: + return USART1; + break; +#endif +#if defined (DMX_USE_USART2) + case dmx::config::USART2_PORT: + return USART2; + break; +#endif +#if defined (DMX_USE_UART3) + case dmx::config::UART3_PORT: + return UART3; + break; +#endif +#if defined (DMX_USE_UART4) + case dmx::config::UART4_PORT: + return UART4; + break; +#endif +#if defined (DMX_USE_USART5) + case dmx::config::USART5_PORT: + return USART5; + break; +#endif +#if defined (DMX_USE_UART6) + case dmx::config::UART6_PORT: + return UART6; + break; +#endif +#if defined (DMX_USE_UART7) + case dmx::config::UART7_PORT: + return UART7; + break; +#endif + default: + assert(0); + __builtin_unreachable(); + break; + } + + assert(0); + __builtin_unreachable(); + return 0; +} + +#if defined (GD32F4XX) || defined (GD32H7XX) +constexpr uint32_t get_usart_af(const uint32_t usart_periph) { + switch (usart_periph) { +#if defined(DMX_USE_USART0) + case USART0: return USART0_GPIO_AFx; + #endif +#if defined(DMX_USE_USART1) + case USART1: + return USART1_GPIO_AFx; +#endif +#if defined(DMX_USE_USART2) + case USART2: + return USART2_GPIO_AFx; +#endif +#if defined(DMX_USE_UART3) + case UART3: return UART3_GPIO_AFx; + #endif +#if defined(DMX_USE_UART4) + case UART4: + return UART4_GPIO_AFx; +#endif +#if defined(DMX_USE_USART5) + case USART5: + return USART5_GPIO_AFx; +#endif +#if defined(DMX_USE_UART6) + case UART6: + return UART6_GPIO_AFx; +#endif +#if defined(DMX_USE_UART7) + case UART7: + return UART7_GPIO_AFx; +#endif + default: + __builtin_unreachable(); + return 0; + } + + __builtin_unreachable(); + return 0; +} + +template +inline void gd32_gpio_mode_output() { + gd32_gpio_mode_set(); +} + +template +inline void gd32_gpio_mode_af() { + gd32_gpio_mode_set(); + + constexpr uint32_t af = get_usart_af(usart_periph); + static_assert(af != 0, "Invalid USART peripheral"); + + gd32_gpio_af_set(); +} +#else +template +inline void gd32_gpio_mode_output() { + gd32_gpio_init(); +} + +template +inline void gd32_gpio_mode_af() { + gd32_gpio_init(); +} +#endif + +#endif /* GD32_DMX_INTERNAL_H_ */ diff --git a/lib-dmx/src/h3/multi/dmx.cpp b/lib-dmx/src/h3/multi/dmx.cpp index 1340bc5e7..cd127f0a7 100644 --- a/lib-dmx/src/h3/multi/dmx.cpp +++ b/lib-dmx/src/h3/multi/dmx.cpp @@ -742,7 +742,7 @@ void Dmx::StartOutput([[maybe_unused]] const uint32_t nPortIndex) { // Nothing to do here } -void Dmx::SetOutput([[maybe_unused]] const bool doForce) { +void Dmx::Sync() { // Nothing to do here } diff --git a/lib-dmx/src/h3/single/dmx.cpp b/lib-dmx/src/h3/single/dmx.cpp index b92f903c3..36e794dfd 100644 --- a/lib-dmx/src/h3/single/dmx.cpp +++ b/lib-dmx/src/h3/single/dmx.cpp @@ -51,7 +51,11 @@ #include "debug.h" -#define GPIO_ANALYZER_CH3 GPIO_EXT_18 +#define GPIO_ANALYZER_CH1 GPIO_EXT_26 +#define GPIO_ANALYZER_CH2 GPIO_EXT_24 +#define GPIO_ANALYZER_CH3 GPIO_EXT_22 +#define GPIO_ANALYZER_CH4 GPIO_EXT_18 +#define GPIO_ANALYZER_CH5 GPIO_EXT_16 extern "C" { void console_error(const char*); @@ -130,7 +134,6 @@ static uint8_t s_RdmData[RDM_DATA_BUFFER_INDEX_ENTRIES][RDM_DATA_BUFFER_SIZE] AL static volatile uint32_t sv_nRdmDiscSlotToSlot[RDM_DATA_BUFFER_INDEX_ENTRIES]; static volatile uint16_t sv_nRdmChecksum; ///< This must be uint16_t volatile uint32_t gsv_RdmDataReceiveEnd; -static volatile uint32_t sv_RdmDiscIndex; /** * Timer 0 interrupt DMX Receiver @@ -166,11 +169,11 @@ static void irq_timer0_dmx_receive(uint32_t clo) { * Timer 0 interrupt DMX Sender */ static void irq_timer0_dmx_sender([[maybe_unused]] uint32_t clo) { -// h3_gpio_set(GPIO_ANALYZER_CH1); + h3_gpio_set(GPIO_ANALYZER_CH1); switch (sv_DmxTransmitState) { case DMXINTER: -// h3_gpio_set(GPIO_ANALYZER_CH2); + h3_gpio_set(GPIO_ANALYZER_CH2); H3_TIMER->TMR0_INTV = s_DmxTransmitBreakTimeIntv; H3_TIMER->TMR0_CTRL |= (TIMER_CTRL_EN_START | TIMER_CTRL_RELOAD); @@ -179,10 +182,10 @@ static void irq_timer0_dmx_sender([[maybe_unused]] uint32_t clo) { dmb(); sv_DmxTransmitState = BREAK; -// h3_gpio_clr(GPIO_ANALYZER_CH2); + h3_gpio_clr(GPIO_ANALYZER_CH2); break; case BREAK: -// h3_gpio_set(GPIO_ANALYZER_CH3); + h3_gpio_set(GPIO_ANALYZER_CH3); H3_TIMER->TMR0_INTV = s_DmxTransmitMabTimeIntv; H3_TIMER->TMR0_CTRL |= (TIMER_CTRL_EN_START | TIMER_CTRL_RELOAD); @@ -190,10 +193,10 @@ static void irq_timer0_dmx_sender([[maybe_unused]] uint32_t clo) { dmb(); sv_DmxTransmitState = MAB; -// h3_gpio_clr(GPIO_ANALYZER_CH3); + h3_gpio_clr(GPIO_ANALYZER_CH3); break; case MAB: { -// h3_gpio_set(GPIO_ANALYZER_CH4); + h3_gpio_set(GPIO_ANALYZER_CH4); uint32_t fifo_cnt = 16; @@ -220,7 +223,7 @@ static void irq_timer0_dmx_sender([[maybe_unused]] uint32_t clo) { } } -// h3_gpio_clr(GPIO_ANALYZER_CH4); + h3_gpio_clr(GPIO_ANALYZER_CH4); } break; case DMXDATA: @@ -231,7 +234,7 @@ static void irq_timer0_dmx_sender([[maybe_unused]] uint32_t clo) { break; } -// h3_gpio_clr(GPIO_ANALYZER_CH1); + h3_gpio_clr(GPIO_ANALYZER_CH1); } /** @@ -375,7 +378,7 @@ static void fiq_dmx_in_handler(void) { * EXT_UART TX interrupt */ static void fiq_dmx_out_handler(void) { -// h3_gpio_set(GPIO_ANALYZER_CH5); + h3_gpio_set(GPIO_ANALYZER_CH5); uint32_t fifo_cnt = 16; @@ -399,7 +402,7 @@ static void fiq_dmx_out_handler(void) { } } -// h3_gpio_clr(GPIO_ANALYZER_CH5); + h3_gpio_clr(GPIO_ANALYZER_CH5); } static void __attribute__((interrupt("FIQ"))) fiq_dmx(void) { @@ -491,25 +494,37 @@ Dmx::Dmx() { h3_gpio_fsel(GPIO_EXT_12, GPIO_FSEL_OUTPUT); h3_gpio_clr(GPIO_EXT_12); // 0 = input, 1 = output -#if defined GPIO_ANALYZER_CH3 - h3_gpio_fsel(GPIO_ANALYZER_CH3, GPIO_FSEL_OUTPUT); - h3_gpio_clr(GPIO_ANALYZER_CH3); -#endif + +#define LOGIC_ANALYZER #ifdef LOGIC_ANALYZER +# if defined GPIO_ANALYZER_CH1 h3_gpio_fsel(GPIO_ANALYZER_CH1, GPIO_FSEL_OUTPUT); h3_gpio_clr(GPIO_ANALYZER_CH1); +# endif +# if defined GPIO_ANALYZER_CH2 h3_gpio_fsel(GPIO_ANALYZER_CH2, GPIO_FSEL_OUTPUT); h3_gpio_clr(GPIO_ANALYZER_CH2); +# endif +# if defined GPIO_ANALYZER_CH3 h3_gpio_fsel(GPIO_ANALYZER_CH3, GPIO_FSEL_OUTPUT); h3_gpio_clr(GPIO_ANALYZER_CH3); +# endif +# if defined GPIO_ANALYZER_CH4 h3_gpio_fsel(GPIO_ANALYZER_CH4, GPIO_FSEL_OUTPUT); h3_gpio_clr(GPIO_ANALYZER_CH4); +# endif +# if defined GPIO_ANALYZER_CH5 h3_gpio_fsel(GPIO_ANALYZER_CH5, GPIO_FSEL_OUTPUT); h3_gpio_clr(GPIO_ANALYZER_CH5); +# endif +# if defined GPIO_ANALYZER_CH6 h3_gpio_fsel(GPIO_ANALYZER_CH6, GPIO_FSEL_OUTPUT); h3_gpio_clr(GPIO_ANALYZER_CH6); +# endif +# if defined GPIO_ANALYZER_CH7 h3_gpio_fsel(GPIO_ANALYZER_CH7, GPIO_FSEL_OUTPUT); h3_gpio_clr(GPIO_ANALYZER_CH7); +# endif #endif ClearData(0); @@ -551,39 +566,23 @@ void Dmx::StartOutput(const uint32_t nPortIndex) { } } -static bool s_doForce; - -void Dmx::SetOutput(const bool doForce) { - if (doForce) { - s_doForce = true; - if ((sv_PortState == dmx::PortState::TX) && (s_OutputStyle == dmx::OutputStyle::CONTINOUS)) { - StopData(0); - } - - sv_PortState = dmx::PortState::TX; - return; - } - +void Dmx::Sync() { if (sv_PortState == dmx::PortState::TX) { - const auto b = ((s_OutputStyle == dmx::OutputStyle::CONTINOUS) && s_doForce); - if (b || ((s_OutputStyle == dmx::OutputStyle::DELTA) && (sv_DmxTransmitState == IDLE))) { + if ((s_OutputStyle == dmx::OutputStyle::DELTA) && (sv_DmxTransmitState == IDLE)) { StartDmxOutput(0); } } - - s_doForce = false; } -void Dmx::StartData(const uint32_t nPortIndex) { - DEBUG_PRINTF("nPortIndex=%u, sv_PortState=%u", nPortIndex, sv_PortState); +void Dmx::StartData([[maybe_unused]] const uint32_t nPortIndex) { assert(sv_PortState == PortState::IDLE); if (s_nPortDirection == PortDirection::OUTP) { sv_PortState = PortState::TX; - if (s_OutputStyle == dmx::OutputStyle::CONTINOUS) { - StartDmxOutput(nPortIndex); - } - } else if (s_nPortDirection == PortDirection::INP) { + return; + } + + if (s_nPortDirection == PortDirection::INP) { sv_DmxReceiveState = IDLE; irq_timer_set(IRQ_TIMER_0, irq_timer0_dmx_receive); @@ -597,10 +596,11 @@ void Dmx::StartData(const uint32_t nPortIndex) { __enable_fiq(); isb(); - } else { - assert(0); - __builtin_unreachable(); + return; } + + assert(0); + __builtin_unreachable(); } void Dmx::StopData([[maybe_unused]] const uint32_t nPortIndex) { @@ -764,8 +764,18 @@ const uint8_t* Dmx::GetDmxChanged([[maybe_unused]] uint32_t nPortIndex) { return (is_changed ? p : nullptr); } -void Dmx::SetOutputStyle([[maybe_unused]] const uint32_t nPortIndex, const dmx::OutputStyle outputStyle) { +void Dmx::SetOutputStyle(const uint32_t nPortIndex, const dmx::OutputStyle outputStyle) { + if (s_OutputStyle == outputStyle) { + return; + } + s_OutputStyle = outputStyle; + + if ((s_OutputStyle == dmx::OutputStyle::CONTINOUS) + && (s_nPortDirection == dmx::PortDirection::OUTP)) { + StopData(nPortIndex); + StartDmxOutput(nPortIndex); + } } dmx::OutputStyle Dmx::GetOutputStyle([[maybe_unused]] const uint32_t nPortIndex) const { @@ -780,7 +790,7 @@ void Dmx::SetSendData([[maybe_unused]] uint32_t nPortIndex, const uint8_t *pData } while (sv_DmxTransmitState != IDLE && sv_DmxTransmitState != DMXINTER); __builtin_prefetch(pData); - memcpy(s_DmxData[0].Data, pData, nLength); + memcpy(reinterpret_cast(s_DmxData[0].Data), pData, nLength); if (nLength != s_nDmxSendDataLength) { s_nDmxSendDataLength = nLength; @@ -933,7 +943,7 @@ void Dmx::RdmSendRaw([[maybe_unused]] uint32_t nPortIndex, const uint8_t *pRdmDa } void Dmx::RdmSendDiscoveryRespondMessage([[maybe_unused]] const uint32_t nPortIndex, const uint8_t *pRdmData, uint32_t nLength) { - DEBUG_PRINTF("nPort=%u, pRdmData=%p, nLength=%u", nPort, pRdmData, nLength); + DEBUG_PRINTF("nPortIndex=%u, pRdmData=%p, nLength=%u", nPortIndex, pRdmData, nLength); assert(nPortIndex < dmx::config::max::PORTS); assert(pRdmData != nullptr); assert(nLength != 0); From 1b010eb904f357dc5cd3eb34ab2b0a8d34b82b94 Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 16 Aug 2024 14:22:59 +0200 Subject: [PATCH 05/17] Removed get_timer.cpp --- lib-flash/src/spi/get_timer.cpp | 36 --------------------------------- lib-flash/src/spi/spi_flash.cpp | 11 +++++++++- 2 files changed, 10 insertions(+), 37 deletions(-) delete mode 100644 lib-flash/src/spi/get_timer.cpp diff --git a/lib-flash/src/spi/get_timer.cpp b/lib-flash/src/spi/get_timer.cpp deleted file mode 100644 index 3edf77d58..000000000 --- a/lib-flash/src/spi/get_timer.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file get_timer.cpp - * - */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include - -uint32_t get_timer(uint32_t base) { - if (0 == base) { - return static_cast(time(nullptr)); - } - - return static_cast(time(nullptr)) - base; -} diff --git a/lib-flash/src/spi/spi_flash.cpp b/lib-flash/src/spi/spi_flash.cpp index fe6629fad..ab0e11c2e 100644 --- a/lib-flash/src/spi/spi_flash.cpp +++ b/lib-flash/src/spi/spi_flash.cpp @@ -5,7 +5,7 @@ /* * Original code : https://github.com/martinezjavier/u-boot/blob/master/drivers/mtd/spi/spi_flash.c */ -/* Copyright (C) 2018-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,6 +33,7 @@ #include #include #include +#include #include "spi/spi_flash.h" @@ -90,6 +91,14 @@ static const struct { }; #define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN) +static uint32_t get_timer(uint32_t base) { + if (0 == base) { + return static_cast(time(nullptr)); + } + + return static_cast(time(nullptr)) - base; +} + uint32_t spi_flash_get_size() { return s_flash.size; } From 50e97fa5a9ff29dd74de21e09f702414c4d951f1 Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 16 Aug 2024 14:23:25 +0200 Subject: [PATCH 06/17] Removed get_timer.cpp --- lib-flash/src/spi/spi_flash_internal.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib-flash/src/spi/spi_flash_internal.h b/lib-flash/src/spi/spi_flash_internal.h index 1bfe9860e..06564fb26 100644 --- a/lib-flash/src/spi/spi_flash_internal.h +++ b/lib-flash/src/spi/spi_flash_internal.h @@ -2,7 +2,7 @@ * @file spi_internal.h * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@g32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -74,8 +74,6 @@ struct spi_flash { #define SPI_XFER_SPEED_HZ 6000000 ///< 6MHz -extern uint32_t get_timer(uint32_t base); //TODO Remove - extern int spi_init(); extern int spi_xfer(uint32_t bitlen, const uint8_t *dout, uint8_t *din, uint32_t flags); From db5da334a463de07449af7ed59a4c4ddfc01c0f4 Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 16 Aug 2024 14:34:29 +0200 Subject: [PATCH 07/17] #281 - Improved pixel configuration framework. This would make it possible to change the configuration at run-time (instead of the reboot). --- lib-ws28xx/include/gd32/gpio/ws28xxmulti.h | 28 +-- lib-ws28xx/include/h3/ws28xxmulti.h | 28 +-- lib-ws28xx/include/pixelconfiguration.h | 155 +++++++++++++- lib-ws28xx/include/pixelpatterns.h | 35 +++- lib-ws28xx/include/pixeltype.h | 106 ++++++++-- lib-ws28xx/include/ws28xx.h | 15 +- lib-ws28xx/include/ws28xxmulti.h | 2 +- lib-ws28xx/src/h3/ws28xx.cpp | 47 +++-- lib-ws28xx/src/h3/ws28xxmulti.cpp | 96 ++++----- lib-ws28xx/src/patterns/pixelpatterns.cpp | 25 +-- lib-ws28xx/src/pixel/ws28xx.cpp | 28 ++- lib-ws28xx/src/pixelconfiguration.cpp | 150 -------------- lib-ws28xx/src/pixeltype.cpp | 130 +++--------- .../src/ws28xxdisplay7segment.cpp | 2 +- lib-ws28xxdisplay/src/ws28xxdisplaymatrix.cpp | 8 +- lib-ws28xxdmx/include/pixeldmxconfiguration.h | 88 +++++--- lib-ws28xxdmx/include/pixeldmxparams.h | 2 +- lib-ws28xxdmx/include/pixeldmxparamsrdm.h | 2 +- lib-ws28xxdmx/include/ws28xxdmx.h | 44 +--- lib-ws28xxdmx/include/ws28xxdmxmulti.h | 68 ++----- lib-ws28xxdmx/src/dmx/ws28xxdmx.cpp | 47 +++-- .../src/dmxmulti/ws28xxdmxmulti._cpp | 189 ++++++++++++++++++ lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti.cpp | 142 +++++++------ lib-ws28xxdmx/src/params/pixeldmxparams.cpp | 62 +++--- .../src/params/pixeldmxparamsrdm.cpp | 4 + .../src/rdm/rdm_manufacturer_pid.cpp | 17 +- opi_emac_artnet_pixel/Makefile.H3 | 5 +- opi_emac_artnet_pixel/firmware/main.cpp | 19 +- opi_emac_artnet_pixel_dmx/firmware/main.cpp | 22 +- .../firmware/main.cpp | 24 +-- opi_emac_artnet_pixel_multi/firmware/main.cpp | 26 +-- .../firmware/main.cpp | 21 +- opi_emac_ddp_pixel_multi/firmware/main.cpp | 21 +- opi_emac_e131_pixel/firmware/main.cpp | 18 +- opi_emac_e131_pixel_dmx/firmware/main.cpp | 20 +- .../firmware/main.cpp | 25 +-- opi_emac_e131_pixel_multi/firmware/main.cpp | 24 +-- opi_emac_osc_pixel/firmware/main.cpp | 11 +- opi_emac_osc_pixel/lib/handler.cpp | 6 +- opi_emac_osc_pixel/lib/networkdisplay.cpp | 78 ++++++-- opi_emac_pp_pixel_multi/Makefile.H3 | 2 +- opi_emac_pp_pixel_multi/firmware/main.cpp | 19 +- rpi_wifi_artnet_pixel/firmware/main.cpp | 8 +- rpi_wifi_e131_pixel/Makefile.BCM | 2 +- rpi_wifi_e131_pixel/firmware/main.cpp | 8 +- rpi_wifi_osc_pixel/firmware/main.cpp | 8 +- rpi_wifi_osc_pixel/lib/handler.cpp | 6 +- 47 files changed, 1040 insertions(+), 853 deletions(-) mode change 100644 => 100755 lib-ws28xx/include/pixelconfiguration.h delete mode 100644 lib-ws28xx/src/pixelconfiguration.cpp create mode 100755 lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti._cpp diff --git a/lib-ws28xx/include/gd32/gpio/ws28xxmulti.h b/lib-ws28xx/include/gd32/gpio/ws28xxmulti.h index 91a532f9d..444d5744a 100644 --- a/lib-ws28xx/include/gd32/gpio/ws28xxmulti.h +++ b/lib-ws28xx/include/gd32/gpio/ws28xxmulti.h @@ -2,7 +2,7 @@ * @file ws28xxmulti.h * */ -/* Copyright (C) 2021-2022 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,13 +32,13 @@ class WS28xxMulti { public: - WS28xxMulti(PixelConfiguration& pixelConfiguration); + WS28xxMulti(); ~WS28xxMulti(); - void Print(); - - void SetPixel(const uint32_t nPortIndex, const uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue); - void SetPixel(const uint32_t nPortIndex, const uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite); + void SetColourRTZ(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); + void SetColourRTZ(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nRed, const uint8_t nGreen, const uint8_t nBlue, const uint8_t nWhite); + void SetColourWS2801(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); + void SetPixel4Bytes(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nCtrl, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); bool IsUpdating(); @@ -46,17 +46,7 @@ class WS28xxMulti { void Blackout(); void FullOn(); - pixel::Type GetType() const { - return m_PixelConfiguration.GetType(); - } - - uint32_t GetCount() const { - return m_PixelConfiguration.GetCount(); - } - - pixel::Map GetMap() const { - return m_PixelConfiguration.GetMap(); - } + void Print(); static WS28xxMulti *Get() { return s_pThis; @@ -65,12 +55,8 @@ class WS28xxMulti { private: void Setup(uint8_t nLowCode, uint8_t nHighCode); void Setup(uint32_t nFrequency); - void SetColourRTZ(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); - void SetColourWS2801(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); - void SetPixel4Bytes(const uint32_t nPortIndex, const uint32_t nPixelIndex, const uint8_t nCtrl, const uint8_t nColour1, const uint8_t nColour2, const uint8_t nColour3); private: - PixelConfiguration m_PixelConfiguration; uint32_t m_nBufSize { 0 }; static WS28xxMulti *s_pThis; diff --git a/lib-ws28xx/include/h3/ws28xxmulti.h b/lib-ws28xx/include/h3/ws28xxmulti.h index be001c29d..9f1725bc3 100644 --- a/lib-ws28xx/include/h3/ws28xxmulti.h +++ b/lib-ws28xx/include/h3/ws28xxmulti.h @@ -2,7 +2,7 @@ * @file ws28xxmulti.h * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,11 +38,17 @@ struct JamSTAPLDisplay; class WS28xxMulti { public: - WS28xxMulti(PixelConfiguration& pixelConfiguration); + WS28xxMulti(); ~WS28xxMulti(); - void SetPixel(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue); - void SetPixel(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite); + void SetColourRTZ(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nColour1, uint8_t nColour2, uint8_t nColour3) { + SetColour(nPortIndex, nPixelIndex, nColour1, nColour2, nColour3); + } + void SetColourRTZ(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite); + void SetColourWS2801(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nColour1, uint8_t nColour2, uint8_t nColour3) { + SetColour(nPortIndex, nPixelIndex, nColour1, nColour2, nColour3); + } + void SetPixel4Bytes(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite); bool IsUpdating() { return h3_spi_dma_tx_is_active(); // returns TRUE while DMA operation is active @@ -52,18 +58,6 @@ class WS28xxMulti { void Blackout(); void FullOn(); - pixel::Type GetType() const { - return m_PixelConfiguration.GetType(); - } - - uint32_t GetCount() const { - return m_PixelConfiguration.GetCount(); - } - - pixel::Map GetMap() const { - return m_PixelConfiguration.GetMap(); - } - void SetJamSTAPLDisplay(JamSTAPLDisplay *pJamSTAPLDisplay) { m_pJamSTAPLDisplay = pJamSTAPLDisplay; } @@ -78,11 +72,9 @@ class WS28xxMulti { void SetupSPI(uint32_t nSpeedHz); bool SetupCPLD(); void SetupBuffers(); - void SetPixel4Bytes(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite); void SetColour(const uint32_t nPortIndex, const uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue); private: - PixelConfiguration m_PixelConfiguration; bool m_hasCPLD { false }; uint32_t m_nBufSize { 0 }; diff --git a/lib-ws28xx/include/pixelconfiguration.h b/lib-ws28xx/include/pixelconfiguration.h old mode 100644 new mode 100755 index ef6006267..82cc8cd6a --- a/lib-ws28xx/include/pixelconfiguration.h +++ b/lib-ws28xx/include/pixelconfiguration.h @@ -2,7 +2,7 @@ * @file pixelconfiguration.h * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,13 +22,22 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/** + * Static Local Variables: + * Since C++11, the initialization of function-local static variables, is guaranteed to be thread-safe. + * This means that even if multiple threads attempt to access Get() simultaneously, + * the C++ runtime ensures that the instance is initialized only once. + */ #ifndef PIXELCONFIGURATION_H_ #define PIXELCONFIGURATION_H_ #include +#include +#include #include "pixeltype.h" + #if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) # include "gamma/gamma_tables.h" #endif @@ -37,7 +46,16 @@ class PixelConfiguration { public: - void SetType(pixel::Type Type) { + PixelConfiguration() { + DEBUG_ENTRY + + assert(s_pThis == nullptr); + s_pThis = this; + + DEBUG_EXIT + } + + void SetType(const pixel::Type Type) { m_type = Type; } @@ -69,7 +87,7 @@ class PixelConfiguration { return m_nLowCode; } - void SetHighCode(uint8_t nHighCode) { + void SetHighCode(const uint8_t nHighCode) { m_nHighCode = nHighCode; } @@ -97,6 +115,10 @@ class PixelConfiguration { return m_bIsRTZProtocol; } + uint32_t GetLedsPerPixel() const { + return m_nLedsPerPixel; + } + #if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) void SetEnableGammaCorrection(const bool doEnable) { m_bEnableGammaCorrection = doEnable; @@ -115,26 +137,141 @@ class PixelConfiguration { } #endif - void Validate(uint32_t& nLedsPerPixel); + void GetTxH(const pixel::Type type, uint8_t &nLowCode, uint8_t &nHighCode) { + nLowCode = 0xC0; + nHighCode = (type == pixel::Type::WS2812B ? 0xF8 : + (((type == pixel::Type::UCS1903) || (type == pixel::Type::UCS2903) || (type == pixel::Type::CS8812)) ? 0xFC : 0xF0)); + } + + void Validate() { + DEBUG_ENTRY + + if (m_type == pixel::Type::SK6812W) { + m_nCount = m_nCount <= static_cast(pixel::max::ledcount::RGBW) ? m_nCount : static_cast(pixel::max::ledcount::RGBW); + m_nLedsPerPixel = 4; + } else { + m_nCount = m_nCount <= static_cast(pixel::max::ledcount::RGB) ? m_nCount : static_cast(pixel::max::ledcount::RGB); + m_nLedsPerPixel = 3; + } + + if ((m_type == pixel::Type::APA102) || (m_type == pixel::Type::SK9822)){ + if (m_nGlobalBrightness > 0x1F) { + m_nGlobalBrightness = 0xFF; + } else { + m_nGlobalBrightness = 0xE0 | (m_nGlobalBrightness & 0x1F); + } + } + + if ((m_type == pixel::Type::WS2801) || (m_type == pixel::Type::APA102) || (m_type == pixel::Type::SK9822) || (m_type == pixel::Type::P9813)) { + m_bIsRTZProtocol = false; + + if (m_map == pixel::Map::UNDEFINED) { + m_map = pixel::Map::RGB; + } + + if (m_type == pixel::Type::P9813) { + if (m_nClockSpeedHz == 0) { + m_nClockSpeedHz = pixel::spi::speed::p9813::default_hz; + } else if (m_nClockSpeedHz > pixel::spi::speed::p9813::max_hz) { + m_nClockSpeedHz = pixel::spi::speed::p9813::max_hz; + } + } else { + if (m_nClockSpeedHz == 0) { + m_nClockSpeedHz = pixel::spi::speed::ws2801::default_hz; + } else if (m_nClockSpeedHz > pixel::spi::speed::ws2801::max_hz) { + m_nClockSpeedHz = pixel::spi::speed::ws2801::max_hz; + } + } + } else { + m_bIsRTZProtocol = true; + + if (m_type == pixel::Type::UNDEFINED) { + m_type = pixel::Type::WS2812B; + } + + if (m_map == pixel::Map::UNDEFINED) { + m_map = pixel::pixel_get_map(m_type); + } + + if (m_nLowCode >= m_nHighCode) { + m_nLowCode = 0; + m_nHighCode = 0; + } + + uint8_t nLowCode, nHighCode; + + GetTxH(m_type, nLowCode, nHighCode); + + if (m_nLowCode == 0) { + m_nLowCode = nLowCode; + } + + if (m_nHighCode == 0) { + m_nHighCode = nHighCode; + } + + m_nClockSpeedHz = 6400000; // 6.4MHz / 8 bits = 800Hz + } + +#if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + if (m_bEnableGammaCorrection) { + if (m_nGammaValue == 0) { + m_pGammaTable = gamma::get_table_default(m_type); + } else { + m_pGammaTable = gamma::get_table(m_nGammaValue); + } + } else { + m_pGammaTable = gamma10_0; + } +#endif + + DEBUG_EXIT + } + + void Print() { + puts("Pixel configuration"); + printf(" Type : %s [%d] <%d leds/pixel>\n", pixel::pixel_get_type(m_type), static_cast(m_type), static_cast(m_nLedsPerPixel)); + printf(" Count : %d\n", m_nCount); - void Print(); + if (m_bIsRTZProtocol) { + printf(" Mapping : %s [%d]\n", pixel::pixel_get_map(m_map), static_cast(m_map)); + printf(" T0H : %.2f [0x%X]\n", pixel::pixel_convert_TxH(m_nLowCode), m_nLowCode); + printf(" T1H : %.2f [0x%X]\n", pixel::pixel_convert_TxH(m_nHighCode), m_nHighCode); + } else { + if ((m_type == pixel::Type::APA102) || (m_type == pixel::Type::SK9822)){ + printf(" GlobalBrightness: %u\n", m_nGlobalBrightness); + } + } - static void GetTxH(pixel::Type type, uint8_t &nLowCode, uint8_t &nHighCode); + printf(" Clock : %u Hz\n", static_cast(m_nClockSpeedHz)); + +#if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + printf(" Gamma correction %s\n", m_bEnableGammaCorrection ? "Yes" : "No"); +#endif + } + + static PixelConfiguration& Get() { + assert(s_pThis != nullptr); // Ensure that s_pThis is valid + return *s_pThis; + } private: uint32_t m_nCount { pixel::defaults::COUNT }; uint32_t m_nClockSpeedHz { 0 }; + uint32_t m_nLedsPerPixel { 3 }; + pixel::Type m_type { pixel::defaults::TYPE }; + pixel::Map m_map { pixel::Map::UNDEFINED }; + bool m_bIsRTZProtocol { true }; uint8_t m_nLowCode { 0 }; uint8_t m_nHighCode { 0 }; uint8_t m_nGlobalBrightness { 0xFF }; - pixel::Map m_map { pixel::Map::UNDEFINED }; - pixel::Type m_type { pixel::defaults::TYPE }; - bool m_bIsRTZProtocol { true }; #if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) uint8_t m_nGammaValue { 0 }; bool m_bEnableGammaCorrection { false }; const uint8_t *m_pGammaTable { gamma10_0 }; #endif + + static inline PixelConfiguration *s_pThis { nullptr }; }; #endif /* PIXELCONFIGURATION_H_ */ diff --git a/lib-ws28xx/include/pixelpatterns.h b/lib-ws28xx/include/pixelpatterns.h index ce4a960d6..a100e9916 100644 --- a/lib-ws28xx/include/pixelpatterns.h +++ b/lib-ws28xx/include/pixelpatterns.h @@ -2,7 +2,7 @@ * @file pixelpatterns.h * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -114,17 +114,35 @@ class PixelPatterns { const auto nGreen = Green(nColour); const auto nBlue = Blue(nColour); #if defined (PIXELPATTERNS_MULTI) - if (s_pOutput->GetType() != pixel::Type::SK6812W) { - s_pOutput->SetPixel(nPortIndex, nPixelIndex, nRed, nGreen, nBlue); - } else { + switch (PixelConfiguration::Get().GetType()) { + case pixel::Type::WS2801: + s_pOutput->SetColourWS2801(nPortIndex, nPixelIndex, nRed, nGreen, nBlue); + break; + case pixel::Type::APA102: + case pixel::Type::SK9822: + s_pOutput->SetPixel4Bytes(nPortIndex, nPixelIndex, 0xFF, nRed, nGreen, nBlue); + break; + case pixel::Type::P9813: { + const auto nFlag = static_cast(0xC0 | ((~nBlue & 0xC0) >> 2) | ((~nRed & 0xC0) >> 4) | ((~nRed & 0xC0) >> 6)); + s_pOutput->SetPixel4Bytes(nPortIndex, nPixelIndex, nFlag, nBlue, nGreen, nRed); + } + break; + case pixel::Type::SK6812W: if ((nRed == nGreen) && (nGreen == nBlue)) { - s_pOutput->SetPixel(nPortIndex, nPixelIndex, 0x00, 0x00, 0x00, nRed); + s_pOutput->SetColourRTZ(nPortIndex, nPixelIndex, 0x00, 0x00, 0x00, nRed); } else { - s_pOutput->SetPixel(nPortIndex, nPixelIndex, nRed, nGreen, nBlue, 0x00); + s_pOutput->SetColourRTZ(nPortIndex, nPixelIndex, nRed, nGreen, nBlue, 0x00); } + break; + default: + s_pOutput->SetColourRTZ(nPortIndex, nPixelIndex, nRed, nGreen, nBlue); + break; } #else - if (s_pOutput->GetType() != pixel::Type::SK6812W) { + auto& pixelConfiguration = PixelConfiguration::Get(); + const auto type = pixelConfiguration.GetType(); + + if (type != pixel::Type::SK6812W) { s_pOutput->SetPixel(nPixelIndex, nRed, nGreen, nBlue); } else { if ((nRed == nGreen) && (nGreen == nBlue)) { @@ -137,7 +155,7 @@ class PixelPatterns { } void ColourSet(const uint32_t nPortIndex, const uint32_t nColour) { - for (uint32_t i = 0; i < s_nCount; i++) { + for (uint32_t i = 0; i < PixelConfiguration::Get().GetCount(); i++) { SetPixelColour(nPortIndex, i, nColour); } } @@ -169,7 +187,6 @@ class PixelPatterns { static WS28xx *s_pOutput; #endif static uint32_t s_nActivePorts; - static uint32_t s_nCount; struct PortConfig { uint32_t nLastUpdate; diff --git a/lib-ws28xx/include/pixeltype.h b/lib-ws28xx/include/pixeltype.h index cc476e574..9cf8ff2dc 100644 --- a/lib-ws28xx/include/pixeltype.h +++ b/lib-ws28xx/include/pixeltype.h @@ -2,7 +2,7 @@ * @file pixeltype.h * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,6 +27,7 @@ #define PIXELTYPE_H_ #include +#include namespace pixel { enum class Type { @@ -77,23 +78,98 @@ static constexpr auto TYPE = Type::WS2812B; static constexpr auto COUNT = 170; static constexpr auto OUTPUT_PORTS = 1; } // namespace defaults -} // namespace pixel -class PixelType { -public: - static const char *GetType(pixel::Type type); - static pixel::Type GetType(const char *pString); +inline Map pixel_get_map(const pixel::Type type) { + if ((type == pixel::Type::WS2811) || (type == pixel::Type::UCS2903)) { + return pixel::Map::RGB; + } - static const char *GetMap(pixel::Map map); - static pixel::Map GetMap(const char *pString); - static pixel::Map GetMap(pixel::Type type); + if (type == pixel::Type::UCS1903) { + return pixel::Map::BRG; + } - static float ConvertTxH(uint8_t nCode); - static uint8_t ConvertTxH(float fTxH); + if (type == pixel::Type::CS8812) { + return pixel::Map::BGR; + } -private: - static const char TYPES[static_cast(pixel::Type::UNDEFINED)][pixel::TYPES_MAX_NAME_LENGTH]; - static const char MAPS[static_cast(pixel::Map::UNDEFINED)][4]; -}; + return pixel::Map::GRB; +} + +static constexpr auto F_INTERVAL = 0.15625f; + +inline float pixel_convert_TxH(const uint8_t nCode) { + switch (nCode) { + case 0x80: + return F_INTERVAL * 1; + break; + case 0xC0: + return F_INTERVAL * 2; + break; + case 0xE0: + return F_INTERVAL * 3; + break; + case 0xF0: + return F_INTERVAL * 4; + break; + case 0xF8: + return F_INTERVAL * 5; + break; + case 0xFC: + return F_INTERVAL * 6; + break; + case 0xFE: + return F_INTERVAL * 7; + break; + default: + return 0; + break; + } + + assert(0); + __builtin_unreachable(); +} + +inline uint8_t pixel_convert_TxH(const float fTxH) { + if (fTxH < 0.5f * F_INTERVAL) { + return 0x00; + } + + if (fTxH < 1.5f * F_INTERVAL) { + return 0x80; + } + + if (fTxH < 2.5f * F_INTERVAL) { + return 0xC0; + } + + if (fTxH < 3.5f * F_INTERVAL) { + return 0xE0; + } + + if (fTxH < 4.5f * F_INTERVAL) { + return 0xF0; + } + + if (fTxH < 5.5f * F_INTERVAL) { + return 0xF8; + } + + if (fTxH < 6.5f * F_INTERVAL) { + return 0xFC; + } + + if (fTxH < 7.5f * F_INTERVAL) { + return 0xFE; + } + + return 0x00; +} + +const char* pixel_get_type(pixel::Type); +pixel::Type pixel_get_type(const char *); + +const char* pixel_get_map(pixel::Map); +pixel::Map pixel_get_map(const char *); +} // namespace pixel #endif /* PIXELTYPE_H_ */ diff --git a/lib-ws28xx/include/ws28xx.h b/lib-ws28xx/include/ws28xx.h index 916dbf5af..d3fb8ef59 100644 --- a/lib-ws28xx/include/ws28xx.h +++ b/lib-ws28xx/include/ws28xx.h @@ -34,7 +34,7 @@ class WS28xx { public: - WS28xx(PixelConfiguration *pPixelConfiguration); + WS28xx(); ~WS28xx(); void SetPixel(uint32_t nIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue); @@ -54,18 +54,6 @@ class WS28xx { void Blackout(); void FullOn(); - pixel::Type GetType() const { - return m_pPixelConfiguration->GetType(); - } - - uint32_t GetCount() const { - return m_pPixelConfiguration->GetCount(); - } - - pixel::Map GetMap() const { - return m_pPixelConfiguration->GetMap(); - } - static WS28xx *Get() { return s_pThis; } @@ -75,7 +63,6 @@ class WS28xx { void SetColorWS28xx(uint32_t nOffset, uint8_t nValue); private: - PixelConfiguration *m_pPixelConfiguration; uint32_t m_nBufSize; uint8_t *m_pBuffer { nullptr }; uint8_t *m_pBlackoutBuffer { nullptr }; diff --git a/lib-ws28xx/include/ws28xxmulti.h b/lib-ws28xx/include/ws28xxmulti.h index 3d61f5753..3872f7a2c 100644 --- a/lib-ws28xx/include/ws28xxmulti.h +++ b/lib-ws28xx/include/ws28xxmulti.h @@ -2,7 +2,7 @@ * @file ws28xxmulti.h * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/lib-ws28xx/src/h3/ws28xx.cpp b/lib-ws28xx/src/h3/ws28xx.cpp index 6f116e3fd..4f4b57032 100644 --- a/lib-ws28xx/src/h3/ws28xx.cpp +++ b/lib-ws28xx/src/h3/ws28xx.cpp @@ -2,7 +2,7 @@ * @file ws28xx.cpp * */ -/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXEL) +# undef NDEBUG +#endif + #if !defined(__clang__) // Needed for compiling on MacOS # pragma GCC push_options # pragma GCC optimize ("O3") @@ -43,25 +47,26 @@ WS28xx *WS28xx::s_pThis; -WS28xx::WS28xx(PixelConfiguration *pPixelConfiguration): m_pPixelConfiguration(pPixelConfiguration) { +WS28xx::WS28xx() { DEBUG_ENTRY assert(s_pThis == nullptr); s_pThis = this; - uint32_t nLedsPerPixel; - m_pPixelConfiguration->Validate(nLedsPerPixel); + auto& pixelConfiguration = PixelConfiguration::Get(); + + pixelConfiguration.Validate(); - const auto nCount = m_pPixelConfiguration->GetCount(); + const auto nCount = pixelConfiguration.GetCount(); - m_nBufSize = nCount * nLedsPerPixel; + m_nBufSize = nCount * pixelConfiguration.GetLedsPerPixel(); - if (m_pPixelConfiguration->IsRTZProtocol()) { + if (pixelConfiguration.IsRTZProtocol()) { m_nBufSize *= 8; m_nBufSize += 1; } - const auto type = m_pPixelConfiguration->GetType(); + const auto type = pixelConfiguration.GetType(); if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822) || (type == pixel::Type::P9813)) { m_nBufSize += nCount; @@ -71,7 +76,7 @@ WS28xx::WS28xx(PixelConfiguration *pPixelConfiguration): m_pPixelConfiguration(p SetupBuffers(); FUNC_PREFIX(spi_begin()); - FUNC_PREFIX(spi_set_speed_hz(m_pPixelConfiguration->GetClockSpeedHz())); + FUNC_PREFIX(spi_set_speed_hz(pixelConfiguration.GetClockSpeedHz())); DEBUG_EXIT } @@ -120,8 +125,10 @@ void WS28xx::SetupBuffers() { DEBUG_PRINTF("m_nBufSize=%u, m_pBuffer=%p, m_pBlackoutBuffer=%p", m_nBufSize, m_pBuffer, m_pBlackoutBuffer); - const auto type = m_pPixelConfiguration->GetType(); - const auto nCount = m_pPixelConfiguration->GetCount(); + auto& pixelConfiguration = PixelConfiguration::Get(); + + const auto type = pixelConfiguration.GetType(); + const auto nCount = pixelConfiguration.GetCount(); if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822) || (type == pixel::Type::P9813)) { memset(m_pBuffer, 0, 4); @@ -137,7 +144,7 @@ void WS28xx::SetupBuffers() { } } else { m_pBuffer[0] = 0x00; - memset(&m_pBuffer[1], type == pixel::Type::WS2801 ? 0 : m_pPixelConfiguration->GetLowCode(), m_nBufSize); + memset(&m_pBuffer[1], type == pixel::Type::WS2801 ? 0 : pixelConfiguration.GetLowCode(), m_nBufSize); } memcpy(m_pBlackoutBuffer, m_pBuffer, m_nBufSize); @@ -167,8 +174,10 @@ void WS28xx::Blackout() { auto *pBuffer = m_pBuffer; m_pBuffer = m_pBlackoutBuffer; - const auto type = m_pPixelConfiguration->GetType(); - const auto nCount = m_pPixelConfiguration->GetCount(); + auto& pixelConfiguration = PixelConfiguration::Get(); + + const auto type = pixelConfiguration.GetType(); + const auto nCount = pixelConfiguration.GetCount(); if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822) || (type == pixel::Type::P9813)) { memset(m_pBuffer, 0, 4); @@ -184,7 +193,7 @@ void WS28xx::Blackout() { } } else { m_pBuffer[0] = 0x00; - memset(&m_pBuffer[1], type == pixel::Type::WS2801 ? 0 : m_pPixelConfiguration->GetLowCode(), m_nBufSize); + memset(&m_pBuffer[1], type == pixel::Type::WS2801 ? 0 : pixelConfiguration.GetLowCode(), m_nBufSize); } Update(); @@ -211,8 +220,10 @@ void WS28xx::FullOn() { } while (FUNC_PREFIX(spi_dma_tx_is_active())); #endif - const auto type = m_pPixelConfiguration->GetType(); - const auto nCount = m_pPixelConfiguration->GetCount(); + auto& pixelConfiguration = PixelConfiguration::Get(); + + const auto type = pixelConfiguration.GetType(); + const auto nCount = pixelConfiguration.GetCount(); if ((type == pixel::Type::APA102) || (type == pixel::Type::SK9822) || (type == pixel::Type::P9813)) { memset(m_pBuffer, 0xFF, 4); @@ -228,7 +239,7 @@ void WS28xx::FullOn() { } } else { m_pBuffer[0] = 0x00; - memset(&m_pBuffer[1], type == pixel::Type::WS2801 ? 0xFF : m_pPixelConfiguration->GetHighCode(), m_nBufSize); + memset(&m_pBuffer[1], type == pixel::Type::WS2801 ? 0xFF : pixelConfiguration.GetHighCode(), m_nBufSize); } Update(); diff --git a/lib-ws28xx/src/h3/ws28xxmulti.cpp b/lib-ws28xx/src/h3/ws28xxmulti.cpp index dbfa5cfce..cfe2ceab3 100644 --- a/lib-ws28xx/src/h3/ws28xxmulti.cpp +++ b/lib-ws28xx/src/h3/ws28xxmulti.cpp @@ -2,7 +2,7 @@ * @file ws28xxmulti.cpp * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXEL) +# undef NDEBUG +#endif + #if !defined(__clang__) // Needed for compiling on MacOS # pragma GCC push_options # pragma GCC optimize ("O3") @@ -50,19 +54,20 @@ using namespace pixel; WS28xxMulti *WS28xxMulti::s_pThis; -WS28xxMulti::WS28xxMulti(PixelConfiguration& pixelConfiguration): m_PixelConfiguration(pixelConfiguration) { +WS28xxMulti::WS28xxMulti() { DEBUG_ENTRY assert(s_pThis == nullptr); s_pThis = this; - uint32_t nLedsPerPixel; - m_PixelConfiguration.Validate(nLedsPerPixel); + auto& pixelConfiguration = PixelConfiguration::Get(); - const auto nCount = m_PixelConfiguration.GetCount(); - m_nBufSize = nCount * nLedsPerPixel; + pixelConfiguration.Validate(); - const auto type = m_PixelConfiguration.GetType(); + const auto nCount = pixelConfiguration.GetCount(); + m_nBufSize = nCount * pixelConfiguration.GetLedsPerPixel(); + + const auto type = pixelConfiguration.GetType(); if ((type == Type::APA102) || (type == Type::SK9822) || (type == Type::P9813)) { m_nBufSize += nCount; @@ -73,20 +78,20 @@ WS28xxMulti::WS28xxMulti(PixelConfiguration& pixelConfiguration): m_PixelConfigu DEBUG_PRINTF("m_nBufSize=%d", m_nBufSize); - const auto nLowCode = m_PixelConfiguration.GetLowCode(); - const auto nHighCode = m_PixelConfiguration.GetHighCode(); + const auto nLowCode = pixelConfiguration.GetLowCode(); + const auto nHighCode = pixelConfiguration.GetHighCode(); m_hasCPLD = SetupCPLD(); SetupHC595(ReverseBits(nLowCode), ReverseBits(nHighCode)); - if (m_PixelConfiguration.IsRTZProtocol()) { - SetupSPI(m_PixelConfiguration.GetClockSpeedHz()); + if (pixelConfiguration.IsRTZProtocol()) { + SetupSPI(pixelConfiguration.GetClockSpeedHz()); } else { if (m_hasCPLD) { - SetupSPI(m_PixelConfiguration.GetClockSpeedHz() * 6); + SetupSPI(pixelConfiguration.GetClockSpeedHz() * 6); } else { - SetupSPI(m_PixelConfiguration.GetClockSpeedHz() * 4); + SetupSPI(pixelConfiguration.GetClockSpeedHz() * 4); } } @@ -117,23 +122,25 @@ void WS28xxMulti::SetupBuffers() { m_pDmaBufferBlackout = m_pDmaBuffer + (nSizeHalf & static_cast(~3)); - const auto type = m_PixelConfiguration.GetType(); - const auto nCount = m_PixelConfiguration.GetCount(); + auto& pixelConfiguration = PixelConfiguration::Get(); + + const auto type = pixelConfiguration.GetType(); + const auto nCount = pixelConfiguration.GetCount(); if ((type == Type::APA102) || (type == Type::SK9822) || (type == Type::P9813)) { DEBUG_PUTS("SPI"); for (uint32_t nPortIndex = 0; nPortIndex < 8; nPortIndex++) { - SetPixel(nPortIndex, 0, 0, 0, 0, 0); + SetPixel4Bytes(nPortIndex, 0, 0, 0, 0, 0); for (uint32_t nPixelIndex = 1; nPixelIndex <= nCount; nPixelIndex++) { - SetPixel(nPortIndex, nPixelIndex, 0, 0xE0, 0, 0); + SetPixel4Bytes(nPortIndex, nPixelIndex, 0, 0xE0, 0, 0); } if ((type == Type::APA102) || (type == Type::SK9822)) { - SetPixel(nPortIndex, 1U + nCount, 0xFF, 0xFF, 0xFF, 0xFF); + SetPixel4Bytes(nPortIndex, 1U + nCount, 0xFF, 0xFF, 0xFF, 0xFF); } else { - SetPixel(nPortIndex, 1U + nCount, 0, 0, 0, 0); + SetPixel4Bytes(nPortIndex, 1U + nCount, 0, 0, 0, 0); } } @@ -280,38 +287,7 @@ void WS28xxMulti::SetPixel4Bytes(uint32_t nPortIndex, uint32_t nPixelIndex, uint } } -void WS28xxMulti::SetPixel(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue) { -#if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) - const auto pGammaTable = m_PixelConfiguration.GetGammaTable(); - - nRed = pGammaTable[nRed]; - nGreen = pGammaTable[nGreen]; - nBlue = pGammaTable[nBlue]; -#endif - - const auto type = m_PixelConfiguration.GetType(); - - if ((m_PixelConfiguration.IsRTZProtocol()) || (type == Type::WS2801)) { - SetColour(nPortIndex, nPixelIndex, nRed, nGreen, nBlue); - return; - } - - if ((type == Type::APA102) || (type == Type::SK9822)) { - SetPixel4Bytes(nPortIndex, 1 + nPixelIndex, nBlue, m_PixelConfiguration.GetGlobalBrightness(), nGreen, nRed); - return; - } - - if (type == Type::P9813) { - const auto nFlag = static_cast(0xC0 | ((~nBlue & 0xC0) >> 2) | ((~nGreen & 0xC0) >> 4) | ((~nRed & 0xC0) >> 6)); - SetPixel4Bytes(nPortIndex, 1+ nPixelIndex, nRed, nFlag, nGreen, nBlue); - return; - } - - assert(0); - __builtin_unreachable(); -} - -void WS28xxMulti::SetPixel(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite) { +void WS28xxMulti::SetColourRTZ(uint32_t nPortIndex, uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite) { #if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) const auto pGammaTable = m_PixelConfiguration.GetGammaTable(); @@ -374,6 +350,10 @@ inline void memcpy64(void *dest, void const *src, size_t n) { void WS28xxMulti::Update() { assert(!FUNC_PREFIX(spi_dma_tx_is_active())); + do { // https://github.com/vanvught/rpidmx512/issues/281 + asm volatile ("isb" ::: "memory"); + } while (FUNC_PREFIX(spi_dma_tx_is_active())); + memcpy64(m_pDmaBuffer, reinterpret_cast(H3_SRAM_A1_BASE + 4096), m_nBufSize); FUNC_PREFIX(spi_dma_tx_start(m_pDmaBuffer, m_nBufSize)); @@ -405,22 +385,24 @@ void WS28xxMulti::FullOn() { asm volatile ("isb" ::: "memory"); } while (FUNC_PREFIX(spi_dma_tx_is_active())); - const auto type = m_PixelConfiguration.GetType(); + auto& pixelConfiguration = PixelConfiguration::Get(); + + const auto type = pixelConfiguration.GetType(); if ((type == Type::APA102) || (type == Type::SK9822) || (type == Type::P9813)) { for (uint32_t nPortIndex = 0; nPortIndex < 8; nPortIndex++) { - SetPixel(nPortIndex, 0, 0, 0, 0, 0); + SetPixel4Bytes(nPortIndex, 0, 0, 0, 0, 0); - const auto nCount = m_PixelConfiguration.GetCount(); + const auto nCount = pixelConfiguration.GetCount(); for (uint32_t nPixelIndex = 1; nPixelIndex <= nCount; nPixelIndex++) { - SetPixel(nPortIndex, nPixelIndex, 0xFF, 0xE0, 0xFF, 0xFF); + SetPixel4Bytes(nPortIndex, nPixelIndex, 0xFF, 0xE0, 0xFF, 0xFF); } if ((type == Type::APA102) || (type == Type::SK9822)) { - SetPixel(nPortIndex, 1U + nCount, 0xFF, 0xFF, 0xFF, 0xFF); + SetPixel4Bytes(nPortIndex, 1U + nCount, 0xFF, 0xFF, 0xFF, 0xFF); } else { - SetPixel(nPortIndex, 1U + nCount, 0, 0, 0, 0); + SetPixel4Bytes(nPortIndex, 1U + nCount, 0, 0, 0, 0); } } } else { diff --git a/lib-ws28xx/src/patterns/pixelpatterns.cpp b/lib-ws28xx/src/patterns/pixelpatterns.cpp index 1dab23e6d..0128bf9d5 100644 --- a/lib-ws28xx/src/patterns/pixelpatterns.cpp +++ b/lib-ws28xx/src/patterns/pixelpatterns.cpp @@ -2,7 +2,7 @@ * @file pixelpatterns.cpp * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -51,7 +51,6 @@ WS28xxMulti *PixelPatterns::s_pOutput; WS28xx *PixelPatterns::s_pOutput; #endif uint32_t PixelPatterns::s_nActivePorts; -uint32_t PixelPatterns::s_nCount; PixelPatterns::PortConfig PixelPatterns::s_PortConfig[pixelpatterns::MAX_PORTS]; uint32_t *PixelPatterns::s_pScannerColours; @@ -67,7 +66,7 @@ PixelPatterns::PixelPatterns(const uint32_t nActivePorts) { assert(s_pOutput != nullptr); s_nActivePorts = std::min(MAX_PORTS, nActivePorts); - s_nCount = s_pOutput->GetCount(); + const auto nMillis = Hardware::Get()->Millis(); for (uint32_t i = 0; i < MAX_PORTS; i++) { @@ -131,8 +130,8 @@ void PixelPatterns::RainbowCycle(uint32_t nPortIndex, uint32_t nInterval, pixelp void PixelPatterns::RainbowCycleUpdate(uint32_t nPortIndex) { const auto nIndex = s_PortConfig[nPortIndex].nPixelIndex; - for (uint32_t i = 0; i < s_nCount; i++) { - SetPixelColour(nPortIndex, i, Wheel(((i * 256U / s_nCount) + nIndex) & 0xFF)); + for (uint32_t i = 0; i < PixelConfiguration::Get().GetCount(); i++) { + SetPixelColour(nPortIndex, i, Wheel(((i * 256U / PixelConfiguration::Get().GetCount()) + nIndex) & 0xFF)); } Increment(nPortIndex); @@ -143,7 +142,7 @@ void PixelPatterns::TheaterChase(uint32_t nPortIndex, uint32_t nColour1, uint32_ s_PortConfig[nPortIndex].ActivePattern = Pattern::THEATER_CHASE; s_PortConfig[nPortIndex].nInterval = nInterval; - s_PortConfig[nPortIndex].nTotalSteps= s_nCount; + s_PortConfig[nPortIndex].nTotalSteps= PixelConfiguration::Get().GetCount(); s_PortConfig[nPortIndex].nColour1 = nColour1; s_PortConfig[nPortIndex].nColour2 = nColour2; s_PortConfig[nPortIndex].nPixelIndex = 0; @@ -155,7 +154,7 @@ void PixelPatterns::TheaterChaseUpdate(uint32_t nPortIndex) { const auto Colour2 = s_PortConfig[nPortIndex].nColour2; const auto Index = s_PortConfig[nPortIndex].nPixelIndex; - for (uint32_t i = 0; i < s_nCount; i++) { + for (uint32_t i = 0; i < PixelConfiguration::Get().GetCount(); i++) { if ((i + Index) % 3 == 0) { SetPixelColour(nPortIndex, i, Colour1); } else { @@ -171,7 +170,7 @@ void PixelPatterns::ColourWipe(uint32_t nPortIndex, uint32_t nColour, uint32_t n s_PortConfig[nPortIndex].ActivePattern = Pattern::COLOR_WIPE; s_PortConfig[nPortIndex].nInterval = nInterval; - s_PortConfig[nPortIndex].nTotalSteps= s_nCount; + s_PortConfig[nPortIndex].nTotalSteps= PixelConfiguration::Get().GetCount(); s_PortConfig[nPortIndex].nColour1 = nColour; s_PortConfig[nPortIndex].nPixelIndex = 0; s_PortConfig[nPortIndex].Direction = Direction; @@ -188,17 +187,19 @@ void PixelPatterns::ColourWipeUpdate(uint32_t nPortIndex) { void PixelPatterns::Scanner(uint32_t nPortIndex, uint32_t nColour1, uint32_t nInterval) { Clear(nPortIndex); + const auto nCount = PixelConfiguration::Get().GetCount(); + s_PortConfig[nPortIndex].ActivePattern = Pattern::SCANNER; s_PortConfig[nPortIndex].nInterval = nInterval; - s_PortConfig[nPortIndex].nTotalSteps= static_cast((s_nCount - 1U) * 2); + s_PortConfig[nPortIndex].nTotalSteps= static_cast((nCount - 1U) * 2); s_PortConfig[nPortIndex].nColour1 = nColour1; s_PortConfig[nPortIndex].nPixelIndex = 0; if (s_pScannerColours == nullptr) { - s_pScannerColours = new uint32_t[s_nCount]; + s_pScannerColours = new uint32_t[nCount]; assert(s_pScannerColours != nullptr); - for (uint32_t i = 0; i < s_nCount; i++) { + for (uint32_t i = 0; i < nCount; i++) { s_pScannerColours[i] = 0; } } @@ -209,7 +210,7 @@ void PixelPatterns::ScannerUpdate(uint32_t nPortIndex) { const auto nTotalSteps = s_PortConfig[nPortIndex].nTotalSteps; const auto nIndex = s_PortConfig[nPortIndex].nPixelIndex; - for (uint32_t i = 0; i < s_nCount; i++) { + for (uint32_t i = 0; i < PixelConfiguration::Get().GetCount(); i++) { if (i == nIndex) { SetPixelColour(nPortIndex, i, nColour1); s_pScannerColours[i] = nColour1; diff --git a/lib-ws28xx/src/pixel/ws28xx.cpp b/lib-ws28xx/src/pixel/ws28xx.cpp index 574e84db3..4db2cd308 100644 --- a/lib-ws28xx/src/pixel/ws28xx.cpp +++ b/lib-ws28xx/src/pixel/ws28xx.cpp @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXEL) +# undef NDEBUG +#endif + #if !defined(__clang__) // Needed for compiling on MacOS # pragma GCC push_options # pragma GCC optimize ("O3") @@ -40,14 +44,15 @@ #include "gamma/gamma_tables.h" void WS28xx::SetColorWS28xx(uint32_t nOffset, uint8_t nValue) { - assert(m_pPixelConfiguration->GetType() != pixel::Type::WS2801); + auto& pixelConfiguration = PixelConfiguration::Get(); + assert(pixelConfiguration.GetType() != pixel::Type::WS2801); assert(m_pBuffer != nullptr); assert(nOffset + 7 < m_nBufSize); nOffset += 1; - const auto nLowCode = m_pPixelConfiguration->GetLowCode(); - const auto nHighCode = m_pPixelConfiguration->GetHighCode(); + const auto nLowCode = pixelConfiguration.GetLowCode(); + const auto nHighCode = pixelConfiguration.GetHighCode(); for (uint8_t mask = 0x80; mask != 0; mask = static_cast(mask >> 1)) { if (nValue & mask) { @@ -60,17 +65,18 @@ void WS28xx::SetColorWS28xx(uint32_t nOffset, uint8_t nValue) { } void WS28xx::SetPixel(uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue) { - assert(nPixelIndex < m_pPixelConfiguration->GetCount()); + auto& pixelConfiguration = PixelConfiguration::Get(); + assert(nPixelIndex < pixelConfiguration.GetCount()); #if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) - const auto pGammaTable = m_pPixelConfiguration->GetGammaTable(); + const auto pGammaTable = pixelConfiguration.GetGammaTable(); nRed = pGammaTable[nRed]; nGreen = pGammaTable[nGreen]; nBlue = pGammaTable[nBlue]; #endif - if (m_pPixelConfiguration->IsRTZProtocol()) { + if (pixelConfiguration.IsRTZProtocol()) { const auto nOffset = nPixelIndex * 24U; SetColorWS28xx(nOffset, nRed); @@ -81,7 +87,7 @@ void WS28xx::SetPixel(uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_ assert(m_pBuffer != nullptr); - const auto type = m_pPixelConfiguration->GetType(); + const auto type = pixelConfiguration.GetType(); if (type == pixel::Type::WS2801) { const auto nOffset = nPixelIndex * 3U; @@ -98,7 +104,7 @@ void WS28xx::SetPixel(uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_ const auto nOffset = 4U + (nPixelIndex * 4U); assert(nOffset + 3U < m_nBufSize); - m_pBuffer[nOffset] = m_pPixelConfiguration->GetGlobalBrightness(); + m_pBuffer[nOffset] = pixelConfiguration.GetGlobalBrightness(); m_pBuffer[nOffset + 1] = nRed; m_pBuffer[nOffset + 2] = nGreen; m_pBuffer[nOffset + 3] = nBlue; @@ -125,11 +131,11 @@ void WS28xx::SetPixel(uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_ } void WS28xx::SetPixel(uint32_t nPixelIndex, uint8_t nRed, uint8_t nGreen, uint8_t nBlue, uint8_t nWhite) { - assert(nPixelIndex < m_pPixelConfiguration->GetCount()); - assert(m_pPixelConfiguration->GetType() == pixel::Type::SK6812W); + assert(nPixelIndex < PixelConfiguration::Get().GetCount()); + assert(PixelConfiguration::Get().GetType() == pixel::Type::SK6812W); #if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) - const auto pGammaTable = m_pPixelConfiguration->GetGammaTable(); + const auto pGammaTable = pixelConfiguration.GetGammaTable(); nRed = pGammaTable[nRed]; nGreen = pGammaTable[nGreen]; diff --git a/lib-ws28xx/src/pixelconfiguration.cpp b/lib-ws28xx/src/pixelconfiguration.cpp deleted file mode 100644 index 51220a585..000000000 --- a/lib-ws28xx/src/pixelconfiguration.cpp +++ /dev/null @@ -1,150 +0,0 @@ -/** - * @file pixelconfiguration.cpp - * - */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#if !defined(__clang__) // Needed for compiling on MacOS -# pragma GCC push_options -# pragma GCC optimize ("Os") -#endif - -#include - -#include "pixelconfiguration.h" -#include "pixeltype.h" -#include "gamma/gamma_tables.h" - -#include "debug.h" - -using namespace pixel; - -void PixelConfiguration::Validate(uint32_t& nLedsPerPixel) { - DEBUG_ENTRY - - if (m_type == Type::SK6812W) { - m_nCount = m_nCount <= static_cast(max::ledcount::RGBW) ? m_nCount : static_cast(max::ledcount::RGBW); - nLedsPerPixel = 4; - } else { - m_nCount = m_nCount <= static_cast(max::ledcount::RGB) ? m_nCount : static_cast(max::ledcount::RGB); - nLedsPerPixel = 3; - } - - if ((m_type == Type::APA102) || (m_type == Type::SK9822)){ - if (m_nGlobalBrightness > 0x1F) { - m_nGlobalBrightness = 0xFF; - } else { - m_nGlobalBrightness = 0xE0 | (m_nGlobalBrightness & 0x1F); - } - } - - if ((m_type == Type::WS2801) || (m_type == Type::APA102) || (m_type == Type::SK9822) || (m_type == Type::P9813)) { - m_bIsRTZProtocol = false; - - if (m_map == Map::UNDEFINED) { - m_map = Map::RGB; - } - - if (m_type == Type::P9813) { - if (m_nClockSpeedHz == 0) { - m_nClockSpeedHz = spi::speed::p9813::default_hz; - } else if (m_nClockSpeedHz > spi::speed::p9813::max_hz) { - m_nClockSpeedHz = spi::speed::p9813::max_hz; - } - } else { - if (m_nClockSpeedHz == 0) { - m_nClockSpeedHz = spi::speed::ws2801::default_hz; - } else if (m_nClockSpeedHz > spi::speed::ws2801::max_hz) { - m_nClockSpeedHz = spi::speed::ws2801::max_hz; - } - } - } else { - m_bIsRTZProtocol = true; - - if (m_map == Map::UNDEFINED) { - m_map = PixelType::GetMap(m_type); - } - - if (m_nLowCode >= m_nHighCode) { - m_nLowCode = 0; - m_nHighCode = 0; - } - - uint8_t nLowCode, nHighCode; - - GetTxH(m_type, nLowCode, nHighCode); - - if (m_nLowCode == 0) { - m_nLowCode = nLowCode; - } - - if (m_nHighCode == 0) { - m_nHighCode = nHighCode; - } - - m_nClockSpeedHz = 6400000; // 6.4MHz / 8 bits = 800Hz - } - -#if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) - if (m_bEnableGammaCorrection) { - if (m_nGammaValue == 0) { - m_pGammaTable = gamma::get_table_default(m_type); - } else { - m_pGammaTable = gamma::get_table(m_nGammaValue); - } - } else { - m_pGammaTable = gamma10_0; - } -#endif - - DEBUG_EXIT -} - -void PixelConfiguration::GetTxH(Type type, uint8_t &nLowCode, uint8_t &nHighCode) { - nLowCode = 0xC0; - nHighCode = (type == Type::WS2812B ? 0xF8 : - (((type == Type::UCS1903) || (type == Type::UCS2903) || (type == Type::CS8812)) ? 0xFC : 0xF0)); -} - -#include - -void PixelConfiguration::Print() { - puts("Pixel configuration"); - printf(" Type : %s [%d]\n", PixelType::GetType(m_type), static_cast(m_type)); - printf(" Count : %d\n", m_nCount); - - if (m_bIsRTZProtocol) { - printf(" Mapping : %s [%d]\n", PixelType::GetMap(m_map), static_cast(m_map)); - printf(" T0H : %.2f [0x%X]\n", PixelType::ConvertTxH(m_nLowCode), m_nLowCode); - printf(" T1H : %.2f [0x%X]\n", PixelType::ConvertTxH(m_nHighCode), m_nHighCode); - } else { - if ((m_type == Type::APA102) || (m_type == Type::SK9822)){ - printf(" GlobalBrightness: %u\n", m_nGlobalBrightness); - } - } - - printf(" Clock: %u Hz\n", static_cast(m_nClockSpeedHz)); - -#if defined (CONFIG_PIXELDMX_ENABLE_GAMMATABLE) - printf(" Gamma correction %s\n", m_bEnableGammaCorrection ? "Yes" : "No"); -#endif -} diff --git a/lib-ws28xx/src/pixeltype.cpp b/lib-ws28xx/src/pixeltype.cpp index 37be1cfbe..44ad8e5b4 100644 --- a/lib-ws28xx/src/pixeltype.cpp +++ b/lib-ws28xx/src/pixeltype.cpp @@ -2,7 +2,7 @@ * @file pixeltype.cpp * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -#if !defined(__clang__) // Needed for compiling on MacOS +#if defined(__GNUC__) && !defined(__clang__) ///< Needed for macOS # pragma GCC push_options # pragma GCC optimize ("Os") #endif @@ -34,9 +34,8 @@ #include "pixeltype.h" -using namespace pixel; - -const char PixelType::TYPES[static_cast(Type::UNDEFINED)][TYPES_MAX_NAME_LENGTH] = +namespace pixel { +const char TYPES[static_cast(pixel::Type::UNDEFINED)][pixel::TYPES_MAX_NAME_LENGTH] = { "WS2801\0", // 1 "WS2811\0", "WS2812\0", "WS2812B", "WS2813\0", "WS2815\0", // 5 "SK6812\0", "SK6812W", // 2 @@ -46,130 +45,49 @@ const char PixelType::TYPES[static_cast(Type::UNDEFINED)][TYPES_MAX_NA "P9813", // 1 }; // = 14 -const char PixelType::MAPS[static_cast(Map::UNDEFINED)][4] = { "RGB", "RBG", "GRB", "GBR", "BRG", "BGR"}; +const char MAPS[static_cast(pixel::Map::UNDEFINED)][4] = { "RGB", "RBG", "GRB", "GBR", "BRG", "BGR"}; -const char *PixelType::GetType(Type type) { - if (type < Type::UNDEFINED) { +const char *pixel_get_type(pixel::Type type) { + if (type < pixel::Type::UNDEFINED) { return TYPES[static_cast(type)]; } return "Unknown"; } -Type PixelType::GetType(const char *pString) { +pixel::Type pixel_get_type(const char *pString) { assert(pString != nullptr); + uint32_t index = 0; - for (uint32_t i = 0; i < static_cast(Type::UNDEFINED); i++) { - if (strcasecmp(pString, TYPES[i]) == 0) { - return static_cast(i); + for (const char (&type)[pixel::TYPES_MAX_NAME_LENGTH] : TYPES) { + if (strcasecmp(pString, type) == 0) { + return static_cast(index); } + ++index; } - return Type::UNDEFINED; + return pixel::Type::UNDEFINED; } -Map PixelType::GetMap(const char *pString) { +pixel::Map pixel_get_map(const char *pString) { assert(pString != nullptr); + uint32_t index = 0; - for (uint32_t nIndex = 0; nIndex < static_cast(Map::UNDEFINED); nIndex++) { - if (strncasecmp(MAPS[nIndex], pString, 3) == 0) { - return static_cast(nIndex); + for (const char (&map)[4] : MAPS) { + if (strncasecmp(map, pString, 3) == 0) { + return static_cast(index); } + ++index; } - return Map::UNDEFINED; + return pixel::Map::UNDEFINED; } -const char *PixelType::GetMap(Map map) { - if (map < Map::UNDEFINED) { +const char *pixel_get_map(pixel::Map map) { + if (map < pixel::Map::UNDEFINED) { return MAPS[static_cast(map)]; } return "Undefined"; } - -Map PixelType::GetMap(Type type) { - if ((type == Type::WS2811) || (type == Type::UCS2903)) { - return Map::RGB; - } - - if (type == Type::UCS1903) { - return Map::BRG; - } - - if (type == Type::CS8812) { - return Map::BGR; - } - - return Map::GRB; -} - -static constexpr auto F_INTERVAL = 0.15625f; - -float PixelType::ConvertTxH(uint8_t nCode) { - switch (nCode) { - case 0x80: - return F_INTERVAL * 1; - break; - case 0xC0: - return F_INTERVAL * 2; - break; - case 0xE0: - return F_INTERVAL * 3; - break; - case 0xF0: - return F_INTERVAL * 4; - break; - case 0xF8: - return F_INTERVAL * 5; - break; - case 0xFC: - return F_INTERVAL * 6; - break; - case 0xFE: - return F_INTERVAL * 7; - break; - default: - return 0; - break; - } - - assert(0); - __builtin_unreachable(); -} - -uint8_t PixelType::ConvertTxH(float fTxH) { - if (fTxH < 0.5f * F_INTERVAL) { - return 0x00; - } - - if (fTxH < 1.5f * F_INTERVAL) { - return 0x80; - } - - if (fTxH < 2.5f * F_INTERVAL) { - return 0xC0; - } - - if (fTxH < 3.5f * F_INTERVAL) { - return 0xE0; - } - - if (fTxH < 4.5f * F_INTERVAL) { - return 0xF0; - } - - if (fTxH < 5.5f * F_INTERVAL) { - return 0xF8; - } - - if (fTxH < 6.5f * F_INTERVAL) { - return 0xFC; - } - - if (fTxH < 7.5f * F_INTERVAL) { - return 0xFE; - } - - return 0x00; -} +} // namespace pixel diff --git a/lib-ws28xxdisplay/src/ws28xxdisplay7segment.cpp b/lib-ws28xxdisplay/src/ws28xxdisplay7segment.cpp index ee670c108..a5bb714c7 100644 --- a/lib-ws28xxdisplay/src/ws28xxdisplay7segment.cpp +++ b/lib-ws28xxdisplay/src/ws28xxdisplay7segment.cpp @@ -202,7 +202,7 @@ WS28xxDisplay7Segment::WS28xxDisplay7Segment(Type tLedType, Map tRGBMapping) { pixelConfiguration.SetCount(WS28xxDisplay7SegmentConfig::LED_COUNT); - m_pWS28xx = new WS28xx(&pixelConfiguration); + m_pWS28xx = new WS28xx; assert(m_pWS28xx != nullptr); m_pWS28xx->Blackout(); diff --git a/lib-ws28xxdisplay/src/ws28xxdisplaymatrix.cpp b/lib-ws28xxdisplay/src/ws28xxdisplaymatrix.cpp index 41408bbef..632f6fca5 100644 --- a/lib-ws28xxdisplay/src/ws28xxdisplaymatrix.cpp +++ b/lib-ws28xxdisplay/src/ws28xxdisplaymatrix.cpp @@ -2,7 +2,7 @@ * @file ws28xxmatrix.cpp * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,7 +38,7 @@ using namespace pixel; -// FIXME Currently working for single row only +///< Note: Currently working for single row only WS28xxDisplayMatrix::WS28xxDisplayMatrix(uint8_t nColumns, uint8_t nRows, Type tLedType, Map tRGBMapping): m_nColumns(nColumns), @@ -65,7 +65,7 @@ WS28xxDisplayMatrix::WS28xxDisplayMatrix(uint8_t nColumns, uint8_t nRows, Type t pixelConfiguration.SetCount(m_nMaxLeds); - m_pWS28xx = new WS28xx(&pixelConfiguration); + m_pWS28xx = new WS28xx; assert(m_pWS28xx != nullptr); m_pWS28xx->Blackout(); @@ -186,7 +186,7 @@ void WS28xxDisplayMatrix::ClearLine(uint8_t nLine) { } for (uint32_t i = 0; i < m_nMaxLeds; i++) { - m_pWS28xx->SetPixel(i, 0, 0, 0); // FIXME Currently working for single row only + m_pWS28xx->SetPixel(i, 0, 0, 0); ///< Note: Currently working for single row only } SetCursorPos(0, static_cast(nLine - 1)); diff --git a/lib-ws28xxdmx/include/pixeldmxconfiguration.h b/lib-ws28xxdmx/include/pixeldmxconfiguration.h index c0c7351e4..49bfbb195 100644 --- a/lib-ws28xxdmx/include/pixeldmxconfiguration.h +++ b/lib-ws28xxdmx/include/pixeldmxconfiguration.h @@ -2,7 +2,7 @@ * @file pixeldmxconfiguration.h * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -22,6 +22,12 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ +/** + * Static Local Variables: + * Since C++11, the initialization of function-local static variables, is guaranteed to be thread-safe. + * This means that even if multiple threads attempt to access Get() simultaneously, + * the C++ runtime ensures that the instance is initialized only once. + */ #ifndef PIXELDMXCONFIGURATION_H_ #define PIXELDMXCONFIGURATION_H_ @@ -29,6 +35,7 @@ #include #include #include +#include #include "pixelconfiguration.h" @@ -43,6 +50,15 @@ struct PortInfo { class PixelDmxConfiguration: public PixelConfiguration { public: + PixelDmxConfiguration() { + DEBUG_ENTRY + + assert(s_pThis == nullptr); + s_pThis = this; + + DEBUG_EXIT + } + void SetOutputPorts(const uint16_t nOutputPorts) { m_nOutputPorts = nOutputPorts; } @@ -67,6 +83,10 @@ class PixelDmxConfiguration: public PixelConfiguration { return m_nUniverses; } + pixeldmxconfiguration::PortInfo& GetPortInfo() { + return m_portInfo; + } + void SetDmxStartAddress(const uint16_t nDmxStartAddress) { m_nDmxStartAddress = nDmxStartAddress; } @@ -79,70 +99,82 @@ class PixelDmxConfiguration: public PixelConfiguration { return m_nDmxFootprint; } - void Validate(const uint32_t nPortsMax, uint32_t& nLedsPerPixel, pixeldmxconfiguration::PortInfo& portInfo) { + void Validate(const uint32_t nPortsMax) { DEBUG_ENTRY - PixelConfiguration::Validate(nLedsPerPixel); + PixelConfiguration::Validate(); - if (!IsRTZProtocol()) { - const auto type = GetType(); - if (!((type == pixel::Type::WS2801) || (type == pixel::Type::APA102) || (type == pixel::Type::SK9822))) { - SetType(pixel::Type::WS2801); + if (!PixelConfiguration::IsRTZProtocol()) { + if (!((PixelConfiguration::GetType() == pixel::Type::WS2801) || (PixelConfiguration::GetType() == pixel::Type::APA102) || (PixelConfiguration::GetType() == pixel::Type::SK9822))) { + PixelConfiguration::SetType(pixel::Type::WS2801); } - PixelConfiguration::Validate(nLedsPerPixel); + PixelConfiguration::Validate(); } - portInfo.nBeginIndexPort[0] = 0; + m_portInfo.nBeginIndexPort[0] = 0; - if (GetType() == pixel::Type::SK6812W) { - portInfo.nBeginIndexPort[1] = 128; - portInfo.nBeginIndexPort[2] = 256; - portInfo.nBeginIndexPort[3] = 384; + if (PixelConfiguration::GetType() == pixel::Type::SK6812W) { + m_portInfo.nBeginIndexPort[1] = 128; + m_portInfo.nBeginIndexPort[2] = 256; + m_portInfo.nBeginIndexPort[3] = 384; } else { - portInfo.nBeginIndexPort[1] = 170; - portInfo.nBeginIndexPort[2] = 340; - portInfo.nBeginIndexPort[3] = 510; + m_portInfo.nBeginIndexPort[1] = 170; + m_portInfo.nBeginIndexPort[2] = 340; + m_portInfo.nBeginIndexPort[3] = 510; } - if ((m_nGroupingCount == 0) || (m_nGroupingCount > GetCount())) { + if ((m_nGroupingCount == 0) || (m_nGroupingCount > PixelConfiguration::GetCount())) { m_nGroupingCount = PixelConfiguration::GetCount(); } m_nGroups = PixelConfiguration::GetCount() / m_nGroupingCount; m_nOutputPorts = std::min(nPortsMax, m_nOutputPorts); - m_nUniverses = static_cast(1U + (m_nGroups / (1U + portInfo.nBeginIndexPort[1]))); - m_nDmxFootprint = static_cast(nLedsPerPixel * m_nGroups); + m_nUniverses = (1U + (m_nGroups / (1U + m_portInfo.nBeginIndexPort[1]))); + m_nDmxFootprint = PixelConfiguration::GetLedsPerPixel() * m_nGroups; if (nPortsMax == 1) { - portInfo.nProtocolPortIndexLast = static_cast(m_nGroups / (1U + portInfo.nBeginIndexPort[1])); + m_portInfo.nProtocolPortIndexLast = static_cast(m_nGroups / (1U + m_portInfo.nBeginIndexPort[1])); } else { #if defined (NODE_DDP_DISPLAY) - portInfo.nProtocolPortIndexLast = static_cast(((m_nOutputPorts - 1U) * 4U) + m_nUniverses - 1U); + m_portInfo.nProtocolPortIndexLast = static_cast(((m_nOutputPorts - 1U) * 4U) + m_nUniverses - 1U); #else - portInfo.nProtocolPortIndexLast = static_cast((m_nOutputPorts * m_nUniverses) - 1U); + m_portInfo.nProtocolPortIndexLast = static_cast((m_nOutputPorts * m_nUniverses) - 1U); #endif } - DEBUG_PRINTF("portInfo.nProtocolPortIndexLast=%u", portInfo.nProtocolPortIndexLast); DEBUG_EXIT } void Print() { PixelConfiguration::Print(); - puts("Pixel DMX configuration"); - printf(" Outputs : %d\n", m_nOutputPorts); - printf(" Grouping count : %d [Groups : %d]\n", m_nGroupingCount, m_nGroups); + printf(" Outputs : %u\n", m_nOutputPorts); + printf(" Grouping count : %u [Groups : %u]\n", m_nGroupingCount, m_nGroups); + printf(" Universes : %u\n", m_nUniverses); + printf(" DmxFootprint : %u\n", m_nDmxFootprint); + +#ifndef NDEBUG + const auto& beginIndexPort = m_portInfo.nBeginIndexPort; + printf(" %u:%u:%u:%u -> %u\n", beginIndexPort[0], beginIndexPort[1], beginIndexPort[2], beginIndexPort[3], m_portInfo.nProtocolPortIndexLast); +#endif + } + + static PixelDmxConfiguration& Get() { + assert(s_pThis != nullptr); // Ensure that s_pThis is valid + return *s_pThis; } private: uint32_t m_nOutputPorts { 1 }; uint32_t m_nGroupingCount { 1 }; uint32_t m_nGroups { pixel::defaults::COUNT }; - uint32_t m_nUniverses; + uint32_t m_nUniverses { 0 }; uint32_t m_nDmxStartAddress { 1 }; - uint32_t m_nDmxFootprint; + uint32_t m_nDmxFootprint { 0 }; + pixeldmxconfiguration::PortInfo m_portInfo; + + static inline PixelDmxConfiguration *s_pThis { nullptr }; }; #endif /* PIXELDMXCONFIGURATION_H_ */ diff --git a/lib-ws28xxdmx/include/pixeldmxparams.h b/lib-ws28xxdmx/include/pixeldmxparams.h index 92190d4b5..9257d6c00 100644 --- a/lib-ws28xxdmx/include/pixeldmxparams.h +++ b/lib-ws28xxdmx/include/pixeldmxparams.h @@ -98,7 +98,7 @@ class PixelDmxParams { Builder(nullptr, pBuffer, nLength, nSize); } - void Set(PixelDmxConfiguration *pPixelDmxConfiguration); + void Set(); uint16_t GetStartUniversePort(uint32_t nOutputPortIndex, bool& isSet) const { if (nOutputPortIndex < pixeldmxparams::MAX_PORTS) { diff --git a/lib-ws28xxdmx/include/pixeldmxparamsrdm.h b/lib-ws28xxdmx/include/pixeldmxparamsrdm.h index 5ebbe69be..6edc66eb7 100644 --- a/lib-ws28xxdmx/include/pixeldmxparamsrdm.h +++ b/lib-ws28xxdmx/include/pixeldmxparamsrdm.h @@ -64,7 +64,7 @@ class PixelDmxParamsRdm final: public LightSet { void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; void Sync([[maybe_unused]] const uint32_t nPortIndex) override {} - void Sync([[maybe_unused]] const bool doForce) override {} + void Sync() override {} bool SetDmxStartAddress([[maybe_unused]] uint16_t nDmxStartAddress) override { return false; diff --git a/lib-ws28xxdmx/include/ws28xxdmx.h b/lib-ws28xxdmx/include/ws28xxdmx.h index 69975d91b..80f0fe42b 100644 --- a/lib-ws28xxdmx/include/ws28xxdmx.h +++ b/lib-ws28xxdmx/include/ws28xxdmx.h @@ -38,7 +38,7 @@ class WS28xxDmx final: public LightSet { public: - WS28xxDmx(PixelDmxConfiguration *pPixelDmxConfiguration); + WS28xxDmx(); ~WS28xxDmx() override; void Start(const uint32_t nPortIndex) override; @@ -46,11 +46,9 @@ class WS28xxDmx final: public LightSet { void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; void Sync([[maybe_unused]] const uint32_t nPortIndex) override {} - void Sync(const bool doForce) override { - if (__builtin_expect((!doForce), 1)) { - assert(m_pWS28xx != nullptr); - m_pWS28xx->Update(); - } + void Sync() override { + assert(m_pWS28xx != nullptr); + m_pWS28xx->Update(); } #if defined (OUTPUT_HAVE_STYLESWITCH) @@ -64,42 +62,18 @@ class WS28xxDmx final: public LightSet { void FullOn() override; void Print() override { - m_pPixelDmxConfiguration->Print(); - } - - pixel::Type GetType() const { - return m_pPixelDmxConfiguration->GetType(); - } - - pixel::Map GetMap() const { - return m_pPixelDmxConfiguration->GetMap(); - } - - uint32_t GetCount() const { - return m_pPixelDmxConfiguration->GetCount(); - } - - uint32_t GetGroups() const { - return m_pPixelDmxConfiguration->GetGroups(); - } - - uint32_t GetGroupingCount() const { - return m_pPixelDmxConfiguration->GetGroupingCount(); - } - - uint32_t GetUniverses() const { - return m_pPixelDmxConfiguration->GetUniverses(); + PixelDmxConfiguration::Get().Print(); } // RDM bool SetDmxStartAddress(uint16_t nDmxStartAddress) override; uint16_t GetDmxStartAddress() override { - return m_pPixelDmxConfiguration->GetDmxStartAddress(); + return PixelDmxConfiguration::Get().GetDmxStartAddress(); } uint16_t GetDmxFootprint() override { - return m_pPixelDmxConfiguration->GetDmxFootprint(); + return PixelDmxConfiguration::Get().GetDmxFootprint(); } bool GetSlotInfo(uint16_t nSlotOffset, lightset::SlotInfo &tSlotInfo) override; @@ -109,10 +83,6 @@ class WS28xxDmx final: public LightSet { } private: - PixelDmxConfiguration *m_pPixelDmxConfiguration; - pixeldmxconfiguration::PortInfo m_PortInfo; - uint32_t m_nChannelsPerPixel; - WS28xx *m_pWS28xx { nullptr }; bool m_bIsStarted { false }; diff --git a/lib-ws28xxdmx/include/ws28xxdmxmulti.h b/lib-ws28xxdmx/include/ws28xxdmxmulti.h index c7370528d..ebbf18091 100644 --- a/lib-ws28xxdmx/include/ws28xxdmxmulti.h +++ b/lib-ws28xxdmx/include/ws28xxdmxmulti.h @@ -48,7 +48,7 @@ static constexpr auto MAX_PORTS = CONFIG_PIXELDMX_MAX_PORTS; class WS28xxDmxMulti final: public LightSet { public: - WS28xxDmxMulti(PixelDmxConfiguration& pixelDmxConfiguration); + WS28xxDmxMulti(); ~WS28xxDmxMulti() override; void Start(const uint32_t nPortIndex) override; @@ -62,10 +62,13 @@ class WS28xxDmxMulti final: public LightSet { return; } - if (nPortIndex == m_PortInfo.nProtocolPortIndexLast) { + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + auto &portInfo = pixelDmxConfiguration.GetPortInfo(); + + if (nPortIndex == portInfo.nProtocolPortIndexLast) { logic_analyzer::ch1_set(); - for (uint32_t nIndex = 0 ; nIndex <= m_PortInfo.nProtocolPortIndexLast;nIndex++) { + for (uint32_t nIndex = 0 ; nIndex <= portInfo.nProtocolPortIndexLast;nIndex++) { logic_analyzer::ch2_set(); SetData(nIndex, lightset::Data::Backup(nIndex), lightset::Data::GetLength(nIndex)); logic_analyzer::ch2_clear(); @@ -97,22 +100,19 @@ class WS28xxDmxMulti final: public LightSet { logic_analyzer::ch2_clear(); } - void Sync(const bool doForce) override { - if (__builtin_expect((!doForce), 1)) { - logic_analyzer::ch1_set(); + void Sync() override { + logic_analyzer::ch1_set(); + logic_analyzer::ch3_set(); - logic_analyzer::ch3_set(); + while (m_pWS28xxMulti->IsUpdating()) { + // wait for completion + } - while (m_pWS28xxMulti->IsUpdating()) { - // wait for completion - } + logic_analyzer::ch3_clear(); - logic_analyzer::ch3_clear(); + m_pWS28xxMulti->Update(); - m_pWS28xxMulti->Update(); - - logic_analyzer::ch1_clear(); - } + logic_analyzer::ch1_clear(); } #if defined (OUTPUT_HAVE_STYLESWITCH) @@ -126,39 +126,7 @@ class WS28xxDmxMulti final: public LightSet { void FullOn() override; void Print() override { - m_pixelDmxConfiguration.Print(); - } - - pixel::Type GetType() const { - return m_pixelDmxConfiguration.GetType(); - } - - pixel::Map GetMap() const { - return m_pixelDmxConfiguration.GetMap(); - } - - uint32_t GetCount() const { - return m_pixelDmxConfiguration.GetCount(); - } - - uint32_t GetGroups() const { - return m_pixelDmxConfiguration.GetGroups(); - } - - uint32_t GetGroupingCount() const { - return m_pixelDmxConfiguration.GetGroupingCount(); - } - - uint32_t GetUniverses() const { - return m_pixelDmxConfiguration.GetUniverses(); - } - - uint32_t GetOutputPorts() const { - return m_pixelDmxConfiguration.GetOutputPorts(); - } - - uint32_t GetChannelsPerPixel() const { - return m_nChannelsPerPixel; + PixelDmxConfiguration::Get().Print(); } // RDMNet LLRP Device Only @@ -178,10 +146,6 @@ class WS28xxDmxMulti final: public LightSet { void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength); private: - PixelDmxConfiguration m_pixelDmxConfiguration; - pixeldmxconfiguration::PortInfo m_PortInfo; - uint32_t m_nChannelsPerPixel; - WS28xxMulti *m_pWS28xxMulti { nullptr }; uint32_t m_bIsStarted { 0 }; diff --git a/lib-ws28xxdmx/src/dmx/ws28xxdmx.cpp b/lib-ws28xxdmx/src/dmx/ws28xxdmx.cpp index 15bcec3b4..a7bdc0d55 100755 --- a/lib-ws28xxdmx/src/dmx/ws28xxdmx.cpp +++ b/lib-ws28xxdmx/src/dmx/ws28xxdmx.cpp @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + #pragma GCC push_options #pragma GCC optimize ("O3") #pragma GCC optimize ("-funroll-loops") @@ -48,15 +52,15 @@ WS28xxDmx *WS28xxDmx::s_pThis; -WS28xxDmx::WS28xxDmx(PixelDmxConfiguration *pPixelDmxConfiguration): m_pPixelDmxConfiguration(pPixelDmxConfiguration) { +WS28xxDmx::WS28xxDmx() { DEBUG_ENTRY assert(s_pThis == nullptr); s_pThis = this; - m_pPixelDmxConfiguration->Validate(1 , m_nChannelsPerPixel, m_PortInfo); + PixelDmxConfiguration::Get().Validate(1); - m_pWS28xx = new WS28xx(m_pPixelDmxConfiguration); + m_pWS28xx = new WS28xx(); assert(m_pWS28xx != nullptr); m_pWS28xx->Blackout(); @@ -109,6 +113,8 @@ void WS28xxDmx::SetData([[maybe_unused]] uint32_t nPortIndex, const uint8_t *pDa return; } + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + auto &portInfo = pixelDmxConfiguration.GetPortInfo(); uint32_t d = 0; #if !defined(LIGHTSET_PORTS) @@ -116,22 +122,23 @@ void WS28xxDmx::SetData([[maybe_unused]] uint32_t nPortIndex, const uint8_t *pDa #else const auto nSwitch = nPortIndex & 0x03; #endif - const auto nGroups = m_pPixelDmxConfiguration->GetGroups(); + const auto nGroups = pixelDmxConfiguration.GetGroups(); #if !defined(LIGHTSET_PORTS) static constexpr uint32_t beginIndex = 0; #else - const auto beginIndex = m_PortInfo.nBeginIndexPort[nSwitch]; + const auto beginIndex = portInfo.nBeginIndexPort[nSwitch]; #endif - const auto endIndex = std::min(nGroups, (beginIndex + (nLength / m_nChannelsPerPixel))); + const auto nChannelsPerPixel = pixelDmxConfiguration.GetLedsPerPixel(); + const auto endIndex = std::min(nGroups, (beginIndex + (nLength / nChannelsPerPixel))); - if ((nSwitch == 0) && (nGroups < m_PortInfo.nBeginIndexPort[1])) { - d = (m_pPixelDmxConfiguration->GetDmxStartAddress() - 1U); + if ((nSwitch == 0) && (nGroups < portInfo.nBeginIndexPort[1])) { + d = (pixelDmxConfiguration.GetDmxStartAddress() - 1U); } - const auto nGroupingCount = m_pPixelDmxConfiguration->GetGroupingCount(); + const auto nGroupingCount = pixelDmxConfiguration.GetGroupingCount(); - if (m_nChannelsPerPixel == 3) { - switch (m_pPixelDmxConfiguration->GetMap()) { + if (nChannelsPerPixel == 3) { + switch (pixelDmxConfiguration.GetMap()) { case pixel::Map::RGB: for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { auto const nPixelIndexStart = (j * nGroupingCount); @@ -192,7 +199,7 @@ void WS28xxDmx::SetData([[maybe_unused]] uint32_t nPortIndex, const uint8_t *pDa break; } } else { - assert(m_nChannelsPerPixel == 4); + assert(nChannelsPerPixel == 4); for (auto j = beginIndex; (j < endIndex) && (d < nLength); j++) { auto const nPixelIndexStart = (j * nGroupingCount); for (uint32_t k = 0; k < nGroupingCount; k++) { @@ -205,7 +212,7 @@ void WS28xxDmx::SetData([[maybe_unused]] uint32_t nPortIndex, const uint8_t *pDa #if !defined(LIGHTSET_PORTS) if (doUpdate) { #else - if ((doUpdate) && (nPortIndex == m_PortInfo.nProtocolPortIndexLast)) { + if ((doUpdate) && (nPortIndex == portInfo.nProtocolPortIndexLast)) { #endif if (__builtin_expect((m_bBlackout), 0)) { return; @@ -241,16 +248,18 @@ void WS28xxDmx::FullOn() { bool WS28xxDmx::SetDmxStartAddress(uint16_t nDmxStartAddress) { assert((nDmxStartAddress != 0) && (nDmxStartAddress <= lightset::dmx::UNIVERSE_SIZE)); - if (nDmxStartAddress == m_pPixelDmxConfiguration->GetDmxStartAddress()) { + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + + if (nDmxStartAddress == pixelDmxConfiguration.GetDmxStartAddress()) { return true; } - if ((nDmxStartAddress + m_pPixelDmxConfiguration->GetDmxFootprint()) > lightset::dmx::UNIVERSE_SIZE) { + if ((nDmxStartAddress + pixelDmxConfiguration.GetDmxFootprint()) > lightset::dmx::UNIVERSE_SIZE) { return false; } if ((nDmxStartAddress != 0) && (nDmxStartAddress <= lightset::dmx::UNIVERSE_SIZE)) { - m_pPixelDmxConfiguration->SetDmxStartAddress(nDmxStartAddress); + pixelDmxConfiguration.SetDmxStartAddress(nDmxStartAddress); PixelDmxStore::SaveDmxStartAddress(nDmxStartAddress); return true; } @@ -261,13 +270,15 @@ bool WS28xxDmx::SetDmxStartAddress(uint16_t nDmxStartAddress) { // RDM bool WS28xxDmx::GetSlotInfo(uint16_t nSlotOffset, lightset::SlotInfo& slotInfo) { - if (nSlotOffset > m_pPixelDmxConfiguration->GetDmxFootprint()) { + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + + if (nSlotOffset > pixelDmxConfiguration.GetDmxFootprint()) { return false; } slotInfo.nType = 0x00; // ST_PRIMARY - switch (nSlotOffset % m_nChannelsPerPixel) { + switch (nSlotOffset % pixelDmxConfiguration.GetLedsPerPixel()) { case 0: slotInfo.nCategory = 0x0205; // SD_COLOR_ADD_RED break; diff --git a/lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti._cpp b/lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti._cpp new file mode 100755 index 000000000..35524818a --- /dev/null +++ b/lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti._cpp @@ -0,0 +1,189 @@ +/** + * @file ws28xxdmxmulti.cpp + * + */ +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + +#pragma GCC push_options +#pragma GCC optimize ("O3") +#pragma GCC optimize ("-funroll-loops") +#pragma GCC optimize ("-fprefetch-loop-arrays") + +#include +#include +#include + +#include "ws28xxdmxmulti.h" +#include "ws28xxmulti.h" +#include "ws28xx.h" + +#include "pixeldmxparams.h" +#include "pixeldmxconfiguration.h" + +#if defined (PIXELDMXSTARTSTOP_GPIO) +# include "hal_gpio.h" +#endif + +#include "debug.h" + +WS28xxDmxMulti::WS28xxDmxMulti(PixelDmxConfiguration& pixelDmxConfiguration): m_pixelDmxConfiguration(pixelDmxConfiguration){ + DEBUG_ENTRY + + m_pixelDmxConfiguration.Validate(ws28xxdmxmulti::MAX_PORTS , m_nChannelsPerPixel, m_PortInfo); + + m_pWS28xxMulti = new WS28xxMulti(pixelDmxConfiguration); + assert(m_pWS28xxMulti != nullptr); + m_pWS28xxMulti->Blackout(); + +#if defined (PIXELDMXSTARTSTOP_GPIO) + FUNC_PREFIX(gpio_fsel(PIXELDMXSTARTSTOP_GPIO, GPIO_FSEL_OUTPUT)); + FUNC_PREFIX(gpio_clr(PIXELDMXSTARTSTOP_GPIO)); +#endif + + DEBUG_EXIT +} + +WS28xxDmxMulti::~WS28xxDmxMulti() { + delete m_pWS28xxMulti; + m_pWS28xxMulti = nullptr; +} + +void WS28xxDmxMulti::Start(const uint32_t nPortIndex) { + DEBUG_PRINTF("%u", nPortIndex); + + if (m_bIsStarted == 0) { +#if defined (PIXELDMXSTARTSTOP_GPIO) + FUNC_PREFIX(gpio_set(PIXELDMXSTARTSTOP_GPIO)); +#endif + } + + m_bIsStarted |= (1U << nPortIndex); +} + +void WS28xxDmxMulti::Stop(const uint32_t nPortIndex) { + DEBUG_PRINTF("%u", nPortIndex); + + if (m_bIsStarted & (1U << nPortIndex)) { + m_bIsStarted &= ~(1U << nPortIndex); + } + + if (m_bIsStarted == 0) { +#if defined (PIXELDMXSTARTSTOP_GPIO) + FUNC_PREFIX(gpio_clr(PIXELDMXSTARTSTOP_GPIO)); +#endif + } +} + +void WS28xxDmxMulti::SetData(const uint32_t nPortIndex, const uint8_t* pData, uint32_t nLength) { + assert(pData != nullptr); + assert(nLength <= lightset::dmx::UNIVERSE_SIZE); + +#if defined (NODE_DDP_DISPLAY) + const auto nOutIndex = (nPortIndex / 4); + const auto nSwitch = nPortIndex - (nOutIndex * 4); +#else + const auto nUniverses = m_pixelDmxConfiguration.GetUniverses(); + const auto nOutIndex = (nPortIndex / nUniverses); + const auto nSwitch = nPortIndex - (nOutIndex * nUniverses); +#endif + + const auto nGroups = m_pixelDmxConfiguration.GetGroups(); + const auto beginIndex = m_PortInfo.nBeginIndexPort[nSwitch]; + const auto endIndex = std::min(nGroups, (beginIndex + (nLength / m_nChannelsPerPixel))); + + uint32_t d = 0; + + const auto nGroupingCount = m_pixelDmxConfiguration.GetGroupingCount(); + + if (m_nChannelsPerPixel == 3) { + // Define a lambda to handle pixel setting based on color order + auto setPixelColor3 = [&](uint32_t r, uint32_t g, uint32_t b) { + for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { + auto const nPixelIndexStart = j * nGroupingCount; + for (uint32_t k = 0; k < nGroupingCount; k++) { + m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, r, g, b); + } + d += 3; // Increment by 3 since we're processing 3 channels per pixel + } + }; + + switch (m_pixelDmxConfiguration.GetMap()) { + case pixel::Map::RGB: + setPixelColor3(pData[d + 0], pData[d + 1], pData[d + 2]); + break; + case pixel::Map::RBG: + setPixelColor3(pData[d + 0], pData[d + 2], pData[d + 1]); + break; + case pixel::Map::GRB: + setPixelColor3(pData[d + 1], pData[d + 0], pData[d + 2]); + break; + case pixel::Map::GBR: + setPixelColor3(pData[d + 2], pData[d + 0], pData[d + 1]); + break; + case pixel::Map::BRG: + setPixelColor3(pData[d + 1], pData[d + 2], pData[d + 0]); + break; + case pixel::Map::BGR: + setPixelColor3(pData[d + 2], pData[d + 1], pData[d + 0]); + break; + default: + assert(0); + __builtin_unreachable(); + break; + } + } else { + assert(m_nChannelsPerPixel == 4); + for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { + auto const nPixelIndexStart = (j * nGroupingCount); + for (uint32_t k = 0; k < nGroupingCount; k++) { + m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d], pData[d + 1], pData[d + 2], pData[d + 3]); + } + d = d + 4; + } + } +} + +void WS28xxDmxMulti::Blackout(bool bBlackout) { + m_bBlackout = bBlackout; + + while (m_pWS28xxMulti->IsUpdating()) { + // wait for completion + } + + if (bBlackout) { + m_pWS28xxMulti->Blackout(); + } else { + m_pWS28xxMulti->Update(); + } +} + +void WS28xxDmxMulti::FullOn() { + while (m_pWS28xxMulti->IsUpdating()) { + // wait for completion + } + + m_pWS28xxMulti->FullOn(); +} diff --git a/lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti.cpp b/lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti.cpp index ba3a87331..2c41033b9 100755 --- a/lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti.cpp +++ b/lib-ws28xxdmx/src/dmxmulti/ws28xxdmxmulti.cpp @@ -2,7 +2,7 @@ * @file ws28xxdmxmulti.cpp * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + #pragma GCC push_options #pragma GCC optimize ("O3") #pragma GCC optimize ("-funroll-loops") @@ -45,12 +49,12 @@ #include "debug.h" -WS28xxDmxMulti::WS28xxDmxMulti(PixelDmxConfiguration& pixelDmxConfiguration): m_pixelDmxConfiguration(pixelDmxConfiguration){ +WS28xxDmxMulti::WS28xxDmxMulti() { DEBUG_ENTRY - m_pixelDmxConfiguration.Validate(ws28xxdmxmulti::MAX_PORTS , m_nChannelsPerPixel, m_PortInfo); + PixelDmxConfiguration::Get().Validate(ws28xxdmxmulti::MAX_PORTS); - m_pWS28xxMulti = new WS28xxMulti(pixelDmxConfiguration); + m_pWS28xxMulti = new WS28xxMulti(); assert(m_pWS28xxMulti != nullptr); m_pWS28xxMulti->Blackout(); @@ -97,78 +101,103 @@ void WS28xxDmxMulti::SetData(const uint32_t nPortIndex, const uint8_t* pData, ui assert(pData != nullptr); assert(nLength <= lightset::dmx::UNIVERSE_SIZE); + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + #if defined (NODE_DDP_DISPLAY) const auto nOutIndex = (nPortIndex / 4); const auto nSwitch = nPortIndex - (nOutIndex * 4); #else - const auto nUniverses = m_pixelDmxConfiguration.GetUniverses(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); const auto nOutIndex = (nPortIndex / nUniverses); const auto nSwitch = nPortIndex - (nOutIndex * nUniverses); #endif - const auto nGroups = m_pixelDmxConfiguration.GetGroups(); - const auto beginIndex = m_PortInfo.nBeginIndexPort[nSwitch]; - const auto endIndex = std::min(nGroups, (beginIndex + (nLength / m_nChannelsPerPixel))); + auto &portInfo = pixelDmxConfiguration.GetPortInfo(); - uint32_t d = 0; + const auto nGroups = pixelDmxConfiguration.GetGroups(); + const auto beginIndex = portInfo.nBeginIndexPort[nSwitch]; + const auto nChannelsPerPixel = pixelDmxConfiguration.GetLedsPerPixel(); + const auto endIndex = std::min(nGroups, (beginIndex + (nLength / nChannelsPerPixel))); + const auto nGroupingCount = pixelDmxConfiguration.GetGroupingCount(); + const auto pixelType = pixelDmxConfiguration.GetType(); + const auto isRTZProtocol = pixelDmxConfiguration.IsRTZProtocol(); - const auto nGroupingCount = m_pixelDmxConfiguration.GetGroupingCount(); + uint32_t d = 0; - if (m_nChannelsPerPixel == 3) { - switch (m_pixelDmxConfiguration.GetMap()) { - case pixel::Map::RGB: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 0], pData[d + 1], pData[d + 2]); + if (nChannelsPerPixel == 3) { + // Define a lambda to handle pixel setting based on color order + auto setPixelsColor3 = [&](uint32_t r, uint32_t g, uint32_t b) { +#if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) + const auto pGammaTable = m_pWS28xxMulti->m_PixelConfiguration.GetGammaTable(); + r = pGammaTable[r]; + g = pGammaTable[g]; + b = pGammaTable[b]; +#endif + if (isRTZProtocol) { + for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { + auto const nPixelIndexStart = j * nGroupingCount; + for (uint32_t k = 0; k < nGroupingCount; k++) { + m_pWS28xxMulti->SetColourRTZ(nOutIndex, nPixelIndexStart + k, r, g, b); + } + d += 3; // Increment by 3 since we're processing 3 channels per pixel + } + } else { + switch (pixelType) { + case pixel::Type::WS2801: + for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { + auto const nPixelIndexStart = j * nGroupingCount; + for (uint32_t k = 0; k < nGroupingCount; k++) { + m_pWS28xxMulti->SetColourWS2801(nOutIndex, nPixelIndexStart + k, r, g, b); + } + d += 3; // Increment by 3 since we're processing 3 channels per pixel + } + break; + case pixel::Type::APA102: + case pixel::Type::SK9822: + for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { + auto const nPixelIndexStart = j * nGroupingCount; + for (uint32_t k = 0; k < nGroupingCount; k++) { + m_pWS28xxMulti->SetPixel4Bytes(nOutIndex, 1 + nPixelIndexStart + k, pixelDmxConfiguration.GetGlobalBrightness(), b, g, r); + } + d += 3; // Increment by 3 since we're processing 3 channels per pixel + } + break; + case pixel::Type::P9813: + for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { + auto const nPixelIndexStart = j * nGroupingCount; + for (uint32_t k = 0; k < nGroupingCount; k++) { + const auto nFlag = static_cast(0xC0 | ((~b & 0xC0) >> 2) | ((~r & 0xC0) >> 4) | ((~r & 0xC0) >> 6)); + m_pWS28xxMulti->SetPixel4Bytes(nOutIndex, 1 + nPixelIndexStart + k, nFlag, b, g, r); + } + d += 3; // Increment by 3 since we're processing 3 channels per pixel + } + break; + default: + assert(0); + __builtin_unreachable(); + break; } - d = d + 3; } + }; + + switch (pixelDmxConfiguration.GetMap()) { + case pixel::Map::RGB: + setPixelsColor3(pData[d + 0], pData[d + 1], pData[d + 2]); break; case pixel::Map::RBG: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 0], pData[d + 2], pData[d + 1]); - } - d = d + 3; - } + setPixelsColor3(pData[d + 0], pData[d + 2], pData[d + 1]); break; case pixel::Map::GRB: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 1], pData[d + 0], pData[d + 2]); - } - d = d + 3; - } + setPixelsColor3(pData[d + 1], pData[d + 0], pData[d + 2]); break; case pixel::Map::GBR: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 2], pData[d + 0], pData[d + 1]); - } - d = d + 3; - } + setPixelsColor3(pData[d + 2], pData[d + 0], pData[d + 1]); break; case pixel::Map::BRG: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 1], pData[d + 2], pData[d + 0]); - } - d = d + 3; - } + setPixelsColor3(pData[d + 1], pData[d + 2], pData[d + 0]); break; case pixel::Map::BGR: - for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { - auto const nPixelIndexStart = (j * nGroupingCount); - for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d + 2], pData[d + 1], pData[d + 0]); - } - d = d + 3; - } + setPixelsColor3(pData[d + 2], pData[d + 1], pData[d + 0]); break; default: assert(0); @@ -176,13 +205,14 @@ void WS28xxDmxMulti::SetData(const uint32_t nPortIndex, const uint8_t* pData, ui break; } } else { - assert(m_nChannelsPerPixel == 4); + assert(nChannelsPerPixel == 4); + assert(isRTZProtocol); for (uint32_t j = beginIndex; (j < endIndex) && (d < nLength); j++) { auto const nPixelIndexStart = (j * nGroupingCount); for (uint32_t k = 0; k < nGroupingCount; k++) { - m_pWS28xxMulti->SetPixel(nOutIndex, nPixelIndexStart + k, pData[d], pData[d + 1], pData[d + 2], pData[d + 3]); + m_pWS28xxMulti->SetColourRTZ(nOutIndex, nPixelIndexStart + k, pData[d], pData[d + 1], pData[d + 2], pData[d + 3]); } - d = d + 4; + d = d + 4; // Increment by 4 since we're processing 4 channels per pixel } } } diff --git a/lib-ws28xxdmx/src/params/pixeldmxparams.cpp b/lib-ws28xxdmx/src/params/pixeldmxparams.cpp index 40b64b2ec..6cdd42ccd 100644 --- a/lib-ws28xxdmx/src/params/pixeldmxparams.cpp +++ b/lib-ws28xxdmx/src/params/pixeldmxparams.cpp @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + #if !defined(__clang__) // Needed for compiling on MacOS # pragma GCC push_options # pragma GCC optimize ("Os") @@ -126,7 +130,7 @@ void PixelDmxParams::callbackFunction(const char *pLine) { if (Sscan::Char(pLine, DevicesParamsConst::TYPE, cBuffer, nLength) == Sscan::OK) { cBuffer[nLength] = '\0'; - const auto type = PixelType::GetType(cBuffer); + const auto type = pixel::pixel_get_type(cBuffer); if (type != pixel::Type::UNDEFINED) { m_Params.nType = static_cast(type); @@ -153,7 +157,7 @@ void PixelDmxParams::callbackFunction(const char *pLine) { if (Sscan::Char(pLine, DevicesParamsConst::MAP, cBuffer, nLength) == Sscan::OK) { cBuffer[nLength] = '\0'; - const auto map = PixelType::GetMap(cBuffer); + const auto map = pixel::pixel_get_map(cBuffer); if (map != Map::UNDEFINED) { m_Params.nSetList |= pixeldmxparams::Mask::MAP; @@ -166,7 +170,7 @@ void PixelDmxParams::callbackFunction(const char *pLine) { } if (Sscan::Float(pLine, DevicesParamsConst::LED_T0H, fValue) == Sscan::OK) { - if ((nValue8 = PixelType::ConvertTxH(fValue)) != 0) { + if ((nValue8 = pixel::pixel_convert_TxH(fValue)) != 0) { m_Params.nSetList |= pixeldmxparams::Mask::LOW_CODE; } else { m_Params.nSetList &= ~pixeldmxparams::Mask::LOW_CODE; @@ -177,7 +181,7 @@ void PixelDmxParams::callbackFunction(const char *pLine) { } if (Sscan::Float(pLine, DevicesParamsConst::LED_T1H, fValue) == Sscan::OK) { - if ((nValue8 = PixelType::ConvertTxH(fValue)) != 0) { + if ((nValue8 = pixel::pixel_convert_TxH(fValue)) != 0) { m_Params.nSetList |= pixeldmxparams::Mask::HIGH_CODE; } else { m_Params.nSetList &= ~pixeldmxparams::Mask::HIGH_CODE; @@ -303,7 +307,7 @@ void PixelDmxParams::Builder(const struct pixeldmxparams::Params *ptWS28xxParams PropertiesBuilder builder(DevicesParamsConst::FILE_NAME, pBuffer, nLength); - builder.Add(DevicesParamsConst::TYPE, PixelType::GetType(static_cast(m_Params.nType)), isMaskSet(pixeldmxparams::Mask::TYPE)); + builder.Add(DevicesParamsConst::TYPE, pixel::pixel_get_type(static_cast(m_Params.nType)), isMaskSet(pixeldmxparams::Mask::TYPE)); builder.Add(DevicesParamsConst::COUNT, m_Params.nCount, isMaskSet(pixeldmxparams::Mask::COUNT)); #if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) @@ -318,15 +322,15 @@ void PixelDmxParams::Builder(const struct pixeldmxparams::Params *ptWS28xxParams builder.AddComment("Overwrite datasheet"); if (!isMaskSet(pixeldmxparams::Mask::MAP)) { - m_Params.nMap = static_cast(PixelType::GetMap(static_cast(m_Params.nType))); + m_Params.nMap = static_cast(pixel::pixel_get_map(static_cast(m_Params.nType))); } - builder.Add(DevicesParamsConst::MAP, PixelType::GetMap(static_cast(m_Params.nMap)), isMaskSet(pixeldmxparams::Mask::MAP)); + builder.Add(DevicesParamsConst::MAP, pixel::pixel_get_map(static_cast(m_Params.nMap)), isMaskSet(pixeldmxparams::Mask::MAP)); if (!isMaskSet(pixeldmxparams::Mask::LOW_CODE) || !isMaskSet(pixeldmxparams::Mask::HIGH_CODE)) { uint8_t nLowCode; uint8_t nHighCode; - PixelConfiguration::GetTxH(static_cast(m_Params.nType), nLowCode, nHighCode); + PixelConfiguration::Get().GetTxH(static_cast(m_Params.nType), nLowCode, nHighCode); if (!isMaskSet(pixeldmxparams::Mask::LOW_CODE)) { m_Params.nLowCode = nLowCode; @@ -338,8 +342,8 @@ void PixelDmxParams::Builder(const struct pixeldmxparams::Params *ptWS28xxParams } builder.AddComment("Overwrite timing (us)"); - builder.Add(DevicesParamsConst::LED_T0H, PixelType::ConvertTxH(m_Params.nLowCode), isMaskSet(pixeldmxparams::Mask::LOW_CODE), 2); - builder.Add(DevicesParamsConst::LED_T1H, PixelType::ConvertTxH(m_Params.nHighCode), isMaskSet(pixeldmxparams::Mask::HIGH_CODE), 2); + builder.Add(DevicesParamsConst::LED_T0H, pixel::pixel_convert_TxH(m_Params.nLowCode), isMaskSet(pixeldmxparams::Mask::LOW_CODE), 2); + builder.Add(DevicesParamsConst::LED_T1H, pixel::pixel_convert_TxH(m_Params.nHighCode), isMaskSet(pixeldmxparams::Mask::HIGH_CODE), 2); builder.AddComment("Grouping"); builder.Add(DevicesParamsConst::GROUPING_COUNT, m_Params.nGroupingCount, isMaskSet(pixeldmxparams::Mask::GROUPING_COUNT)); @@ -370,61 +374,61 @@ void PixelDmxParams::Builder(const struct pixeldmxparams::Params *ptWS28xxParams DEBUG_PRINTF("nSize=%d", nSize); } -void PixelDmxParams::Set(PixelDmxConfiguration *pPixelDmxConfiguration) { - assert(pPixelDmxConfiguration != nullptr); - +void PixelDmxParams::Set() { // Pixel + auto& pixelConfiguration = PixelConfiguration::Get(); if (isMaskSet(pixeldmxparams::Mask::TYPE)) { - pPixelDmxConfiguration->SetType(static_cast(m_Params.nType)); + pixelConfiguration.SetType(static_cast(m_Params.nType)); } if (isMaskSet(pixeldmxparams::Mask::COUNT)) { - pPixelDmxConfiguration->SetCount(m_Params.nCount); + pixelConfiguration.SetCount(m_Params.nCount); } if (isMaskSet(pixeldmxparams::Mask::MAP)) { - pPixelDmxConfiguration->SetMap(static_cast(m_Params.nMap)); + pixelConfiguration.SetMap(static_cast(m_Params.nMap)); } if (isMaskSet(pixeldmxparams::Mask::LOW_CODE)) { - pPixelDmxConfiguration->SetLowCode(m_Params.nLowCode); + pixelConfiguration.SetLowCode(m_Params.nLowCode); } if (isMaskSet(pixeldmxparams::Mask::HIGH_CODE)) { - pPixelDmxConfiguration->SetHighCode(m_Params.nHighCode); + pixelConfiguration.SetHighCode(m_Params.nHighCode); } if (isMaskSet(pixeldmxparams::Mask::SPI_SPEED)) { - pPixelDmxConfiguration->SetClockSpeedHz(m_Params.nSpiSpeedHz); + pixelConfiguration.SetClockSpeedHz(m_Params.nSpiSpeedHz); } if (isMaskSet(pixeldmxparams::Mask::GLOBAL_BRIGHTNESS)) { - pPixelDmxConfiguration->SetGlobalBrightness(m_Params.nGlobalBrightness); + pixelConfiguration.SetGlobalBrightness(m_Params.nGlobalBrightness); } #if defined(CONFIG_PIXELDMX_ENABLE_GAMMATABLE) if (isMaskSet(pixeldmxparams::Mask::GAMMA_CORRECTION)) { - pPixelDmxConfiguration->SetEnableGammaCorrection(true); + pixelConfiguration.SetEnableGammaCorrection(true); if (m_Params.nGammaValue != 0) { - pPixelDmxConfiguration->SetGammaTable(m_Params.nGammaValue); + pixelConfiguration.SetGammaTable(m_Params.nGammaValue); } } #endif // Dmx + auto& pixelDmxConfiguration = PixelDmxConfiguration::Get(); if (isMaskSet(pixeldmxparams::Mask::DMX_START_ADDRESS)) { - pPixelDmxConfiguration->SetDmxStartAddress(m_Params.nDmxStartAddress); + pixelDmxConfiguration.SetDmxStartAddress(m_Params.nDmxStartAddress); } if (isMaskSet(pixeldmxparams::Mask::GROUPING_COUNT)) { - pPixelDmxConfiguration->SetGroupingCount(m_Params.nGroupingCount); + pixelDmxConfiguration.SetGroupingCount(m_Params.nGroupingCount); } #if defined(OUTPUT_DMX_PIXEL_MULTI) if (isMaskSet(pixeldmxparams::Mask::ACTIVE_OUT)) { - pPixelDmxConfiguration->SetOutputPorts(m_Params.nActiveOutputs); + pixelDmxConfiguration.SetOutputPorts(m_Params.nActiveOutputs); } #endif } @@ -438,10 +442,10 @@ void PixelDmxParams::staticCallbackFunction(void *p, const char *s) { void PixelDmxParams::Dump() { printf("%s::%s \'%s\':\n", __FILE__,__FUNCTION__, DevicesParamsConst::FILE_NAME); - printf(" %s=%s [%d]\n", DevicesParamsConst::TYPE, PixelType::GetType(static_cast(m_Params.nType)), static_cast(m_Params.nType)); - printf(" %s=%d [%s]\n", DevicesParamsConst::MAP, static_cast(m_Params.nMap), PixelType::GetMap(static_cast(m_Params.nMap))); - printf(" %s=%.2f [0x%X]\n", DevicesParamsConst::LED_T0H, PixelType::ConvertTxH(m_Params.nLowCode), m_Params.nLowCode); - printf(" %s=%.2f [0x%X]\n", DevicesParamsConst::LED_T1H, PixelType::ConvertTxH(m_Params.nHighCode), m_Params.nHighCode); + printf(" %s=%s [%d]\n", DevicesParamsConst::TYPE, pixel::pixel_get_type(static_cast(m_Params.nType)), static_cast(m_Params.nType)); + printf(" %s=%d [%s]\n", DevicesParamsConst::MAP, static_cast(m_Params.nMap), pixel::pixel_get_map(static_cast(m_Params.nMap))); + printf(" %s=%.2f [0x%X]\n", DevicesParamsConst::LED_T0H, pixel::pixel_convert_TxH(m_Params.nLowCode), m_Params.nLowCode); + printf(" %s=%.2f [0x%X]\n", DevicesParamsConst::LED_T1H, pixel::pixel_convert_TxH(m_Params.nHighCode), m_Params.nHighCode); printf(" %s=%d\n", DevicesParamsConst::COUNT, m_Params.nCount); for (uint32_t i = 0; i < std::min(static_cast(pixelpatterns::MAX_PORTS), sizeof(LightSetParamsConst::START_UNI_PORT) / sizeof(LightSetParamsConst::START_UNI_PORT[0])); i++) { diff --git a/lib-ws28xxdmx/src/params/pixeldmxparamsrdm.cpp b/lib-ws28xxdmx/src/params/pixeldmxparamsrdm.cpp index cbbce10d4..13fadf644 100644 --- a/lib-ws28xxdmx/src/params/pixeldmxparamsrdm.cpp +++ b/lib-ws28xxdmx/src/params/pixeldmxparamsrdm.cpp @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + #include #include diff --git a/lib-ws28xxdmx/src/rdm/rdm_manufacturer_pid.cpp b/lib-ws28xxdmx/src/rdm/rdm_manufacturer_pid.cpp index 14c6aac5e..9d0f4d3ff 100755 --- a/lib-ws28xxdmx/src/rdm/rdm_manufacturer_pid.cpp +++ b/lib-ws28xxdmx/src/rdm/rdm_manufacturer_pid.cpp @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_PIXELDMX) +# undef NDEBUG +#endif + #include #include #include @@ -150,29 +154,32 @@ namespace rdm { bool handle_manufactureer_pid_get(const uint16_t nPid, [[maybe_unused]] const ManufacturerParamData *pIn, ManufacturerParamData *pOut, uint16_t& nReason) { DEBUG_PRINTF("nPid=%x", __builtin_bswap16(nPid)); + auto &pixelConfiguration = PixelConfiguration::Get(); + auto &pixelDmxConfiguration = PixelDmxConfiguration::Get(); + switch (nPid) { case rdm::E120_MANUFACTURER_PIXEL_TYPE::code: { - const auto *pString = ::PixelType::GetType(WS28xxDmx::Get()->GetType()); + const auto *pString = ::pixel::pixel_get_type(pixelConfiguration.GetType()); pOut->nPdl = static_cast(strlen(pString)); memcpy(pOut->pParamData, pString, pOut->nPdl); return true; } case rdm::E120_MANUFACTURER_PIXEL_COUNT::code: { - const auto nCount = WS28xxDmx::Get()->GetCount(); + const auto nCount = pixelConfiguration.GetCount(); pOut->nPdl = 2; pOut->pParamData[0] = static_cast(nCount >> 8); pOut->pParamData[1] = static_cast(nCount); return true; } case rdm::E120_MANUFACTURER_PIXEL_GROUPING_COUNT::code: { - const auto nGroupingCount = WS28xxDmx::Get()->GetGroupingCount(); + const auto nGroupingCount = pixelDmxConfiguration.GetGroupingCount(); pOut->nPdl = 2; pOut->pParamData[0] = static_cast(nGroupingCount >> 8); pOut->pParamData[1] = static_cast(nGroupingCount); return true; } case rdm::E120_MANUFACTURER_PIXEL_MAP::code: { - const auto *pString = ::PixelType::GetMap(WS28xxDmx::Get()->GetMap()); + const auto *pString = ::pixel::pixel_get_map(pixelConfiguration.GetMap()); pOut->nPdl = static_cast(strlen(pString)); memcpy(pOut->pParamData, pString, pOut->nPdl); return true; @@ -228,7 +235,7 @@ bool handle_manufactureer_pid_set(const bool isBroadcast, const uint16_t nPid, c } case rdm::E120_MANUFACTURER_PIXEL_MAP::code: { if (pIn->nPdl == 3) { - const auto map = ::PixelType::GetMap(reinterpret_cast(pIn->pParamData)); + const auto map = ::pixel::pixel_get_map(reinterpret_cast(pIn->pParamData)); if (map == pixel::Map::UNDEFINED) { nReason = E120_NR_DATA_OUT_OF_RANGE; diff --git a/opi_emac_artnet_pixel/Makefile.H3 b/opi_emac_artnet_pixel/Makefile.H3 index ad4a0c872..2b69f6ed9 100644 --- a/opi_emac_artnet_pixel/Makefile.H3 +++ b/opi_emac_artnet_pixel/Makefile.H3 @@ -22,7 +22,10 @@ DEFINES+=ENABLE_HTTPD ENABLE_CONTENT DEFINES+=DISABLE_RTC -DEFINES+=NDEBUG +DEFINES+=DEBUG_PIXEL +DEFINES+=DEBUG_STACK +DEFINES+=DEBUG_HEAP +#DEFINES+=NDEBUG LIBS= diff --git a/opi_emac_artnet_pixel/firmware/main.cpp b/opi_emac_artnet_pixel/firmware/main.cpp index 82456287b..ec79c114e 100644 --- a/opi_emac_artnet_pixel/firmware/main.cpp +++ b/opi_emac_artnet_pixel/firmware/main.cpp @@ -29,7 +29,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -93,10 +93,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("Art-Net 4 Pixel controller {1x 4 Universes}"); - nw.Print(); - - display.TextStatus(ArtNetMsgConst::PARAMS, CONSOLE_YELLOW); - + ArtNetNode node; ArtNetParams artnetParams; @@ -107,11 +104,11 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmx pixelDmx(&pixelDmxConfiguration); + WS28xxDmx pixelDmx; - const auto nUniverses = pixelDmx.GetUniverses(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); uint32_t nPortProtocolIndex = 0; @@ -142,7 +139,7 @@ int main() { #if defined (NODE_RDMNET_LLRP_ONLY) display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "Art-Net Pixel 1-%s:%d", PixelType::GetType(WS28xx::Get()->GetType()), WS28xx::Get()->GetCount()); + snprintf(aDescription, sizeof(aDescription) - 1, "Art-Net Pixel 1-%s:%d", pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount()); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero Pixel"); @@ -194,10 +191,10 @@ int main() { display.Show(); display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); diff --git a/opi_emac_artnet_pixel_dmx/firmware/main.cpp b/opi_emac_artnet_pixel_dmx/firmware/main.cpp index f42764d09..6b0fc4327 100644 --- a/opi_emac_artnet_pixel_dmx/firmware/main.cpp +++ b/opi_emac_artnet_pixel_dmx/firmware/main.cpp @@ -24,13 +24,12 @@ */ #include -#include #include "hardware.h" #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -47,7 +46,6 @@ #include "pixeldmxparams.h" #include "ws28xxdmx.h" - #include "dmxparams.h" #include "dmxsend.h" #include "dmxconfigudp.h" @@ -101,10 +99,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("Art-Net 4 Pixel controller {1x 4 Universes} / DMX"); - nw.Print(); - - display.TextStatus(ArtNetMsgConst::PARAMS, CONSOLE_YELLOW); - + ArtNetNode node; ArtNetParams artnetParams; @@ -115,18 +110,17 @@ int main() { PixelDmxConfiguration pixelDmxConfiguration; - PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmx pixelDmx(&pixelDmxConfiguration); + WS28xxDmx pixelDmx; auto isPixelUniverseSet = false; const auto nStartPixelUniverse = pixelDmxParams.GetStartUniversePort(0, isPixelUniverseSet); if (isPixelUniverseSet) { - const auto nUniverses = pixelDmx.GetUniverses(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); for (uint32_t nPortIndex = 0; nPortIndex < nUniverses; nPortIndex++) { node.SetUniverse(nPortIndex, lightset::PortDir::OUTPUT, static_cast(nStartPixelUniverse + nPortIndex)); @@ -177,7 +171,7 @@ int main() { display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "Art-Net Pixel 1-%s:%d", PixelType::GetType(WS28xx::Get()->GetType()), WS28xx::Get()->GetCount()); + snprintf(aDescription, sizeof(aDescription) - 1, "Art-Net Pixel 1-%s:%d", pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount()); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero Pixel-DMX"); @@ -226,10 +220,10 @@ int main() { display.Show(); display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); diff --git a/opi_emac_artnet_pixel_dmx_multi/firmware/main.cpp b/opi_emac_artnet_pixel_dmx_multi/firmware/main.cpp index c08b6c213..17fb2dde1 100644 --- a/opi_emac_artnet_pixel_dmx_multi/firmware/main.cpp +++ b/opi_emac_artnet_pixel_dmx_multi/firmware/main.cpp @@ -25,13 +25,12 @@ #include #include -#include #include "hardware.h" #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -104,10 +103,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("Art-Net 4 Pixel controller {8x 4 Universes} / 2x DMX"); - nw.Print(); - - display.TextStatus(ArtNetMsgConst::PARAMS, CONSOLE_YELLOW); - + ArtNetNode node; ArtNetParams artnetParams; @@ -120,14 +116,14 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmxMulti pixelDmxMulti(pixelDmxConfiguration); + WS28xxDmxMulti pixelDmxMulti; WS28xxMulti::Get()->SetJamSTAPLDisplay(new HandlerOled); - const auto nPixelActivePorts = pixelDmxMulti.GetOutputPorts(); - const auto nUniverses = pixelDmxMulti.GetUniverses(); + const auto nPixelActivePorts = pixelDmxConfiguration.GetOutputPorts(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); uint32_t nPortProtocolIndex = 0; @@ -196,7 +192,7 @@ int main() { display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "Art-Net Pixel %d-%s:%d DMX %d", nPixelActivePorts, PixelType::GetType(WS28xxMulti::Get()->GetType()), WS28xxMulti::Get()->GetCount(), nDmxUniverses); + snprintf(aDescription, sizeof(aDescription) - 1, "Art-Net Pixel %d-%s:%d DMX %d", nPixelActivePorts, pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), nDmxUniverses); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero Pixel-DMX"); @@ -233,7 +229,7 @@ int main() { showFile.Print(); #endif - display.SetTitle("ArtNet 4 Pixel %dx%d", nPixelActivePorts, WS28xxMulti::Get()->GetCount()); + display.SetTitle("ArtNet 4 Pixel %dx%d", nPixelActivePorts, pixelDmxConfiguration.GetCount()); display.Set(2, displayudf::Labels::IP); display.Set(3, displayudf::Labels::VERSION); display.Set(4, displayudf::Labels::UNIVERSE_PORT_A); @@ -245,10 +241,10 @@ int main() { display.Show(); display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); diff --git a/opi_emac_artnet_pixel_multi/firmware/main.cpp b/opi_emac_artnet_pixel_multi/firmware/main.cpp index 8426f2c06..4ea7b3cbc 100644 --- a/opi_emac_artnet_pixel_multi/firmware/main.cpp +++ b/opi_emac_artnet_pixel_multi/firmware/main.cpp @@ -29,7 +29,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -95,12 +95,9 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("Art-Net 4 Pixel controller {8x 4 Universes}"); - nw.Print(); - - display.TextStatus(ArtNetMsgConst::PARAMS, CONSOLE_YELLOW); - - ArtNetNode node; + ArtNetNode node; + ArtNetParams artnetParams; artnetParams.Load(); artnetParams.Set(); @@ -109,14 +106,14 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmxMulti pixelDmxMulti(pixelDmxConfiguration); + WS28xxDmxMulti pixelDmxMulti; WS28xxMulti::Get()->SetJamSTAPLDisplay(new HandlerOled); - const auto nPixelActivePorts = pixelDmxMulti.GetOutputPorts(); - const auto nUniverses = pixelDmxMulti.GetUniverses(); + const auto nPixelActivePorts = pixelDmxConfiguration.GetOutputPorts(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); uint32_t nPortProtocolIndex = 0; @@ -148,7 +145,7 @@ int main() { #if defined (NODE_RDMNET_LLRP_ONLY) display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "Art-Net Pixel %u-%s:%u", static_cast(nPixelActivePorts), PixelType::GetType(WS28xxMulti::Get()->GetType()), static_cast(WS28xxMulti::Get()->GetCount())); + snprintf(aDescription, sizeof(aDescription) - 1, "Art-Net Pixel %u-%s:%u", static_cast(nPixelActivePorts), pixel::pixel_get_type(pixelDmxConfiguration.GetType()), static_cast(pixelDmxConfiguration.GetCount())); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero Pixel"); @@ -188,7 +185,7 @@ int main() { node.Print(); pixelDmxMulti.Print(); - display.SetTitle("ArtNet 4 Pixel %dx%d", nPixelActivePorts, WS28xxMulti::Get()->GetCount()); + display.SetTitle("ArtNet 4 Pixel %dx%d", nPixelActivePorts, pixelDmxConfiguration.GetCount()); display.Set(2, displayudf::Labels::IP); display.Set(3, displayudf::Labels::VERSION); display.Set(4, displayudf::Labels::UNIVERSE_PORT_A); @@ -199,12 +196,11 @@ int main() { displayUdfParams.Set(&display); display.Show(); - display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); diff --git a/opi_emac_ddp_pixel_dmx_multi/firmware/main.cpp b/opi_emac_ddp_pixel_dmx_multi/firmware/main.cpp index 71234e212..e68f87d4a 100644 --- a/opi_emac_ddp_pixel_dmx_multi/firmware/main.cpp +++ b/opi_emac_ddp_pixel_dmx_multi/firmware/main.cpp @@ -31,7 +31,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -69,8 +69,6 @@ #include "flashcodeinstall.h" #include "configstore.h" - - #include "firmwareversion.h" #include "software_version.h" @@ -91,8 +89,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("DDP Pixel controller 8x 4U with 2x DMX"); - nw.Print(); - + mDns.ServiceRecordAdd(nullptr, mdns::Services::DDP, "type=display"); // LightSet A - Pixel - 32 Universes @@ -101,17 +98,17 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmxMulti pixelDmxMulti(pixelDmxConfiguration); + WS28xxDmxMulti pixelDmxMulti; WS28xxMulti::Get()->SetJamSTAPLDisplay(new HandlerOled); DdpDisplay ddpDisplay; - const auto nActivePorts = pixelDmxMulti.GetOutputPorts(); + const auto nActivePorts = pixelDmxConfiguration.GetOutputPorts(); - ddpDisplay.SetCount(pixelDmxMulti.GetGroups(), pixelDmxMulti.GetChannelsPerPixel(), nActivePorts); + ddpDisplay.SetCount(pixelDmxConfiguration.GetGroups(), pixelDmxConfiguration.GetLedsPerPixel(), nActivePorts); const auto nTestPattern = static_cast(pixelDmxParams.GetTestPattern()); PixelTestPattern pixelTestPattern(nTestPattern, nActivePorts); @@ -139,7 +136,7 @@ int main() { display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "DDP Display %u-%s:%d DMX 2x", nActivePorts, PixelType::GetType(WS28xxMulti::Get()->GetType()), WS28xxMulti::Get()->GetCount()); + snprintf(aDescription, sizeof(aDescription) - 1, "DDP Display %u-%s:%d DMX 2x", nActivePorts, pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount()); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero Pixel-DMX"); @@ -173,10 +170,10 @@ int main() { display.Show(); display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); diff --git a/opi_emac_ddp_pixel_multi/firmware/main.cpp b/opi_emac_ddp_pixel_multi/firmware/main.cpp index b35f12a34..a00d0d438 100644 --- a/opi_emac_ddp_pixel_multi/firmware/main.cpp +++ b/opi_emac_ddp_pixel_multi/firmware/main.cpp @@ -25,13 +25,12 @@ #include #include -#include #include "hardware.h" #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -85,26 +84,24 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("DDP Pixel controller 8x 4U"); - nw.Print(); - - + mDns.ServiceRecordAdd(nullptr, mdns::Services::DDP, "type=display"); PixelDmxConfiguration pixelDmxConfiguration; PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmxMulti pixelDmxMulti(pixelDmxConfiguration); + WS28xxDmxMulti pixelDmxMulti; WS28xxMulti::Get()->SetJamSTAPLDisplay(new HandlerOled); DdpDisplay ddpDisplay; - const auto nActivePorts = pixelDmxMulti.GetOutputPorts(); + const auto nActivePorts = pixelDmxConfiguration.GetOutputPorts(); - ddpDisplay.SetCount(pixelDmxMulti.GetGroups(), pixelDmxMulti.GetChannelsPerPixel(), nActivePorts); + ddpDisplay.SetCount(pixelDmxConfiguration.GetGroups(), pixelDmxConfiguration.GetLedsPerPixel(), nActivePorts); const auto nTestPattern = static_cast(pixelDmxParams.GetTestPattern()); PixelTestPattern pixelTestPattern(nTestPattern, nActivePorts); @@ -116,7 +113,7 @@ int main() { display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "DDP Display %u-%s:%d", nActivePorts, PixelType::GetType(WS28xxMulti::Get()->GetType()), WS28xxMulti::Get()->GetCount()); + snprintf(aDescription, sizeof(aDescription) - 1, "DDP Display %u-%s:%d", nActivePorts, pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount()); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero Pixel"); @@ -150,10 +147,10 @@ int main() { display.Show(); display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); diff --git a/opi_emac_e131_pixel/firmware/main.cpp b/opi_emac_e131_pixel/firmware/main.cpp index c691d65a4..5c7106b24 100644 --- a/opi_emac_e131_pixel/firmware/main.cpp +++ b/opi_emac_e131_pixel/firmware/main.cpp @@ -29,7 +29,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -92,9 +92,6 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("sACN E1.31 Pixel controller {1x 4 Universes}"); - nw.Print(); - - display.TextStatus(E131MsgConst::PARAMS, CONSOLE_YELLOW); E131Bridge bridge; @@ -106,11 +103,11 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmx pixelDmx(&pixelDmxConfiguration); + WS28xxDmx pixelDmx; - const auto nUniverses = pixelDmx.GetUniverses(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); uint32_t nPortProtocolIndex = 0; @@ -136,7 +133,7 @@ int main() { #if defined (NODE_RDMNET_LLRP_ONLY) display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "sACN Pixel 1-%s:%d", PixelType::GetType(WS28xx::Get()->GetType()), WS28xx::Get()->GetCount()); + snprintf(aDescription, sizeof(aDescription) - 1, "sACN Pixel 1-%s:%d", pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount()); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero Pixel"); @@ -185,12 +182,11 @@ int main() { displayUdfParams.Set(&display); display.Show(); - display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); diff --git a/opi_emac_e131_pixel_dmx/firmware/main.cpp b/opi_emac_e131_pixel_dmx/firmware/main.cpp index 9e274e506..495284239 100644 --- a/opi_emac_e131_pixel_dmx/firmware/main.cpp +++ b/opi_emac_e131_pixel_dmx/firmware/main.cpp @@ -24,13 +24,12 @@ */ #include -#include #include "hardware.h" #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -99,10 +98,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("sACN E1.31 Pixel controller {1x 4 Universes} / DMX"); - nw.Print(); - - display.TextStatus(E131MsgConst::PARAMS, CONSOLE_YELLOW); - + E131Bridge bridge; E131Params e131params; @@ -115,15 +111,15 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmx pixelDmx(&pixelDmxConfiguration); + WS28xxDmx pixelDmx; auto isPixelUniverseSet = false; const auto nStartPixelUniverse = pixelDmxParams.GetStartUniversePort(0, isPixelUniverseSet); if (isPixelUniverseSet) { - const auto nUniverses = pixelDmx.GetUniverses(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); for (uint32_t nPortIndex = 0; nPortIndex < nUniverses; nPortIndex++) { bridge.SetUniverse(nPortIndex, lightset::PortDir::OUTPUT, static_cast(nStartPixelUniverse + nPortIndex)); @@ -173,7 +169,7 @@ int main() { display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "sACN Pixel %d-%s:%d DMX %d", isPixelUniverseSet, PixelType::GetType(WS28xx::Get()->GetType()), WS28xx::Get()->GetCount(), isDmxUniverseSet); + snprintf(aDescription, sizeof(aDescription) - 1, "sACN Pixel %d-%s:%d DMX %d", isPixelUniverseSet, pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), isDmxUniverseSet); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero Pixel-DMX"); @@ -222,10 +218,10 @@ int main() { display.Show(); display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); diff --git a/opi_emac_e131_pixel_dmx_multi/firmware/main.cpp b/opi_emac_e131_pixel_dmx_multi/firmware/main.cpp index 50a6f293b..b28a42f0b 100644 --- a/opi_emac_e131_pixel_dmx_multi/firmware/main.cpp +++ b/opi_emac_e131_pixel_dmx_multi/firmware/main.cpp @@ -25,13 +25,12 @@ #include #include -#include #include "hardware.h" #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -103,10 +102,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("sACN E1.31 Pixel controller {8x 4 Universes} / 2x DMX"); - nw.Print(); - - display.TextStatus(E131MsgConst::PARAMS, CONSOLE_YELLOW); - + E131Bridge bridge; E131Params e131params; @@ -119,14 +115,14 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmxMulti pixelDmxMulti(pixelDmxConfiguration); + WS28xxDmxMulti pixelDmxMulti; WS28xxMulti::Get()->SetJamSTAPLDisplay(new HandlerOled); - const auto nActivePorts = pixelDmxMulti.GetOutputPorts(); - const auto nUniverses = pixelDmxMulti.GetUniverses(); + const auto nActivePorts = pixelDmxConfiguration.GetOutputPorts(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); uint32_t nPortProtocolIndex = 0; @@ -199,7 +195,7 @@ int main() { display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "sACN Pixel %u-%s:%d DMX %u", nActivePorts, PixelType::GetType(WS28xxMulti::Get()->GetType()), WS28xxMulti::Get()->GetCount(), nDmxUniverses); + snprintf(aDescription, sizeof(aDescription) - 1, "sACN Pixel %u-%s:%d DMX %u", nActivePorts, pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), nDmxUniverses); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero Pixel-DMX"); @@ -233,7 +229,7 @@ int main() { showFile.Print(); #endif - display.SetTitle("sACN Pixel 8:%dx%d", nActivePorts, WS28xxMulti::Get()->GetCount()); + display.SetTitle("sACN Pixel 8:%dx%d", nActivePorts, pixelDmxConfiguration.GetCount()); display.Set(2, displayudf::Labels::IP); display.Set(3, displayudf::Labels::HOSTNAME); display.Set(4, displayudf::Labels::VERSION); @@ -245,12 +241,11 @@ int main() { displayUdfParams.Set(&display); display.Show(); - display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); diff --git a/opi_emac_e131_pixel_multi/firmware/main.cpp b/opi_emac_e131_pixel_multi/firmware/main.cpp index 18568e01c..497b13f17 100644 --- a/opi_emac_e131_pixel_multi/firmware/main.cpp +++ b/opi_emac_e131_pixel_multi/firmware/main.cpp @@ -29,7 +29,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -95,10 +95,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("sACN E1.31 Pixel controller {8x 4 Universes}"); - nw.Print(); - - display.TextStatus(E131MsgConst::PARAMS, CONSOLE_YELLOW); - + E131Bridge bridge; E131Params e131params; @@ -109,13 +106,14 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); + + WS28xxDmxMulti pixelDmxMulti; - WS28xxDmxMulti pixelDmxMulti(pixelDmxConfiguration); WS28xxMulti::Get()->SetJamSTAPLDisplay(new HandlerOled); - const auto nUniverses = pixelDmxMulti.GetUniverses(); - const auto nActivePorts = pixelDmxMulti.GetOutputPorts(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); + const auto nActivePorts = pixelDmxConfiguration.GetOutputPorts(); uint32_t nPortProtocolIndex = 0; @@ -143,7 +141,7 @@ int main() { #if defined (NODE_RDMNET_LLRP_ONLY) display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "sACN Pixel %d-%s:%d", nActivePorts, PixelType::GetType(WS28xxMulti::Get()->GetType()), WS28xxMulti::Get()->GetCount()); + snprintf(aDescription, sizeof(aDescription) - 1, "sACN Pixel %d-%s:%d", nActivePorts, pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount()); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero Pixel"); @@ -181,7 +179,7 @@ int main() { bridge.Print(); pixelDmxMulti.Print(); - display.SetTitle("sACN Pixel 8:%dx%d", nActivePorts, WS28xxMulti::Get()->GetCount()); + display.SetTitle("sACN Pixel 8:%dx%d", nActivePorts, pixelDmxConfiguration.GetCount()); display.Set(2, displayudf::Labels::IP); display.Set(3, displayudf::Labels::HOSTNAME); display.Set(4, displayudf::Labels::VERSION); @@ -195,10 +193,10 @@ int main() { display.Show(); display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); diff --git a/opi_emac_osc_pixel/firmware/main.cpp b/opi_emac_osc_pixel/firmware/main.cpp index 474798f7d..432eeaaa7 100644 --- a/opi_emac_osc_pixel/firmware/main.cpp +++ b/opi_emac_osc_pixel/firmware/main.cpp @@ -29,7 +29,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "display.h" #include "displayhandler.h" @@ -52,8 +52,6 @@ #include "flashcodeinstall.h" #include "configstore.h" - - #include "firmwareversion.h" #include "software_version.h" @@ -73,7 +71,6 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("OSC Server Pixel controller {1x Universe}"); - nw.Print(); OSCServerParams params; OscServer server; @@ -89,14 +86,14 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmx pixelDmx(&pixelDmxConfiguration); + WS28xxDmx pixelDmx; const auto nTestPattern = static_cast(pixelDmxParams.GetTestPattern()); PixelTestPattern pixelTestPattern(nTestPattern, 1); - display.Printf(7, "%s:%d G%d", PixelType::GetType(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); + display.Printf(7, "%s:%d G%d", pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); server.SetOutput(&pixelDmx); server.SetOscServerHandler(new Handler(&pixelDmx)); diff --git a/opi_emac_osc_pixel/lib/handler.cpp b/opi_emac_osc_pixel/lib/handler.cpp index 15505dc30..d1442d0d2 100644 --- a/opi_emac_osc_pixel/lib/handler.cpp +++ b/opi_emac_osc_pixel/lib/handler.cpp @@ -2,7 +2,7 @@ * @file handler.cpp * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,8 +38,8 @@ Handler::Handler(WS28xxDmx *pWS28xxDmx): m_pWS28xxDmx(pWS28xxDmx), - m_nCount(WS28xx::Get()->GetCount()), - m_TypeString(const_cast(PixelType::GetType(WS28xx::Get()->GetType()))) + m_nCount(PixelConfiguration::Get().GetCount()), + m_TypeString(const_cast(pixel::pixel_get_type(PixelConfiguration::Get().GetType()))) { DEBUG_ENTRY diff --git a/opi_emac_osc_pixel/lib/networkdisplay.cpp b/opi_emac_osc_pixel/lib/networkdisplay.cpp index af3db144f..c5021dea9 100644 --- a/opi_emac_osc_pixel/lib/networkdisplay.cpp +++ b/opi_emac_osc_pixel/lib/networkdisplay.cpp @@ -2,7 +2,7 @@ * @file networkdisplay.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,24 +23,76 @@ * THE SOFTWARE. */ +#include + +#include "display.h" + #include "network.h" +#include "net/protocol/dhcp.h" -namespace network { -void display_emac_config() {} -void display_emac_start() {} -void display_emac_status([[maybe_unused]] const bool isLinkUp) {} +namespace net { +static constexpr auto LINE_IP = 2U; -void display_ip() {} +void display_emac_config() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet config"); +} -void display_netmask() {} +void display_emac_start() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet start"); +} -void display_gateway() {} +void display_emac_status(const bool isLinkUp) { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet Link "); + if (isLinkUp) { + Display::Get()->PutString("UP"); + } else { + Display::Get()->PutString("DOWN"); + } +} -void display_hostname() {} +void display_ip() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->Printf(LINE_IP, "" IPSTR "/%d %c", IP2STR(Network::Get()->GetIp()), Network::Get()->GetNetmaskCIDR(), Network::Get()->GetAddressingMode()); +} -void display_emac_shutdown() {} +void display_netmask() { + display_ip(); +} -// DHCP Client -void display_dhcp_status([[maybe_unused]] network::dhcp::ClientStatus nStatus) {} -} // namespace network +void display_gateway() { +} + +void display_hostname() { +} +void display_emac_shutdown() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet shutdown"); +} + +void display_dhcp_status(net::dhcp::State state) { + Display::Get()->ClearLine(LINE_IP); + + switch (state) { + case net::dhcp::State::STATE_OFF: + break; + case net::dhcp::State::STATE_RENEWING: + Display::Get()->PutString("DHCP renewing"); + break; + case net::dhcp::State::STATE_BOUND: + Display::Get()->PutString("Got IP"); + break; + case net::dhcp::State::STATE_REQUESTING: + Display::Get()->PutString("DHCP requesting"); + break; + case net::dhcp::State::STATE_BACKING_OFF: + Display::Get()->PutString("DHCP Error"); + break; + default: + break; + } +} +} // namespace network diff --git a/opi_emac_pp_pixel_multi/Makefile.H3 b/opi_emac_pp_pixel_multi/Makefile.H3 index bed6ff776..cd0d0303e 100644 --- a/opi_emac_pp_pixel_multi/Makefile.H3 +++ b/opi_emac_pp_pixel_multi/Makefile.H3 @@ -5,7 +5,7 @@ DEFINES+=NODE_RDMNET_LLRP_ONLY DEFINES+=OUTPUT_DMX_PIXEL_MULTI PIXELPATTERNS_MULTI DEFINES+=CONFIG_PIXELDMX_MAX_PORTS=8 -DEFINES+=CONFIG_PIXELDMX_ENABLE_GAMMATABLE +#DEFINES+=CONFIG_PIXELDMX_ENABLE_GAMMATABLE DEFINES+=ENABLE_HTTPD ENABLE_CONTENT diff --git a/opi_emac_pp_pixel_multi/firmware/main.cpp b/opi_emac_pp_pixel_multi/firmware/main.cpp index db9aac689..b56ce84e4 100644 --- a/opi_emac_pp_pixel_multi/firmware/main.cpp +++ b/opi_emac_pp_pixel_multi/firmware/main.cpp @@ -25,13 +25,12 @@ #include #include -#include #include "hardware.h" #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -84,7 +83,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("PixelPusher controller 8x 4U"); - nw.Print(); + mDns.ServiceRecordAdd(nullptr, mdns::Services::PP, "type=PixelPusher"); @@ -92,16 +91,16 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmxMulti pixelDmxMulti(pixelDmxConfiguration); + WS28xxDmxMulti pixelDmxMulti; WS28xxMulti::Get()->SetJamSTAPLDisplay(new HandlerOled); PixelPusher pp; - const auto nActivePorts = pixelDmxMulti.GetOutputPorts(); + const auto nActivePorts = pixelDmxConfiguration.GetOutputPorts(); - pp.SetCount(pixelDmxMulti.GetGroups(), nActivePorts, false); + pp.SetCount(pixelDmxConfiguration.GetGroups(), nActivePorts, false); const auto nTestPattern = static_cast(pixelDmxParams.GetTestPattern()); PixelTestPattern pixelTestPattern(nTestPattern, nActivePorts); @@ -115,7 +114,7 @@ int main() { display.TextStatus(RDMNetConst::MSG_CONFIG, CONSOLE_YELLOW); char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH + 1]; - snprintf(aDescription, sizeof(aDescription) - 1, "PixelPusher %u-%s:%d", nActivePorts, PixelType::GetType(WS28xxMulti::Get()->GetType()), WS28xxMulti::Get()->GetCount()); + snprintf(aDescription, sizeof(aDescription) - 1, "PixelPusher %u-%s:%d", nActivePorts, pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount()); char aLabel[RDM_DEVICE_LABEL_MAX_LENGTH + 1]; const auto nLength = snprintf(aLabel, sizeof(aLabel) - 1, "Orange Pi Zero PixelPusher"); @@ -149,10 +148,10 @@ int main() { display.Show(); display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (nTestPattern != pixelpatterns::Pattern::NONE) { display.ClearLine(6); diff --git a/rpi_wifi_artnet_pixel/firmware/main.cpp b/rpi_wifi_artnet_pixel/firmware/main.cpp index 0ae499221..5ef519e22 100755 --- a/rpi_wifi_artnet_pixel/firmware/main.cpp +++ b/rpi_wifi_artnet_pixel/firmware/main.cpp @@ -111,15 +111,15 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - auto *pWS28xxDmx = new WS28xxDmx(&pixelDmxConfiguration); + auto *pWS28xxDmx = new WS28xxDmx(); assert(pWS28xxDmx != nullptr); pSpi = pWS28xxDmx; - display.Printf(7, "%s:%d G%d", PixelType::GetType(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); + display.Printf(7, "%s:%d G%d", pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); - const auto nUniverses = pWS28xxDmx->GetUniverses(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); for (uint32_t nPortIndex = 1; nPortIndex < nUniverses; nPortIndex++) { node.SetUniverse(nPortIndex, lightset::PortDir::OUTPUT, static_cast(nStartUniverse + nPortIndex)); diff --git a/rpi_wifi_e131_pixel/Makefile.BCM b/rpi_wifi_e131_pixel/Makefile.BCM index a19689d0f..5a796b5f8 100755 --- a/rpi_wifi_e131_pixel/Makefile.BCM +++ b/rpi_wifi_e131_pixel/Makefile.BCM @@ -6,7 +6,7 @@ DEFINES+=ENABLE_MMU DEFINES+=DISABLE_RTC DEFINES+=NDEBUG -LIBS=e131 uuid dmxsend dmx ws28xxdmx ws28xx dmxmonitor lightset display +LIBS=e131 dmxsend dmx ws28xxdmx ws28xx dmxmonitor lightset display SRCDIR=firmware diff --git a/rpi_wifi_e131_pixel/firmware/main.cpp b/rpi_wifi_e131_pixel/firmware/main.cpp index a9712bd7c..4d0af6169 100755 --- a/rpi_wifi_e131_pixel/firmware/main.cpp +++ b/rpi_wifi_e131_pixel/firmware/main.cpp @@ -107,15 +107,15 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - auto *pWS28xxDmx = new WS28xxDmx(&pixelDmxConfiguration); + auto *pWS28xxDmx = new WS28xxDmx(); assert(pWS28xxDmx != nullptr); pSpi = pWS28xxDmx; - display.Printf(7, "%s:%d G%d", PixelType::GetType(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); + display.Printf(7, "%s:%d G%d", pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); - const auto nUniverses = pWS28xxDmx->GetUniverses(); + const auto nUniverses = pixelDmxConfiguration.GetUniverses(); for (uint32_t nPortIndex = 1; nPortIndex < nUniverses; nPortIndex++) { bridge.SetUniverse(nPortIndex, lightset::PortDir::OUTPUT, static_cast(nStartUniverse + nPortIndex)); diff --git a/rpi_wifi_osc_pixel/firmware/main.cpp b/rpi_wifi_osc_pixel/firmware/main.cpp index bcb977ebe..7f7cd7acd 100755 --- a/rpi_wifi_osc_pixel/firmware/main.cpp +++ b/rpi_wifi_osc_pixel/firmware/main.cpp @@ -2,7 +2,7 @@ * @file main.cpp * */ -/* Copyright (C) 2018-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -104,7 +104,7 @@ int main() { PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); // For the time being, just 1 Universe if (pixelDmxConfiguration.GetType() == pixel::Type::SK6812W) { @@ -117,11 +117,11 @@ int main() { } } - auto *pPixelDmx = new WS28xxDmx(&pixelDmxConfiguration); + auto *pPixelDmx = new WS28xxDmx(); assert(pPixelDmx != nullptr); pSpi = pPixelDmx; - display.Printf(7, "%s:%d G%d", PixelType::GetType(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); + display.Printf(7, "%s:%d G%d", pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); server.SetOutput(pSpi); server.SetOscServerHandler(new Handler(pPixelDmx)); diff --git a/rpi_wifi_osc_pixel/lib/handler.cpp b/rpi_wifi_osc_pixel/lib/handler.cpp index 15505dc30..d1442d0d2 100755 --- a/rpi_wifi_osc_pixel/lib/handler.cpp +++ b/rpi_wifi_osc_pixel/lib/handler.cpp @@ -2,7 +2,7 @@ * @file handler.cpp * */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,8 +38,8 @@ Handler::Handler(WS28xxDmx *pWS28xxDmx): m_pWS28xxDmx(pWS28xxDmx), - m_nCount(WS28xx::Get()->GetCount()), - m_TypeString(const_cast(PixelType::GetType(WS28xx::Get()->GetType()))) + m_nCount(PixelConfiguration::Get().GetCount()), + m_TypeString(const_cast(pixel::pixel_get_type(PixelConfiguration::Get().GetType()))) { DEBUG_ENTRY From 68bdd5a66627389542c4c35a1ad1d1c6364cffec Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 16 Aug 2024 14:36:03 +0200 Subject: [PATCH 08/17] Removed lightsetdmx.cpp and lightsetgetslotinfo.cpp --- lib-lightset/include/lightset.h | 26 ++-- lib-lightset/include/lightset32with4.h | 6 +- lib-lightset/include/lightset4with4.h | 6 +- lib-lightset/include/lightset64with4.h | 6 +- lib-lightset/include/lightsetchain.h | 2 +- lib-lightset/include/lightsetdata.h | 4 +- lib-lightset/include/lightsetwith4.h | 164 +++++++++++++++++++++++ lib-lightset/src/lightsetchain.cpp | 4 +- lib-lightset/src/lightsetdmx.cpp | 42 ------ lib-lightset/src/lightsetgetslotinfo.cpp | 34 ----- 10 files changed, 194 insertions(+), 100 deletions(-) mode change 100644 => 100755 lib-lightset/include/lightsetdata.h create mode 100755 lib-lightset/include/lightsetwith4.h delete mode 100644 lib-lightset/src/lightsetdmx.cpp delete mode 100644 lib-lightset/src/lightsetgetslotinfo.cpp diff --git a/lib-lightset/include/lightset.h b/lib-lightset/include/lightset.h index e2bbf3bfa..169075118 100755 --- a/lib-lightset/include/lightset.h +++ b/lib-lightset/include/lightset.h @@ -2,7 +2,7 @@ * @file lightset.h * */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2016-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -192,11 +192,7 @@ class LightSet { * @param [IN] PortIndex */ virtual void Sync(const uint32_t PortIndex)= 0; - /** - * - * @param [IN] doForce This parameter is used with Art-Net ArtSync only. - */ - virtual void Sync(const bool doForce = false)= 0; + virtual void Sync()= 0; #if defined (OUTPUT_HAVE_STYLESWITCH) virtual void SetOutputStyle(const uint32_t nPortIndex, const lightset::OutputStyle outputStyle)=0; virtual lightset::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const=0; @@ -206,10 +202,20 @@ class LightSet { virtual void FullOn() {} virtual void Print() {} // RDM Optional - virtual bool SetDmxStartAddress(uint16_t nDmxStartAddress); - virtual uint16_t GetDmxStartAddress(); - virtual uint16_t GetDmxFootprint(); - virtual bool GetSlotInfo(uint16_t nSlotOffset, lightset::SlotInfo &tSlotInfo); + virtual bool SetDmxStartAddress([[maybe_unused]] const uint16_t nDmxStartAddress) { + return false; + } + virtual uint16_t GetDmxStartAddress() { + return lightset::dmx::START_ADDRESS_DEFAULT; + } + virtual uint16_t GetDmxFootprint() { + return lightset::dmx::UNIVERSE_SIZE; + } + virtual bool GetSlotInfo([[maybe_unused]] const uint16_t nSlotOffset, lightset::SlotInfo &slotInfo) { + slotInfo.nType = 0x00; // ST_PRIMARY + slotInfo.nCategory = 0x0001; // SD_INTENSITY + return true; + } }; #endif /* LIGHTSET_H_ */ diff --git a/lib-lightset/include/lightset32with4.h b/lib-lightset/include/lightset32with4.h index 89e2252bd..8524ac495 100644 --- a/lib-lightset/include/lightset32with4.h +++ b/lib-lightset/include/lightset32with4.h @@ -89,12 +89,12 @@ class LightSet32with4 final: public LightSet { } } - void Sync(const bool doForce) override { + void Sync() override { if (m_pA != nullptr) { - m_pA->Sync(doForce); + m_pA->Sync(); } if (m_pB != nullptr) { - m_pB->Sync(doForce); + m_pB->Sync(); } } diff --git a/lib-lightset/include/lightset4with4.h b/lib-lightset/include/lightset4with4.h index 536e943fa..714256c67 100644 --- a/lib-lightset/include/lightset4with4.h +++ b/lib-lightset/include/lightset4with4.h @@ -89,12 +89,12 @@ class LightSet4with4 final: public LightSet { } } - void Sync(const bool doForce) override { + void Sync() override { if (m_pA != nullptr) { - m_pA->Sync(doForce); + m_pA->Sync(); } if (m_pB != nullptr) { - m_pB->Sync(doForce); + m_pB->Sync(); } } diff --git a/lib-lightset/include/lightset64with4.h b/lib-lightset/include/lightset64with4.h index 7facc3f25..c1371ba30 100644 --- a/lib-lightset/include/lightset64with4.h +++ b/lib-lightset/include/lightset64with4.h @@ -89,12 +89,12 @@ class LightSet64with4 final: public LightSet { } } - void Sync(const bool doForce) override { + void Sync() override { if (m_pA != nullptr) { - m_pA->Sync(doForce); + m_pA->Sync(); } if (m_pB != nullptr) { - m_pB->Sync(doForce); + m_pB->Sync(); } } diff --git a/lib-lightset/include/lightsetchain.h b/lib-lightset/include/lightsetchain.h index cde7b672a..e4d5e301e 100755 --- a/lib-lightset/include/lightsetchain.h +++ b/lib-lightset/include/lightsetchain.h @@ -47,7 +47,7 @@ class LightSetChain final: public LightSet { void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; void Sync(const uint32_t nPortIndex) override; - void Sync(const bool doForce = false) override; + void Sync() override; #if defined (OUTPUT_HAVE_STYLESWITCH) void SetOutputStyle(const uint32_t nPortIndex, const lightset::OutputStyle outputStyle) override; lightset::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const override; diff --git a/lib-lightset/include/lightsetdata.h b/lib-lightset/include/lightsetdata.h old mode 100644 new mode 100755 index 182587e82..b55a29da6 --- a/lib-lightset/include/lightsetdata.h +++ b/lib-lightset/include/lightsetdata.h @@ -201,13 +201,13 @@ class Data { #endif struct Source { - uint8_t data[dmx::UNIVERSE_SIZE]; + uint8_t data[dmx::UNIVERSE_SIZE] __attribute__ ((aligned (4))); }; struct OutputPort { Source sourceA; Source sourceB; - uint8_t data[dmx::UNIVERSE_SIZE]; + uint8_t data[dmx::UNIVERSE_SIZE] __attribute__ ((aligned (4))); uint32_t nLength; }; diff --git a/lib-lightset/include/lightsetwith4.h b/lib-lightset/include/lightsetwith4.h new file mode 100755 index 000000000..c301a2fe2 --- /dev/null +++ b/lib-lightset/include/lightsetwith4.h @@ -0,0 +1,164 @@ +/** + * @file lightsetwith4.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef LIGHTSETWITH4_H_ +#define LIGHTSETWITH4_H_ + +#include "lightset.h" + +#include "debug.h" + +template +class LightSetWith4 final: public LightSet { +public: + LightSetWith4(LightSet *pA, LightSet *pB) : m_pA(pA), m_pB(pB) { + DEBUG_PRINTF("%u %p %p", nMaxPorts, m_pA, m_pB); + } + + ~LightSetWith4() override {} + + void SetLightSetA(const LightSet *pA) { + m_pA = pA; + } + + LightSet *GetLightSetA() const { + return m_pA; + } + + void SetLightSetB(const LightSet *pB) { + m_pB = pB; + } + + LightSet *GetLightSetB() const { + return m_pB; + } + + void Start(const uint32_t nPortIndex) override { + if ((nPortIndex < nMaxPorts) && (m_pA != nullptr)) { + return m_pA->Start(nPortIndex); + } + if (m_pB != nullptr) { + m_pB->Start(nPortIndex & 0x3); + } + } + + void Stop(const uint32_t nPortIndex) override { + if ((nPortIndex < nMaxPorts) && (m_pA != nullptr)) { + return m_pA->Stop(nPortIndex); + } + if (m_pB != nullptr) { + m_pB->Stop(nPortIndex & 0x3); + } + } + + void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate) override { + if ((nPortIndex < nMaxPorts) && (m_pA != nullptr)) { + return m_pA->SetData(nPortIndex, pData, nLength, doUpdate); + } + if (m_pB != nullptr) { + return m_pB->SetData(nPortIndex & 0x3, pData, nLength, doUpdate); + } + } + + void Sync(const uint32_t nPortIndex) override { + if (m_pA != nullptr) { + m_pA->Sync(nPortIndex); + } + if (m_pB != nullptr) { + m_pB->Sync(nPortIndex); + } + } + + void Sync() override { + if (m_pA != nullptr) { + m_pA->Sync(); + } + if (m_pB != nullptr) { + m_pB->Sync(); + } + } + +#if defined (OUTPUT_HAVE_STYLESWITCH) + void SetOutputStyle(const uint32_t nPortIndex, const lightset::OutputStyle outputStyle) override { + if ((nPortIndex < nMaxPorts) && (m_pA != nullptr)) { + return m_pA->SetOutputStyle(nPortIndex, outputStyle); + } + if (m_pB != nullptr) { + return m_pB->SetOutputStyle(nPortIndex, outputStyle); + } + } + + lightset::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const override{ + if ((nPortIndex < nMaxPorts) && (m_pA != nullptr)) { + return m_pA->GetOutputStyle(nPortIndex); + } + if (m_pB != nullptr) { + return m_pB->GetOutputStyle(nPortIndex); + } + + return lightset::OutputStyle::DELTA; + } +#endif + + void Blackout(bool bBlackout) override { + if (m_pA != nullptr) { + m_pA->Blackout(bBlackout); + } + if (m_pB != nullptr) { + m_pB->Blackout(bBlackout); + } + } + + void Print() override { + if (m_pA != nullptr) { + m_pA->Print(); + } + if (m_pB != nullptr) { + m_pB->Print(); + } + } + + bool SetDmxStartAddress([[maybe_unused]] uint16_t nDmxStartAddress) override { + return false; + } + + uint16_t GetDmxStartAddress() override { + return lightset::dmx::ADDRESS_INVALID; + } + + uint16_t GetDmxFootprint() override { + return 0; + } + + bool GetSlotInfo([[maybe_unused]] uint16_t nSlotOffset, [[maybe_unused]] lightset::SlotInfo &tSlotInfo) override { + return false; + } + +private: + LightSet *m_pA; + LightSet *m_pB; +}; + +#endif /* LIGHTSETWITH4_H_ */ diff --git a/lib-lightset/src/lightsetchain.cpp b/lib-lightset/src/lightsetchain.cpp index 1a29afe4a..fa165ee9d 100755 --- a/lib-lightset/src/lightsetchain.cpp +++ b/lib-lightset/src/lightsetchain.cpp @@ -78,9 +78,9 @@ void LightSetChain::Sync(const uint32_t nPortIndex) { } } -void LightSetChain::Sync(const bool doForce) { +void LightSetChain::Sync() { for (uint32_t i = 0; i < m_nSize; i++) { - m_pTable[i].pLightSet->Sync(doForce); + m_pTable[i].pLightSet->Sync(); } } diff --git a/lib-lightset/src/lightsetdmx.cpp b/lib-lightset/src/lightsetdmx.cpp deleted file mode 100644 index a44ef2a4c..000000000 --- a/lib-lightset/src/lightsetdmx.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @file lightset.cpp - * - */ -/* Copyright (C) 2016-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include - -#include "lightset.h" - -using namespace lightset; - -uint16_t LightSet::GetDmxStartAddress() { - return dmx::START_ADDRESS_DEFAULT; -} - -uint16_t LightSet::GetDmxFootprint() { - return dmx::UNIVERSE_SIZE; -} - -bool LightSet::SetDmxStartAddress([[maybe_unused]] uint16_t nDmxStartAddress) { - return false; -} diff --git a/lib-lightset/src/lightsetgetslotinfo.cpp b/lib-lightset/src/lightsetgetslotinfo.cpp deleted file mode 100644 index 8dce961b2..000000000 --- a/lib-lightset/src/lightsetgetslotinfo.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @file lightset.cpp - * - */ -/* Copyright (C) 2016-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include "lightset.h" - -using namespace lightset; - -bool LightSet::GetSlotInfo([[maybe_unused]] uint16_t nSlot, SlotInfo &tSlotInfo) { - tSlotInfo.nType = 0x00; // ST_PRIMARY - tSlotInfo.nCategory = 0x0001; // SD_INTENSITY - return true; -} From bd7727daabce54da69d98e7d0b1941a8fcbcfd26 Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 16 Aug 2024 14:37:48 +0200 Subject: [PATCH 09/17] Added Software timers in H.A.L. framework. - This would make it easier migrating to FreeRTOS --- lib-hal/include/console.h | 2 +- lib-hal/include/gd32/hardware.h | 168 ++++++++++++++++++------- lib-hal/include/h3/hardware.h | 129 +++++++++++++------ lib-hal/include/hal_timers.h.template | 143 +++++++++++++++++++++ lib-hal/include/hardware.h | 10 ++ lib-hal/include/linux/hardware.h | 73 ++++++++++- lib-hal/include/rpi/hardware.h | 5 - lib-hal/posix/file.cpp | 4 +- lib-hal/src/h3/hardware.cpp | 17 ++- lib-hal/src/h3/sys_time.cpp | 2 +- lib-hal/src/hardware.cpp | 8 +- lib-hal/src/linux/minimum/exec_cmd.cpp | 2 +- lib-hal/src/rpi/hardware.cpp | 16 --- 13 files changed, 463 insertions(+), 116 deletions(-) create mode 100755 lib-hal/include/hal_timers.h.template mode change 100755 => 100644 lib-hal/src/linux/minimum/exec_cmd.cpp diff --git a/lib-hal/include/console.h b/lib-hal/include/console.h index ea4034afe..5c0107116 100644 --- a/lib-hal/include/console.h +++ b/lib-hal/include/console.h @@ -60,7 +60,7 @@ inline void console_putc([[maybe_unused]] int i) {} inline void console_puts([[maybe_unused]] const char *p) {} inline void console_write([[maybe_unused]] const char *p, [[maybe_unused]] unsigned int i) {} inline void console_status([[maybe_unused]] uint32_t i, [[maybe_unused]] const char *p) {} -inline void console_error([[maybe_unused]] const char *p) {} +extern "C" inline void console_error([[maybe_unused]] const char *p) {} #else #ifdef __cplusplus extern "C" { diff --git a/lib-hal/include/gd32/hardware.h b/lib-hal/include/gd32/hardware.h index 09b00211e..98254b615 100644 --- a/lib-hal/include/gd32/hardware.h +++ b/lib-hal/include/gd32/hardware.h @@ -58,9 +58,13 @@ extern "C" { void emac_debug_run(); #endif +#ifdef NDEBUG + extern "C" void console_error(const char *); +#endif + #include "panel_led.h" -extern volatile uint32_t s_nSysTickMillis; +#include "debug.h" class Hardware { public: @@ -76,8 +80,8 @@ class Hardware { uint32_t Millis() { #if defined (CONFIG_HAL_USE_SYSTICK) - extern volatile uint32_t s_nSysTickMillis; - return s_nSysTickMillis; + extern volatile uint32_t gv_nSysTickMillis; + return gv_nSysTickMillis; #else extern uint32_t timer6_get_elapsed_milliseconds(); return timer6_get_elapsed_milliseconds(); @@ -114,12 +118,6 @@ class Hardware { #endif } - void GetTime(struct tm *pTime) { - auto ltime = time(nullptr); - const auto *pLocalTime = localtime(<ime); - memcpy(pTime, pLocalTime, sizeof(struct tm)); - } - #if !defined(DISABLE_RTC) bool SetAlarm(const struct tm *pTime) { const auto b = m_HwClock.AlarmSet(pTime); @@ -200,6 +198,67 @@ class Hardware { return m_Mode; } + struct Timer { + uint32_t nExpireTime; + uint32_t nIntervalMillis; + int32_t nId; + hal::TimerCallback callback; + }; + + int32_t SoftwareTimerAdd(const uint32_t nIntervalMillis, const hal::TimerCallback callback) { + if (m_nTimersCount >= hal::SOFTWARE_TIMERS_MAX) { +#ifdef NDEBUG + console_error("SoftwareTimerAdd\n"); +#endif + return -1; + } + + const auto nCurrentTime = Hardware::Millis(); + + Timer newTimer = { + .nExpireTime = nCurrentTime + nIntervalMillis, + .nIntervalMillis = nIntervalMillis, + .nId = m_nNextId++, + .callback = callback, + }; + + m_Timers[m_nTimersCount++] = newTimer; + + return newTimer.nId; + } + + bool SoftwareTimerDelete(int32_t& nId) { + if (nId >= 0) { + for (uint32_t i = 0; i < m_nTimersCount; ++i) { + if (m_Timers[i].nId == nId) { + for (uint32_t j = i; j < m_nTimersCount - 1; ++j) { + m_Timers[j] = m_Timers[j + 1]; + } + --m_nTimersCount; + nId = -1; + return true; + } + } + } + + return false; + } + + bool SoftwareTimerChange(const int32_t nId, const uint32_t nIntervalMillis) { + if (nId >= 0) { + for (uint32_t i = 0; i < m_nTimersCount; ++i) { + if (m_Timers[i].nId == nId) { + m_Timers[i].nExpireTime = Hardware::Millis() + nIntervalMillis; + m_Timers[i].nIntervalMillis = nIntervalMillis; + + return true; + } + } + } + + return false; + } + void Run() { #if defined (ENABLE_USB_HOST) && defined (CONFIG_USB_HOST_MSC) # if defined (GD32H7XX) || defined (GD32F4XX) @@ -208,30 +267,14 @@ class Hardware { usbh_core_task(&usb_host); # endif #endif - if (__builtin_expect(m_nTicksPerSecond != 0, 1)) { - if (__builtin_expect(!(Hardware::Get()->Millis() - m_nMillisPrevious < m_nTicksPerSecond), 1)) { - m_nMillisPrevious = Hardware::Get()->Millis(); -#if defined(HAL_HAVE_PORT_BIT_TOGGLE) - GPIO_TG(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; -#else - m_nToggleLed = -m_nToggleLed; + const auto nCurrentTime = Hardware::Get()->Millis(); - if (m_nToggleLed > 0) { -# if defined (CONFIG_LEDBLINK_USE_PANELLED) - hal::panel_led_on(hal::panelled::ACTIVITY); -# else - GPIO_BOP(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; -# endif - } else { -# if defined (CONFIG_LEDBLINK_USE_PANELLED) - hal::panel_led_off(hal::panelled::ACTIVITY); -# else - GPIO_BC(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; -# endif - } -#endif - } - } + for (uint32_t i = 0; i < m_nTimersCount; i++) { + if (m_Timers[i].nExpireTime <= nCurrentTime) { + m_Timers[i].callback(); + m_Timers[i].nExpireTime = nCurrentTime + m_Timers[i].nIntervalMillis; + } + } hal::panel_led_run(); @@ -251,27 +294,63 @@ class Hardware { private: void RebootHandler(); + static void ledblink() { +#if defined(HAL_HAVE_PORT_BIT_TOGGLE) + GPIO_TG(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; +#else + m_nToggleLed = -m_nToggleLed; + + if (m_nToggleLed > 0) { +# if defined (CONFIG_LEDBLINK_USE_PANELLED) + hal::panel_led_on(hal::panelled::ACTIVITY); +# else + GPIO_BOP(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; +# endif + } else { +# if defined (CONFIG_LEDBLINK_USE_PANELLED) + hal::panel_led_off(hal::panelled::ACTIVITY); +# else + GPIO_BC(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; +# endif + } +#endif + } + void SetFrequency(const uint32_t nFreqHz) { + DEBUG_ENTRY + DEBUG_PRINTF("m_nTimerId=%d, nFreqHz=%u", m_nTimerId, nFreqHz); + + if (m_nTimerId < 0) { + m_nTimerId = SoftwareTimerAdd((1000U / nFreqHz), ledblink); + DEBUG_EXIT + return; + } + switch (nFreqHz) { case 0: - m_nTicksPerSecond = 0; + SoftwareTimerDelete(m_nTimerId); #if defined (CONFIG_LEDBLINK_USE_PANELLED) hal::panel_led_off(hal::panelled::ACTIVITY); #else GPIO_BC(LED_BLINK_GPIO_PORT) = LED_BLINK_PIN; #endif break; +# if !defined (CONFIG_HAL_USE_MINIMUM) case 1: - m_nTicksPerSecond = (1000 / 1); + SoftwareTimerChange(m_nTimerId, (1000U / 1)); break; case 3: - m_nTicksPerSecond = (1000 / 3); + SoftwareTimerChange(m_nTimerId, (1000U / 3)); break; case 5: - m_nTicksPerSecond = (1000 / 5); + SoftwareTimerChange(m_nTimerId, (1000U / 5)); break; + case 8: + SoftwareTimerChange(m_nTimerId, (1000U / 8)); + break; +# endif case 255: - m_nTicksPerSecond = 0; + SoftwareTimerDelete(m_nTimerId); #if defined (CONFIG_LEDBLINK_USE_PANELLED) hal::panel_led_on(hal::panelled::ACTIVITY); #else @@ -279,9 +358,11 @@ class Hardware { #endif break; default: - m_nTicksPerSecond = (1000U / nFreqHz); + SoftwareTimerChange(m_nTimerId, (1000U / nFreqHz)); break; } + + DEBUG_EXIT } private: @@ -292,12 +373,15 @@ class Hardware { bool m_bIsWatchdog { false }; hardware::ledblink::Mode m_Mode { hardware::ledblink::Mode::UNKNOWN }; bool m_doLock { false }; - uint32_t m_nTicksPerSecond { 1000 / 2 }; + int32_t m_nTimerId { -1 }; + + Timer m_Timers[hal::SOFTWARE_TIMERS_MAX]; + uint32_t m_nTimersCount { 0 }; + int32_t m_nNextId { 0 }; + #if !defined(HAL_HAVE_PORT_BIT_TOGGLE) - int32_t m_nToggleLed { 1 }; + static inline int32_t m_nToggleLed { 1 }; #endif - uint32_t m_nMillisPrevious { 0 }; - static Hardware *s_pThis; }; diff --git a/lib-hal/include/h3/hardware.h b/lib-hal/include/h3/hardware.h index 8136b6f09..81b858ef6 100644 --- a/lib-hal/include/h3/hardware.h +++ b/lib-hal/include/h3/hardware.h @@ -39,19 +39,22 @@ #include "h3_watchdog.h" #include "h3_thermal.h" +#include "debug.h" + #if defined (DEBUG_STACK) void stack_debug_run(); #endif uint32_t hardware_uptime_seconds(); void hardware_led_set(int); +extern "C" void console_error(const char *); class Hardware { public: Hardware(); uint32_t GetReleaseId() const { - return 0; // TODO U-Boot version + return 0; } void GetUuid(uuid_t out) { @@ -156,21 +159,71 @@ class Hardware { return m_Mode; } - void Run() { - if (__builtin_expect (m_nTicksPerSecond == 0, 0)) { - return; - } + struct Timer { + uint32_t nExpireTime; + uint32_t nIntervalMillis; + int32_t nId; + hal::TimerCallback callback; + }; + + int32_t SoftwareTimerAdd(const uint32_t nIntervalMillis, const hal::TimerCallback callback) { + if (m_nTimersCount >= hal::SOFTWARE_TIMERS_MAX) { +#ifdef NDEBUG + console_error("SoftwareTimerAdd\n"); +#endif + return -1; + } - const auto nMicros = H3_TIMER->AVS_CNT1; + const auto nCurrentTime = Hardware::Millis(); - if (__builtin_expect ((nMicros - m_nMicrosPrevious < m_nTicksPerSecond), 0)) { - return; - } + Timer newTimer = { + .nExpireTime = nCurrentTime + nIntervalMillis, + .nIntervalMillis = nIntervalMillis, + .nId = m_nNextId++, + .callback = callback, + }; - m_nMicrosPrevious = nMicros; + m_Timers[m_nTimersCount++] = newTimer; - m_nToggleLed ^= 0x1; - hardware_led_set(m_nToggleLed); + return newTimer.nId; + } + + bool SoftwareTimerDelete(int32_t& nId) { + for (uint32_t i = 0; i < m_nTimersCount; ++i) { + if (m_Timers[i].nId == nId) { + for (uint32_t j = i; j < m_nTimersCount - 1; ++j) { + m_Timers[j] = m_Timers[j + 1]; + } + --m_nTimersCount; + nId = -1; + return true; + } + } + + return false; + } + + bool SoftwareTimerChange(const int32_t nId, const uint32_t nIntervalMillis) { + for (uint32_t i = 0; i < m_nTimersCount; ++i) { + if (m_Timers[i].nId == nId) { + m_Timers[i].nExpireTime = Hardware::Millis() + nIntervalMillis; + m_Timers[i].nIntervalMillis = nIntervalMillis; + return true; + } + } + + return false; + } + + void Run() { + const auto nCurrentTime = Hardware::Get()->Millis(); + + for (uint32_t i = 0; i < m_nTimersCount; i++) { + if (m_Timers[i].nExpireTime <= nCurrentTime) { + m_Timers[i].callback(); + m_Timers[i].nExpireTime = nCurrentTime + m_Timers[i].nIntervalMillis; + } + } #if defined (DEBUG_STACK) stack_debug_run(); @@ -184,29 +237,32 @@ class Hardware { private: void RebootHandler(); - void SetFrequency(uint32_t nFreqHz) { - switch (nFreqHz) { - case 0: - m_nTicksPerSecond = 0; + static void ledblink() { + m_nToggleLed ^= 0x1; + hardware_led_set(m_nToggleLed); + } + + void SetFrequency(const uint32_t nFreqHz) { + if (nFreqHz == 0) { + SoftwareTimerDelete(m_nTimerId); hardware_led_set(0); - break; - case 1: - m_nTicksPerSecond = (1000000 / 1); - break; - case 3: - m_nTicksPerSecond = (1000000 / 3); - break; - case 5: - m_nTicksPerSecond = (1000000 / 5); - break; - case 255: - m_nTicksPerSecond = 0; + return; + } + + if (nFreqHz == 255) { + SoftwareTimerDelete(m_nTimerId); hardware_led_set(1); - break; - default: - m_nTicksPerSecond = (1000000 / nFreqHz); - break; + return; } + + if (m_nTimerId < 0) { + m_nTimerId = SoftwareTimerAdd((1000U / nFreqHz),ledblink); + DEBUG_PRINTF("m_nTimerId=%d", m_nTimerId); + return; + } + + DEBUG_PRINTF("m_nTimerId=%d", m_nTimerId); + SoftwareTimerChange(m_nTimerId, (1000U / nFreqHz)); } private: @@ -218,10 +274,13 @@ class Hardware { hardware::ledblink::Mode m_Mode { hardware::ledblink::Mode::UNKNOWN }; bool m_doLock { false }; - uint32_t m_nTicksPerSecond { 0 }; - int32_t m_nToggleLed { 0 }; - uint32_t m_nMicrosPrevious { 0 }; + int32_t m_nTimerId { -1 }; + + Timer m_Timers[hal::SOFTWARE_TIMERS_MAX]; + uint32_t m_nTimersCount { 0 }; + int32_t m_nNextId { 0 }; + static inline int32_t m_nToggleLed { 0 }; static Hardware *s_pThis; }; diff --git a/lib-hal/include/hal_timers.h.template b/lib-hal/include/hal_timers.h.template new file mode 100755 index 000000000..b50162319 --- /dev/null +++ b/lib-hal/include/hal_timers.h.template @@ -0,0 +1,143 @@ +/** + * @file hal_timers.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef HAL_TIMERS_H_ +#define HAL_TIMERS_H_ + +#include + +#include "hardware.h" + +namespace hal { +#if !defined (CONFIG_HAL_TIMERS_COUNT) +# define CONFIG_HAL_TIMERS_COUNT 8 +#endif + +static constexpr uint32_t SOFTWARE_TIMERS_MAX = CONFIG_HAL_TIMERS_COUNT; + +typedef void (*TimerCallback)(); + + +class SoftwareTimer { +public: + struct Timer { + uint32_t nExpireTime; + uint32_t nIntervalMillis; + int32_t nId; + TimerCallback callback; + }; + + static SoftwareTimer& Get() { + static SoftwareTimer instance; + return instance; + } + + static int32_t Add(const uint32_t nIntervalMillis, const TimerCallback callback) { + return Get().IAdd(nIntervalMillis, callback); + } + + static bool Delete(const int32_t nId) { + return Get().IDelete(nId); + } + + static bool Change(const int32_t nId, const uint32_t nIntervalMillis) { + return Get().IChange(nId, nIntervalMillis); + } + + static void Run() { + Get().IRun(); + } + +private: + int32_t IAdd(const uint32_t nIntervalMillis, const TimerCallback callback) { + if (m_nTimersCount >= SOFTWARE_TIMERS_MAX) { +#ifdef NDEBUG + console_error("SoftwareTimerAdd\n"); +#endif + return -1; + } + + const auto nCurrentTime = Hardware::Millis(); + + Timer newTimer = { + .nExpireTime = nCurrentTime + nIntervalMillis, + .nIntervalMillis = nIntervalMillis, + .callback = callback, + .nId = m_nNextId++ + }; + + m_Timers[m_nTimersCount++] = newTimer; + + return newTimer.nId; + } + + bool IDelete(const int32_t nId) { + for (uint32_t i = 0; i < m_nTimersCount; ++i) { + if (m_Timers[i].nId == nId) { + for (uint32_t j = i; j < m_nTimersCount - 1; ++j) { + m_Timers[j] = m_Timers[j + 1]; + } + --m_nTimersCount; + + return true; + } + } + + return false; + } + + bool IChange(const int32_t nId, const uint32_t nIntervalMillis) { + for (uint32_t i = 0; i < m_nTimersCount; ++i) { + if (m_Timers[i].nId == nId) { + m_Timers[i].nExpireTime = Hardware::Millis() + nIntervalMillis; + m_Timers[i].nIntervalMillis = nIntervalMillis; + + return true; + } + } + + return false; + } + + void IRun() { + const auto nCurrentTime = Hardware::Millis(); + + for (uint32_t i = 0; i < m_nTimersCount; i++) { + if (m_Timers[i].nExpireTime <= nCurrentTime) { + m_Timers[i].callback(); + m_Timers[i].nExpireTime = nCurrentTime + m_Timers[i].nIntervalMillis; + } + } + } + +private: + Timer m_Timers[SOFTWARE_TIMERS_MAX]; + uint32_t m_nTimersCount; + int32_t m_nNextId; +}; + +} // namespace hal + +#endif /* HAL_TIMERS_H_ */ diff --git a/lib-hal/include/hardware.h b/lib-hal/include/hardware.h index a676855a3..e7a2d94d7 100644 --- a/lib-hal/include/hardware.h +++ b/lib-hal/include/hardware.h @@ -47,6 +47,16 @@ enum class Mode { } // namespace ledblink } // namespace hardware +namespace hal { +#if !defined (CONFIG_HAL_TIMERS_COUNT) +# define CONFIG_HAL_TIMERS_COUNT 8 +#endif + +static constexpr uint32_t SOFTWARE_TIMERS_MAX = CONFIG_HAL_TIMERS_COUNT; + +typedef void (*TimerCallback)(); +} // namespace hal + #if defined(__linux__) || defined (__APPLE__) # if defined (CONFIG_HAL_USE_MINIMUM) # include "linux/minimum/hardware.h" diff --git a/lib-hal/include/linux/hardware.h b/lib-hal/include/linux/hardware.h index f935c9f04..268917ba2 100644 --- a/lib-hal/include/linux/hardware.h +++ b/lib-hal/include/linux/hardware.h @@ -33,6 +33,7 @@ #include #include +#include #include #include #include @@ -86,7 +87,6 @@ class Hardware { uint32_t GetUpTime(); bool SetTime(const struct tm *pTime); - void GetTime(struct tm *pTime); bool SetAlarm(const struct tm *pTime); void GetAlarm(struct tm *pTime); @@ -118,7 +118,72 @@ class Hardware { return m_Mode; } - void Run() {} // Not needed + struct Timer { + uint32_t nExpireTime; + uint32_t nIntervalMillis; + int32_t nId; + hal::TimerCallback callback; + }; + + int32_t SoftwareTimerAdd(const uint32_t nIntervalMillis, const hal::TimerCallback callback) { + if (m_nTimersCount >= hal::SOFTWARE_TIMERS_MAX) { +#ifdef NDEBUG + fprintf(stderr, "SoftwareTimerAdd\n"); +#endif + return -1; + } + + const auto nCurrentTime = Hardware::Millis(); + + Timer newTimer = { + .nExpireTime = nCurrentTime + nIntervalMillis, + .nIntervalMillis = nIntervalMillis, + .nId = m_nNextId++, + .callback = callback, + }; + + m_Timers[m_nTimersCount++] = newTimer; + + return newTimer.nId; + } + + bool SoftwareTimerDelete(int32_t& nId) { + for (uint32_t i = 0; i < m_nTimersCount; ++i) { + if (m_Timers[i].nId == nId) { + for (uint32_t j = i; j < m_nTimersCount - 1; ++j) { + m_Timers[j] = m_Timers[j + 1]; + } + --m_nTimersCount; + nId = -1; + return true; + } + } + + return false; + } + + bool SoftwareTimerChange(const int32_t nId, const uint32_t nIntervalMillis) { + for (uint32_t i = 0; i < m_nTimersCount; ++i) { + if (m_Timers[i].nId == nId) { + m_Timers[i].nExpireTime = Hardware::Millis() + nIntervalMillis; + m_Timers[i].nIntervalMillis = nIntervalMillis; + return true; + } + } + + return false; + } + + void Run() { + const auto nCurrentTime = Hardware::Get()->Millis(); + + for (uint32_t i = 0; i < m_nTimersCount; i++) { + if (m_Timers[i].nExpireTime <= nCurrentTime) { + m_Timers[i].callback(); + m_Timers[i].nExpireTime = nCurrentTime + m_Timers[i].nIntervalMillis; + } + } + } static Hardware *Get() { return s_pThis; @@ -165,6 +230,10 @@ class Hardware { hardware::ledblink::Mode m_Mode { hardware::ledblink::Mode::UNKNOWN }; bool m_doLock { false }; + Timer m_Timers[hal::SOFTWARE_TIMERS_MAX]; + uint32_t m_nTimersCount { 0 }; + int32_t m_nNextId { 0 }; + static Hardware *s_pThis; }; diff --git a/lib-hal/include/rpi/hardware.h b/lib-hal/include/rpi/hardware.h index d6cb67b8d..eb33a9043 100644 --- a/lib-hal/include/rpi/hardware.h +++ b/lib-hal/include/rpi/hardware.h @@ -88,11 +88,6 @@ class Hardware { } bool SetTime(const struct tm *pTime); - void GetTime(struct tm *pTime); - - time_t GetTime() { - return time(nullptr); - } uint32_t GetUpTime() { return hardware_uptime_seconds(); diff --git a/lib-hal/posix/file.cpp b/lib-hal/posix/file.cpp index d44742cb9..26a5438ab 100644 --- a/lib-hal/posix/file.cpp +++ b/lib-hal/posix/file.cpp @@ -406,7 +406,7 @@ static dirent_t s_dirent; DIR *opendir([[maybe_unused]] const char *dirname) { #if !defined (CONFIG_FS_ENABLE_WRITE) errno = ENOSYS; - return 0; + return nullptr; #else const auto len = strlen(dirname); @@ -437,7 +437,7 @@ DIR *opendir([[maybe_unused]] const char *dirname) { struct dirent *readdir([[maybe_unused]] DIR *dirp) { #if !defined (CONFIG_FS_ENABLE_WRITE) errno = ENOSYS; - return 0; + return nullptr; #else FILINFO fno; diff --git a/lib-hal/src/h3/hardware.cpp b/lib-hal/src/h3/hardware.cpp index 828ae5421..29bec431c 100644 --- a/lib-hal/src/h3/hardware.cpp +++ b/lib-hal/src/h3/hardware.cpp @@ -25,8 +25,9 @@ #include #include -#include +#include #include +#include #include #include "hardware.h" @@ -47,6 +48,10 @@ #include "logic_analyzer.h" +namespace net { +void net_shutdown(); +} // namespace net + namespace soc { #if defined (ORANGE_PI) static constexpr char NAME[] = "H2+"; @@ -129,20 +134,18 @@ const char *Hardware::GetSocName(uint8_t &nLength) { return soc::NAME; } -#include - bool Hardware::Reboot() { puts("Rebooting ..."); + h3_watchdog_disable(); + #if !defined(DISABLE_RTC) m_HwClock.SysToHc(); #endif - h3_watchdog_disable(); - RebootHandler(); - h3_watchdog_enable(); + net::net_shutdown(); clean_data_cache(); invalidate_data_cache(); @@ -156,6 +159,8 @@ bool Hardware::Reboot() { SetMode(hardware::ledblink::Mode::REBOOT); + h3_watchdog_enable(); + for (;;) { Run(); } diff --git a/lib-hal/src/h3/sys_time.cpp b/lib-hal/src/h3/sys_time.cpp index 9ac63a0f8..f3110ed9f 100644 --- a/lib-hal/src/h3/sys_time.cpp +++ b/lib-hal/src/h3/sys_time.cpp @@ -43,5 +43,5 @@ void __attribute__((cold)) sys_time_init() { settimeofday(&tv, nullptr); DEBUG_PRINTF("%.4d/%.2d/%.2d %.2d:%.2d:%.2d", 1900 + tmbuf.tm_year, tmbuf.tm_mon, tmbuf.tm_mday, tmbuf.tm_hour, tmbuf.tm_min, tmbuf.tm_sec); - DEBUG_PRINTF("%s", asctime(localtime((const time_t* ) &seconds))); +// DEBUG_PRINTF("%s", asctime(localtime((const time_t* ) &seconds))); } diff --git a/lib-hal/src/hardware.cpp b/lib-hal/src/hardware.cpp index 64e618604..706f1853d 100755 --- a/lib-hal/src/hardware.cpp +++ b/lib-hal/src/hardware.cpp @@ -2,7 +2,7 @@ * @file hardware.cpp * */ -/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,11 +28,9 @@ #include "hardware.h" #include "debug.h" -namespace hardware { -namespace ledblink { +namespace hardware::ledblink { void __attribute__((weak)) display([[maybe_unused]] const uint32_t nState) {} -} // namespace ledblink -} // namespace hardware +} // namespace hardware::ledblink enum class FreqMode { OFF_OFF = 0, NORMAL = 1, DATA = 3, FAST = 5, REBOOT = 8, OFF_ON = 255 diff --git a/lib-hal/src/linux/minimum/exec_cmd.cpp b/lib-hal/src/linux/minimum/exec_cmd.cpp old mode 100755 new mode 100644 index 2283f59df..3be2d5044 --- a/lib-hal/src/linux/minimum/exec_cmd.cpp +++ b/lib-hal/src/linux/minimum/exec_cmd.cpp @@ -29,7 +29,7 @@ bool exec_cmd(const char *pCmd, char *Result, int nResultSize) { auto *fp = popen(pCmd, "r"); - if (fgets(Result, nResultSize - 1, fp) == 0) { + if (fgets(Result, nResultSize - 1, fp) == nullptr) { pclose(fp); return false; } diff --git a/lib-hal/src/rpi/hardware.cpp b/lib-hal/src/rpi/hardware.cpp index 50ea29e82..c1fb9331b 100644 --- a/lib-hal/src/rpi/hardware.cpp +++ b/lib-hal/src/rpi/hardware.cpp @@ -159,22 +159,6 @@ bool Hardware::SetTime(const struct tm *pTime) { return true; } -void Hardware::GetTime(struct tm *pTime) { - time_t ltime; - struct tm *local_time; - - ltime = time(nullptr); - local_time = localtime(<ime); - - pTime->tm_year = local_time->tm_year; - pTime->tm_mon = local_time->tm_mon ; - pTime->tm_mday = local_time->tm_mday; - // - pTime->tm_hour = local_time->tm_hour; - pTime->tm_min = local_time->tm_min; - pTime->tm_sec = local_time->tm_sec; -} - bool Hardware::Reboot() { hardware_led_set(1); From de5774398f9c81feb4084a394a5afca2795184ce Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 16 Aug 2024 14:38:53 +0200 Subject: [PATCH 10/17] Minor code cleanup --- include/cstring | 37 +++++++- lib-artnet/Makefile.H3 | 2 +- lib-artnet/include/artnetmsgconst.h | 6 +- lib-artnet/include/artnetnode.h | 47 +++++----- lib-artnet/src/artnetconst.cpp | 7 +- .../src/controller/json_get_polltable.cpp | 5 - lib-artnet/src/node/artnetmsgconst.cpp | 8 +- lib-artnet/src/node/artnetnode.cpp | 16 +--- .../src/node/artnetnodehandleaddress.cpp | 4 - lib-artnet/src/node/artnetnodehandlesync.cpp | 6 -- .../src/node/rdm/controller/handlerdmsub.cpp | 4 - .../src/node/rdm/responder/handlerdm.cpp | 4 +- .../src/node/rdm/responder/handlerdmsub.cpp | 4 - lib-bcm2835/include/bcm2835_gpio.h | 6 +- lib-bcm2835/src/bcm2837_gpio_virt.c | 2 +- lib-configstore/device/i2c/storedevice.cpp | 2 +- lib-configstore/device/spi/storedevice.cpp | 2 +- lib-configstore/include/configstore.h | 11 ++- lib-ddp/src/ddpdisplay.cpp | 6 +- lib-device/Makefile.Linux | 2 +- lib-device/include/ema.h | 77 +++++++++++++++ lib-display/include/spi/ili9341.h | 75 ++++++++------- lib-display/include/spi/st77xx.h | 77 ++++++++------- lib-displayudf/include/displayudf.h | 19 ++-- .../src/artnet/displayudfshowartnet.cpp | 4 + lib-displayudf/src/network/network.cpp | 12 ++- lib-displayudf/src/network/ntpclient.cpp | 2 +- lib-dmxmonitor/include/dmxmonitor.h | 2 +- lib-dmxserial/include/dmxserial.h | 4 +- lib-dmxserial/include/dmxserialtftp.h | 2 +- lib-dmxserial/src/dmxserial.cpp | 8 +- lib-dmxserial/src/dmxserialhandleudp.cpp | 6 +- lib-e131/include/e131bridge.h | 85 ++++++++--------- lib-e131/include/e131msgconst.h | 3 +- lib-e131/src/node/dmxin/discoverypacket.cpp | 28 +++--- lib-e131/src/node/dmxin/handledmxin.cpp | 68 +++++++------- lib-e131/src/node/e131bridge.cpp | 25 +++-- .../node/e131bridgehandlesynchronization.cpp | 13 +-- lib-e131/src/node/e131msgconst.cpp | 3 +- lib-flashcode/src/gd32/flashcode.cpp | 2 +- .../include/flashcodeinstall.h | 10 +- lib-h3/include/board/h3_opi_zero.h | 1 + lib-l6470dmx/include/sparkfundmx.h | 2 +- lib-l6470dmx/src/sparkfundmx.cpp | 2 +- lib-ltc/include/ntpserver.h | 2 +- lib-ltc/src/arm/gd32/ltcsender.cpp | 1 - lib-ltc/src/arm/gd32/platform_ltc.cpp | 3 - lib-ltc/src/displayrgb/ltcdisplayrgb.cpp | 4 +- lib-ltc/src/ltcdisplayparams.cpp | 14 +-- lib-ltc/src/ntpserver.cpp | 2 +- lib-midi/include/applemidi.h | 2 +- lib-osc/src/oscsimplesend.cpp | 2 +- lib-pca9685dmx/include/pca9685dmxled.h | 2 +- lib-pca9685dmx/include/pca9685dmxservo.h | 2 +- lib-rdm/Rules.mk | 2 +- lib-rdm/include/rdmdevice.h | 23 +++++ lib-rdm/include/rdmdiscovery.h | 2 +- lib-rdm/src/controller/rdmdiscovery.cpp | 18 ++-- lib-rdm/src/llrp/llrpdevice.cpp | 4 +- lib-rdm/src/llrp/llrpdevicedump.cpp | 2 +- lib-rdm/src/llrp/rdmhandlere1372.cpp | 93 ++++++++++++------- lib-rdm/src/rdmdevice.cpp | 26 ++---- lib-remoteconfig/include/remoteconfig.h | 4 +- .../include/tftp/tftpfileserver.h | 4 +- lib-remoteconfig/src/httpd/httpd.cpp | 2 +- .../src/httpd/httpdhandlerequest.cpp | 5 +- lib-remoteconfig/src/remoteconfig.cpp | 76 +++++---------- lib-remoteconfig/src/remoteconfigfactory.cpp | 6 +- lib-remoteconfig/src/remoteconfigreboot.cpp | 2 - lib-remoteconfig/src/remoteconfigstatic.cpp | 2 +- lib-remoteconfig/src/shell/shellcmd.cpp | 11 +-- lib-showfile/include/showfileosc.h | 10 +- lib-showfile/include/showfiletftp.h | 2 +- lib-tlc59711dmx/include/tlc59711dmx.h | 2 +- lib-tlc59711dmx/src/tlc59711dmx.cpp | 9 +- lib-widget/src/hdmi/widgetmonitor.cpp | 12 +-- linux_artnet/src/main.cpp | 4 +- linux_ddp/src/main.cpp | 2 +- linux_e131/src/main.cpp | 2 +- linux_osc/src/main.cpp | 2 +- linux_pp/src/main.cpp | 2 +- opi_dmx_monitor/firmware/main.cpp | 2 +- opi_emac_artnet_dmx/Makefile.H3 | 2 +- opi_emac_artnet_dmx/firmware/main.cpp | 5 +- opi_emac_artnet_dmx_multi/Makefile.H3 | 3 +- opi_emac_artnet_dmx_multi/firmware/main.cpp | 5 +- opi_emac_artnet_monitor/firmware/main.cpp | 8 +- opi_emac_artnet_rdm_l6470/firmware/main.cpp | 8 +- opi_emac_artnet_rdm_pca9685/firmware/main.cpp | 8 +- opi_emac_artnet_serial/firmware/main.cpp | 5 +- opi_emac_e131_artnet/firmware/main.cpp | 5 +- opi_emac_e131_artnet/include/artnetoutput.h | 2 +- opi_emac_e131_artnet/lib/artnetoutput.cpp | 4 +- opi_emac_e131_dmx/firmware/main.cpp | 7 +- opi_emac_e131_dmx_multi/firmware/main.cpp | 7 +- opi_emac_e131_monitor/firmware/main.cpp | 8 +- opi_emac_llrp_tftpd/Makefile.H3 | 16 +++- opi_emac_llrp_tftpd/firmware/main.cpp | 15 ++- opi_emac_ltc_smpte/firmware/main.cpp | 8 +- opi_emac_ltc_smpte/include/ltcsource.h | 2 +- opi_emac_ltc_smpte/lib/mcpbuttons.cpp | 1 - opi_emac_ltc_smpte/lib/networkdisplay.cpp | 59 +++++++----- opi_emac_ltc_smpte/lib/ntpclientdisplay.cpp | 2 +- opi_emac_osc_client/firmware/main.cpp | 4 +- opi_emac_osc_client/lib/networkdisplay.cpp | 78 +++++++++++++--- opi_emac_osc_dmx/firmware/main.cpp | 4 +- opi_emac_osc_dmx/lib/networkdisplay.cpp | 78 +++++++++++++--- opi_emac_osc_monitor/firmware/main.cpp | 6 +- opi_emac_osc_monitor/lib/networkdisplay.cpp | 78 +++++++++++++--- opi_emac_osc_monitor/lib/ntpclient.cpp | 2 +- opi_emac_showfile_artnet/firmware/main.cpp | 6 +- opi_emac_showfile_e131/firmware/main.cpp | 6 +- opi_midi_monitor/firmware/main.cpp | 2 +- opi_rdm_responder/firmware/main.cpp | 17 ++-- opi_rdm_responder/lib/display.cpp | 4 +- opi_rdm_responder/lib/personalityupdate.cpp | 10 +- opi_rdm_responder_l6470/firmware/main.cpp | 2 +- rpi_wifi_artnet_monitor/firmware/main.cpp | 2 +- rpi_wifi_e131_dmx/Makefile.BCM | 2 +- rpi_wifi_e131_monitor/Makefile.BCM | 2 +- rpi_wifi_osc_dmx/lib/handler.cpp | 52 ----------- rpi_wifi_osc_monitor/firmware/main.cpp | 2 +- rpi_wifi_osc_monitor/lib/handler.cpp | 2 +- 123 files changed, 877 insertions(+), 738 deletions(-) mode change 100755 => 100644 lib-configstore/include/configstore.h create mode 100755 lib-device/include/ema.h mode change 100644 => 100755 lib-e131/include/e131bridge.h delete mode 100644 rpi_wifi_osc_dmx/lib/handler.cpp diff --git a/include/cstring b/include/cstring index 998d93dac..b32bea0fb 100644 --- a/include/cstring +++ b/include/cstring @@ -2,7 +2,7 @@ * @file cstring * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,8 +26,37 @@ #ifndef CSTRING_ #define CSTRING_ -#ifdef __cplusplus -# include -#endif +#include + +// Get rid of those macros defined in in lieu of real functions. +#undef memcmp +#undef memcpy +#undef memmove +#undef memset +#undef strchr +#undef strcmp +#undef strcpy +#undef strerror +#undef strlen +#undef strncmp +#undef strncpy +#undef strstr +#undef strtok + +namespace std { +using ::memcmp; +using ::memcpy; +using ::memmove; +using ::memset; +using ::strcmp; +using ::strcpy; +using ::strerror; +using ::strlen; +using ::strncmp; +using ::strncpy; +using ::strtok; +using ::strchr; +using ::strstr; +} #endif /* CSTRING_ */ diff --git a/lib-artnet/Makefile.H3 b/lib-artnet/Makefile.H3 index 3582ff3a2..886e31480 100644 --- a/lib-artnet/Makefile.H3 +++ b/lib-artnet/Makefile.H3 @@ -1,4 +1,4 @@ -DEFINES=NDEBUG +#DEFINES=NDEBUG EXTRA_INCLUDES= diff --git a/lib-artnet/include/artnetmsgconst.h b/lib-artnet/include/artnetmsgconst.h index d82df31be..18c540ee6 100644 --- a/lib-artnet/include/artnetmsgconst.h +++ b/lib-artnet/include/artnetmsgconst.h @@ -2,10 +2,7 @@ * @file artnetmsgconst.h * */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,7 +28,6 @@ class ArtNetMsgConst { public: - static const char PARAMS[]; static const char START[]; static const char STARTED[]; static const char RDM_RUN[]; diff --git a/lib-artnet/include/artnetnode.h b/lib-artnet/include/artnetnode.h index eebc6017c..10a8eead8 100755 --- a/lib-artnet/include/artnetnode.h +++ b/lib-artnet/include/artnetnode.h @@ -78,6 +78,10 @@ #include "debug.h" +#ifndef ALIGNED +# define ALIGNED __attribute__ ((aligned (4))) +#endif + namespace artnetnode { enum class FailSafe : uint8_t { LAST = 0x08, OFF= 0x09, ON = 0x0a, PLAYBACK = 0x0b, RECORD = 0x0c @@ -88,9 +92,9 @@ struct State { uint32_t ArtPollIpAddress; uint32_t ArtPollReplyCount; uint32_t ArtPollReplyDelayMillis; - artnet::ArtPollQueue ArtPollReplyQueue[4]; uint32_t ArtDmxIpAddress; uint32_t ArtSyncMillis; ///< Latest ArtSync received time + artnet::ArtPollQueue ArtPollReplyQueue[4]; artnet::ReportCode reportCode; artnet::Status status; bool SendArtPollReplyOnChange; ///< ArtPoll : Flags Bit 1 : 1 = Send ArtPollReply whenever Node conditions change. @@ -114,10 +118,7 @@ struct State { }; struct Node { - uint32_t IPAddressTimeCode; - bool bMapUniverse0; ///< Art-Net 4 struct { - char ShortName[artnet::SHORT_NAME_LENGTH]; uint16_t PortAddress; ///< The Port-Address is a 15 bit number composed of Net+Sub-Net+Universe. uint8_t DefaultAddress; uint8_t NetSwitch; ///< Bits 14-8 of the 15 bit Port-Address are encoded into the bottom 7 bits of this field. @@ -125,7 +126,11 @@ struct Node { lightset::PortDir direction; artnet::PortProtocol protocol; ///< Art-Net 4 bool bLocalMerge; - } Port[artnetnode::MAX_PORTS]; + char ShortName[artnet::SHORT_NAME_LENGTH] ALIGNED; + } Port[artnetnode::MAX_PORTS] ALIGNED; + + uint32_t IPAddressTimeCode; + bool bMapUniverse0; ///< Art-Net 4 }; struct Source { @@ -135,11 +140,11 @@ struct Source { }; struct OutputPort { - Source SourceA; - Source SourceB; + Source SourceA ALIGNED; + Source SourceB ALIGNED; + uint32_t nIpRdm; uint8_t GoodOutput; uint8_t GoodOutputB; - uint32_t nIpRdm; uint8_t nPollReplyIndex; bool IsTransmitting; bool IsDataPending; @@ -572,14 +577,7 @@ class ArtNetNode { void SetNetSwitch(const uint32_t nPortIndex, const uint8_t nNetSwitch); void SetSubnetSwitch(const uint32_t nPortIndex, const uint8_t nSubnetSwitch); -#undef UNUSED -#if defined (ARTNET_ENABLE_SENDDIAG) -# define UNUSED -#else -# define UNUSED [[maybe_unused]] -#endif - - void SendDiag(UNUSED const artnet::PriorityCodes priorityCode, UNUSED const char *format, ...) { + void SendDiag([[maybe_unused]] const artnet::PriorityCodes priorityCode, [[maybe_unused]] const char *format, ...) { #if defined (ARTNET_ENABLE_SENDDIAG) if (!m_State.SendArtDiagData) { return; @@ -626,7 +624,9 @@ class ArtNetNode { void HandleRdmIn(); void HandleTrigger(); - uint16_t MakePortAddress(const uint16_t nUniverse, const uint32_t nPage); + uint16_t MakePortAddress(const uint16_t nUniverse, const uint32_t nPage) { + return artnet::make_port_address(m_Node.Port[nPage].NetSwitch, m_Node.Port[nPage].SubSwitch, nUniverse); + } void UpdateMergeStatus(const uint32_t nPortIndex); void CheckMergeTimeouts(const uint32_t nPortIndex); @@ -642,7 +642,7 @@ class ArtNetNode { void FailSafeRecord(); void FailSafePlayback(); - void Process(const uint16_t); + void Process(const uint32_t); #if defined (RDM_CONTROLLER) bool RdmDiscoveryRun() { @@ -709,12 +709,12 @@ class ArtNetNode { artnet::ArtRdm ArtRdm; }; UArtTodPacket m_ArtTodPacket; -#endif -#if defined (RDM_CONTROLLER) +# if defined (RDM_CONTROLLER) ArtNetRdmController *m_pArtNetRdmController; -#endif -#if defined (RDM_RESPONDER) +# endif +# if defined (RDM_RESPONDER) ArtNetRdmResponder *m_pArtNetRdmResponder; +# endif #endif #if defined (ARTNET_HAVE_TIMECODE) artnet::ArtTimeCode m_ArtTimeCode; @@ -729,7 +729,4 @@ class ArtNetNode { static ArtNetNode *s_pThis; }; -#if defined (UNUSED) -# undef UNUSED -#endif #endif /* ARTNETNODE_H_ */ diff --git a/lib-artnet/src/artnetconst.cpp b/lib-artnet/src/artnetconst.cpp index 29258bbc6..5e36a9fb9 100644 --- a/lib-artnet/src/artnetconst.cpp +++ b/lib-artnet/src/artnetconst.cpp @@ -2,10 +2,7 @@ * @file artnetconst.cpp * */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,7 +28,7 @@ #include "artnetconst.h" #include "artnet.h" -const uint8_t ArtNetConst::VERSION[] = { 1, 59 }; +const uint8_t ArtNetConst::VERSION[] = { 1, 60 }; const uint8_t ArtNetConst::ESTA_ID[artnet::ESTA_SIZE] = { 0x50, 0x00 }; ///< https://tsp.esta.org/tsp/working_groups/CP/mfctrIDs.php const uint8_t ArtNetConst::OEM_ID[] = { 0xff, 0xff }; ///< Waiting OEM from Artistic Licence Holdings Ltd. diff --git a/lib-artnet/src/controller/json_get_polltable.cpp b/lib-artnet/src/controller/json_get_polltable.cpp index d0b976e48..1c8b300a1 100755 --- a/lib-artnet/src/controller/json_get_polltable.cpp +++ b/lib-artnet/src/controller/json_get_polltable.cpp @@ -23,11 +23,6 @@ * THE SOFTWARE. */ -/** - * TODO - * FIXME - */ - #include #include #include diff --git a/lib-artnet/src/node/artnetmsgconst.cpp b/lib-artnet/src/node/artnetmsgconst.cpp index f697afc50..7e07038ba 100644 --- a/lib-artnet/src/node/artnetmsgconst.cpp +++ b/lib-artnet/src/node/artnetmsgconst.cpp @@ -2,10 +2,7 @@ * @file artnetmsgconst.cpp * */ -/** - * Art-Net Designed by and Copyright Artistic Licence Holdings Ltd. - */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -28,9 +25,6 @@ #include "artnetmsgconst.h" -const char ArtNetMsgConst::PARAMS[] = "Configuring Art-Net"; const char ArtNetMsgConst::START[] = "Starting Art-Net"; const char ArtNetMsgConst::STARTED[] = "Art-Net started"; const char ArtNetMsgConst::RDM_RUN[] = "Running RDM Discovery"; - - diff --git a/lib-artnet/src/node/artnetnode.cpp b/lib-artnet/src/node/artnetnode.cpp index 1bdf36d62..0c5b113c1 100755 --- a/lib-artnet/src/node/artnetnode.cpp +++ b/lib-artnet/src/node/artnetnode.cpp @@ -356,20 +356,6 @@ void ArtNetNode::SetOutputStyle(const uint32_t nPortIndex, lightset::OutputStyle m_OutputPort[nPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::STYLE_CONSTANT); } -#if defined (OUTPUT_DMX_SEND) || defined (OUTPUT_DMX_SEND_MULTI) - /** - * FIXME I do not like this hack. It should be handled in dmx.cpp - */ - if ((m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) - && (outputStyle == lightset::OutputStyle::CONSTANT) - && (m_pLightSet != nullptr)) { - if (m_OutputPort[nPortIndex].IsTransmitting) { - m_OutputPort[nPortIndex].IsTransmitting = false; - m_pLightSet->Stop(nPortIndex); - } - } -#endif - m_State.IsSynchronousMode = false; if (m_State.status == artnet::Status::ON) { @@ -459,7 +445,7 @@ static artnet::OpCodes get_op_code(const uint32_t nBytesReceived, const uint8_t return artnet::OpCodes::OP_NOT_DEFINED; } -void ArtNetNode::Process(const uint16_t nBytesReceived) { +void ArtNetNode::Process(const uint32_t nBytesReceived) { if (__builtin_expect((nBytesReceived == 0), 1)) { const auto nDeltaMillis = m_nCurrentPacketMillis - m_nPreviousPacketMillis; diff --git a/lib-artnet/src/node/artnetnodehandleaddress.cpp b/lib-artnet/src/node/artnetnodehandleaddress.cpp index 576f68984..24d983268 100644 --- a/lib-artnet/src/node/artnetnodehandleaddress.cpp +++ b/lib-artnet/src/node/artnetnodehandleaddress.cpp @@ -87,10 +87,6 @@ void ArtNetNode::SetLocalMerging() { DEBUG_EXIT } -uint16_t ArtNetNode::MakePortAddress(const uint16_t nUniverse, const uint32_t nPage) { - return artnet::make_port_address(m_Node.Port[nPage].NetSwitch, m_Node.Port[nPage].SubSwitch, nUniverse); -} - void ArtNetNode::SetUniverse(const uint32_t nPortIndex, const lightset::PortDir dir, const uint16_t nUniverse) { assert(nPortIndex < artnetnode::MAX_PORTS); diff --git a/lib-artnet/src/node/artnetnodehandlesync.cpp b/lib-artnet/src/node/artnetnodehandlesync.cpp index 39e6323fa..17c5f0ffa 100755 --- a/lib-artnet/src/node/artnetnodehandlesync.cpp +++ b/lib-artnet/src/node/artnetnodehandlesync.cpp @@ -41,12 +41,6 @@ void ArtNetNode::HandleSync() { if (!m_State.IsSynchronousMode) { m_State.IsSynchronousMode = true; - /* - * As the ArtSync is after the ArtDmx which are already processed - * we need to do a forced sync - */ - m_pLightSet->Sync(true); - SendDiag(artnet::PriorityCodes::DIAG_LOW, "Sync forced"); return; } diff --git a/lib-artnet/src/node/rdm/controller/handlerdmsub.cpp b/lib-artnet/src/node/rdm/controller/handlerdmsub.cpp index bcb0e95ad..bd59d8457 100755 --- a/lib-artnet/src/node/rdm/controller/handlerdmsub.cpp +++ b/lib-artnet/src/node/rdm/controller/handlerdmsub.cpp @@ -26,10 +26,6 @@ * THE SOFTWARE. */ -#ifdef NDEBUG -# undef NDEBUG //TODO Remove # undef NDEBUG -#endif - #include #include #include diff --git a/lib-artnet/src/node/rdm/responder/handlerdm.cpp b/lib-artnet/src/node/rdm/responder/handlerdm.cpp index 84e9c9e08..8398b9216 100755 --- a/lib-artnet/src/node/rdm/responder/handlerdm.cpp +++ b/lib-artnet/src/node/rdm/responder/handlerdm.cpp @@ -61,7 +61,7 @@ void ArtNetNode::HandleRdm() { const auto nLength = sizeof(struct artnet::ArtRdm) - sizeof(pArtRdm->RdmPacket) + nMessageLength; - Network::Get()->SendTo(m_nHandle, m_pReceiveBuffer, static_cast(nLength), m_nIpAddressFrom, artnet::UDP_PORT); + Network::Get()->SendTo(m_nHandle, m_pReceiveBuffer, nLength, m_nIpAddressFrom, artnet::UDP_PORT); } else { DEBUG_PUTS("No RDM response"); } @@ -135,7 +135,7 @@ void ArtNetNode::SendTod(uint32_t nPortIndex) { const auto nLength = sizeof(struct artnet::ArtTodData) - (sizeof(pTodData->Tod)) + (nDiscovered * 6U); - Network::Get()->SendTo(m_nHandle, pTodData, static_cast(nLength), Network::Get()->GetBroadcastIp(), artnet::UDP_PORT); + Network::Get()->SendTo(m_nHandle, pTodData, nLength, Network::Get()->GetBroadcastIp(), artnet::UDP_PORT); DEBUG_EXIT } diff --git a/lib-artnet/src/node/rdm/responder/handlerdmsub.cpp b/lib-artnet/src/node/rdm/responder/handlerdmsub.cpp index bcb0e95ad..bd59d8457 100755 --- a/lib-artnet/src/node/rdm/responder/handlerdmsub.cpp +++ b/lib-artnet/src/node/rdm/responder/handlerdmsub.cpp @@ -26,10 +26,6 @@ * THE SOFTWARE. */ -#ifdef NDEBUG -# undef NDEBUG //TODO Remove # undef NDEBUG -#endif - #include #include #include diff --git a/lib-bcm2835/include/bcm2835_gpio.h b/lib-bcm2835/include/bcm2835_gpio.h index 5c5a8d74d..2bf7a3025 100644 --- a/lib-bcm2835/include/bcm2835_gpio.h +++ b/lib-bcm2835/include/bcm2835_gpio.h @@ -100,7 +100,7 @@ extern "C" { * @return */ /*@unused@*/inline static uint8_t bcm2835_gpio_lev(const uint8_t pin) { - const uint32_t value = BCM2835_GPIO->GPLEV0; // TODO BUG pin > 32 + const uint32_t value = BCM2835_GPIO->GPLEV0; return (value & (1 << pin)) ? (uint8_t) HIGH : (uint8_t) LOW; } @@ -114,7 +114,7 @@ extern "C" { * @return */ /*@unused@*/inline static uint8_t bcm2835_gpio_eds(const uint8_t pin) { - const uint32_t value = BCM2835_GPIO->GPEDS0; // TODO BUG pin > 32 + const uint32_t value = BCM2835_GPIO->GPEDS0; return (value & (1 << pin)) ? (uint8_t) HIGH : (uint8_t) LOW; } @@ -126,7 +126,7 @@ extern "C" { * @param pin */ /*@unused@*/inline static void bcm2835_gpio_set_eds(const uint8_t pin) { - BCM2835_GPIO->GPEDS0 = (1 << pin); // TODO BUG pin > 32 + BCM2835_GPIO->GPEDS0 = (1 << pin); } diff --git a/lib-bcm2835/src/bcm2837_gpio_virt.c b/lib-bcm2835/src/bcm2837_gpio_virt.c index bdc7392c8..ff1455cd6 100644 --- a/lib-bcm2835/src/bcm2837_gpio_virt.c +++ b/lib-bcm2835/src/bcm2837_gpio_virt.c @@ -91,7 +91,7 @@ static uint32_t firmware_property_set(void) { vc_msg->tag.tag_id = RPI_FIRMWARE_FRAMEBUFFER_SET_GPIO_VIRTBUF; vc_msg->tag.buffer_size = 8; vc_msg->tag.data_size = 4; - vc_msg->tag.value = address + 4096; // FIXME + vc_msg->tag.value = address + 4096; vc_msg->end_tag = 0; if (bcm2835_mailbox_write_read(BCM2835_MAILBOX_PROP_CHANNEL, address) != address) { diff --git a/lib-configstore/device/i2c/storedevice.cpp b/lib-configstore/device/i2c/storedevice.cpp index c40303500..dd6e0e66a 100755 --- a/lib-configstore/device/i2c/storedevice.cpp +++ b/lib-configstore/device/i2c/storedevice.cpp @@ -50,7 +50,7 @@ StoreDevice::StoreDevice() : AT24C32(storedevice::I2C_INDEX) { if (!m_IsDetected) { printf("StoreDevice: No AT24C32 at %2x", AT24C32::GetAddress()); } else { - printf("StoreDevice: Detected AT24C32 with total %u bytes [%u kB]\n", GetSize(), GetSize() / 1024U); + printf("StoreDevice: AT24C32 total %u bytes [%u kB]\n", GetSize(), GetSize() / 1024U); } DEBUG_EXIT diff --git a/lib-configstore/device/spi/storedevice.cpp b/lib-configstore/device/spi/storedevice.cpp index cb3078f6f..1c77549f1 100755 --- a/lib-configstore/device/spi/storedevice.cpp +++ b/lib-configstore/device/spi/storedevice.cpp @@ -37,7 +37,7 @@ StoreDevice::StoreDevice() { if (spi_flash_probe(0, 0, 0) < 0) { DEBUG_PUTS("No SPI flash chip"); } else { - printf("StoreDevice: Detected %s with sector size %u total %u bytes [%u kB]\n", + printf("StoreDevice: %s sector size %u total %u bytes [%u kB]\n", spi_flash_get_name(), static_cast(spi_flash_get_sector_size()), static_cast(spi_flash_get_size()), diff --git a/lib-configstore/include/configstore.h b/lib-configstore/include/configstore.h old mode 100755 new mode 100644 index 9c6198cec..bb69861c9 --- a/lib-configstore/include/configstore.h +++ b/lib-configstore/include/configstore.h @@ -81,10 +81,6 @@ class ConfigStore: StoreDevice { ; } - bool HaveFlashChip() const { - return s_bHaveFlashChip; - } - void Update(configstore::Store store, uint32_t nOffset, const void *pData, uint32_t nDataLength, uint32_t nSetList = 0, uint32_t nOffsetSetList = 0); void Update(configstore::Store store, const void *pData, uint32_t nDataLength) { Update(store, 0, pData, nDataLength); @@ -93,6 +89,11 @@ class ConfigStore: StoreDevice { void Copy(const configstore::Store store, void *pData, uint32_t nDataLength, uint32_t nOffset = 0, const bool doUpdate = true); void ResetSetList(configstore::Store store); + void ResetSetListAll() { + for (uint32_t i = 0; i < static_cast(configstore::Store::LAST); i++) { + ResetSetList(static_cast(i)); + } + } bool Flash(); @@ -167,7 +168,7 @@ class ConfigStore: StoreDevice { static constexpr uint32_t SIZE = 4096; }; - static_assert(sizeof(struct Env) == FlashStore::ENV_SIZE); + static_assert(sizeof(struct Env) == FlashStore::ENV_SIZE, ""); static bool s_bHaveFlashChip; diff --git a/lib-ddp/src/ddpdisplay.cpp b/lib-ddp/src/ddpdisplay.cpp index 4b386d3e2..13c4a6f80 100644 --- a/lib-ddp/src/ddpdisplay.cpp +++ b/lib-ddp/src/ddpdisplay.cpp @@ -169,7 +169,7 @@ void DdpDisplay::HandleQuery() { m_Packet.header.len[0] = static_cast(nLength >> 8); m_Packet.header.len[1] = static_cast(nLength); - Network::Get()->SendTo(m_nHandle, &m_Packet, static_cast(HEADER_LEN + static_cast(nLength)), Network::Get()->GetIp() | ~(Network::Get()->GetNetmask()), ddp::UDP_PORT); + Network::Get()->SendTo(m_nHandle, &m_Packet, (HEADER_LEN + static_cast(nLength)), Network::Get()->GetIp() | ~(Network::Get()->GetNetmask()), ddp::UDP_PORT); } if ((m_Packet.header.id & id::STATUS) == id::CONFIG) { @@ -206,9 +206,9 @@ void DdpDisplay::HandleQuery() { m_Packet.header.len[0] = static_cast(nLength >> 8); m_Packet.header.len[1] = static_cast(nLength); - Network::Get()->SendTo(m_nHandle, &m_Packet, static_cast(HEADER_LEN + static_cast(nLength)), m_nFromIp, ddp::UDP_PORT); + Network::Get()->SendTo(m_nHandle, &m_Packet, HEADER_LEN + nLength, m_nFromIp, ddp::UDP_PORT); - debug_dump(&m_Packet, static_cast(HEADER_LEN + static_cast(nLength))); + debug_dump(&m_Packet, HEADER_LEN + nLength); } DEBUG_EXIT diff --git a/lib-device/Makefile.Linux b/lib-device/Makefile.Linux index 192da4034..29568cae2 100644 --- a/lib-device/Makefile.Linux +++ b/lib-device/Makefile.Linux @@ -1,4 +1,4 @@ -DEFINES=NDEBUG +#DEFINES=NDEBUG EXTRA_INCLUDES= diff --git a/lib-device/include/ema.h b/lib-device/include/ema.h new file mode 100755 index 000000000..169d8763e --- /dev/null +++ b/lib-device/include/ema.h @@ -0,0 +1,77 @@ +/** + * @file ema.h + * + */ +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef EMA_H_ +#define EMA_H_ + +#include + +/** + * @brief + * The EMA class template implements an Exponential Moving Average (EMA) filter in a compact and efficient manner, + * suitable for real-time applications where resource constraints may be a consideration. + * The class uses unsigned integer arithmetic to achieve the filtering, + * which is beneficial for systems that do not have floating-point units or where performance is critical. + * + * @tparam K + * A compile-time constant that determines the weight of the EMA. + * Higher K values mean a slower response to changes in the input, making the EMA smoother. + */ + +template +class EMA { +public: + EMA(uint16_t nIntitial = 0) : nState(static_cast(nIntitial << K) - nIntitial) {} + + /** + * @brief + * This method allows resetting the internal state nState of the filter to a specific value nValue. + * It sets the state in the same way as the constructor, + * preparing the filter to start processing new inputs from the given value. + * @param nValue + */ + void Reset(const uint16_t nValue = 0) { + nState = static_cast(nValue << K) - nValue; + } + + uint16_t Filter(const uint16_t nInput) { + nState += nInput; + const auto nOutput = static_cast((nState + nHalf) >> K); + nState -= nOutput; + return nOutput; + } + + /* + * This static constant is used for rounding during the shift operation. + * It ensures that when you shift the value right by K bits, + * it rounds to the nearest integer rather than truncating. + */ + static constexpr uint16_t nHalf = K > 0 ? 1 << (K - 1) : 0; + +private: + uint16_t nState; +}; + +#endif /* EMA_H_ */ diff --git a/lib-display/include/spi/ili9341.h b/lib-display/include/spi/ili9341.h index fe72a20ef..ea0eccca1 100644 --- a/lib-display/include/spi/ili9341.h +++ b/lib-display/include/spi/ili9341.h @@ -2,7 +2,7 @@ * @file ili9341.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,25 +32,25 @@ namespace ili9341 { namespace cmd { -static constexpr uint8_t NOP = 0x00; -static constexpr uint8_t SWRESET = 0x01; -static constexpr uint8_t RDDID = 0x04; -static constexpr uint8_t RDDST = 0x09; -static constexpr uint8_t SLPIN = 0x10; -static constexpr uint8_t SLPOUT = 0x11; -static constexpr uint8_t PTLON = 0x12; -static constexpr uint8_t NORON = 0x13; -static constexpr uint8_t INVOFF = 0x20; -static constexpr uint8_t INVON = 0x21; -static constexpr uint8_t DISPOFF = 0x28; -static constexpr uint8_t DISPON = 0x29; -static constexpr uint8_t CASET = 0x2A; -static constexpr uint8_t RASET = 0x2B; -static constexpr uint8_t RAMWR = 0x2C; -static constexpr uint8_t RAMRD = 0x2E; -static constexpr uint8_t PTLAR = 0x30; -static constexpr uint8_t MADCTL = 0x36; -static constexpr uint8_t PIXFMT = 0x3A; +static constexpr uint8_t NOP = 0x00; +static constexpr uint8_t SWRESET = 0x01; +static constexpr uint8_t RDDID = 0x04; +static constexpr uint8_t RDDST = 0x09; +static constexpr uint8_t SLPIN = 0x10; +static constexpr uint8_t SLPOUT = 0x11; +static constexpr uint8_t PTLON = 0x12; +static constexpr uint8_t NORON = 0x13; +static constexpr uint8_t INVOFF = 0x20; +static constexpr uint8_t INVON = 0x21; +static constexpr uint8_t DISPOFF = 0x28; +static constexpr uint8_t DISPON = 0x29; +static constexpr uint8_t CASET = 0x2A; +static constexpr uint8_t RASET = 0x2B; +static constexpr uint8_t RAMWR = 0x2C; +static constexpr uint8_t RAMRD = 0x2E; +static constexpr uint8_t PTLAR = 0x30; +static constexpr uint8_t MADCTL = 0x36; +static constexpr uint8_t PIXFMT = 0x3A; } // namespace cmd namespace data { /** @@ -59,27 +59,26 @@ namespace data { * param: MY MX MV ML RGB MH - - * */ -static constexpr uint8_t MADCTL_MY = 0x80; ///< Page Address Order ('0': Top to Bottom, '1': the opposite) -static constexpr uint8_t MADCTL_MX = 0x40; ///< Column Address Order ('0': Left to Right, '1': the opposite) -static constexpr uint8_t MADCTL_MV = 0x20; ///< Page/Column Order ('0' = Normal Mode, '1' = Reverse Mode) -static constexpr uint8_t MADCTL_ML = 0x10; ///< Line Address Order ('0' = LCD Refresh Top to Bottom, '1' = the opposite) -static constexpr uint8_t MADCTL_RGB = 0x00; ///< Red-Green-Blue pixel order -static constexpr uint8_t MADCTL_BGR = 0x08; ///< Blue-Green-Red pixel order +static constexpr uint8_t MADCTL_MY = 0x80; ///< Page Address Order ('0': Top to Bottom, '1': the opposite) +static constexpr uint8_t MADCTL_MX = 0x40; ///< Column Address Order ('0': Left to Right, '1': the opposite) +static constexpr uint8_t MADCTL_MV = 0x20; ///< Page/Column Order ('0' = Normal Mode, '1' = Reverse Mode) +static constexpr uint8_t MADCTL_ML = 0x10; ///< Line Address Order ('0' = LCD Refresh Top to Bottom, '1' = the opposite) +static constexpr uint8_t MADCTL_RGB = 0x00; ///< Red-Green-Blue pixel order +static constexpr uint8_t MADCTL_BGR = 0x08; ///< Blue-Green-Red pixel order } // namespace data -//TODO Need to sort here namespace colour { -static constexpr uint16_t BLACK = 0x0000; -static constexpr uint16_t WHITE = 0xFFFF; -static constexpr uint16_t RED = 0xF800; -static constexpr uint16_t GREEN = 0x07E0; -static constexpr uint16_t BLUE = 0x001F; -static constexpr uint16_t DARKBLUE = 0X01CF; -static constexpr uint16_t CYAN = 0x07FF; -static constexpr uint16_t MAGENTA = 0xF81F; -static constexpr uint16_t YELLOW = 0xFFE0; -static constexpr uint16_t ORANGE = 0xFC00; -static constexpr uint16_t GRAY = 0X8430; +static constexpr uint16_t BLACK = 0x0000; +static constexpr uint16_t BLUE = 0x001F; +static constexpr uint16_t CYAN = 0x07FF; +static constexpr uint16_t DARKBLUE = 0X01CF; +static constexpr uint16_t GRAY = 0X8430; +static constexpr uint16_t GREEN = 0x07E0; +static constexpr uint16_t MAGENTA = 0xF81F; +static constexpr uint16_t ORANGE = 0xFC00; +static constexpr uint16_t RED = 0xF800; +static constexpr uint16_t WHITE = 0xFFFF; +static constexpr uint16_t YELLOW = 0xFFE0; } // namespace colour } // namespace ili9341 diff --git a/lib-display/include/spi/st77xx.h b/lib-display/include/spi/st77xx.h index 0371d4aba..af61b9b7e 100644 --- a/lib-display/include/spi/st77xx.h +++ b/lib-display/include/spi/st77xx.h @@ -2,7 +2,7 @@ * @file st77xx.h * */ -/* Copyright (C) 2022 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -34,27 +34,27 @@ namespace st77xx { namespace cmd { -static constexpr uint8_t NOP = 0x00; -static constexpr uint8_t SWRESET = 0x01; -static constexpr uint8_t RDDID = 0x04; -static constexpr uint8_t RDDST = 0x09; -static constexpr uint8_t SLPIN = 0x10; -static constexpr uint8_t SLPOUT = 0x11; -static constexpr uint8_t PTLON = 0x12; -static constexpr uint8_t NORON = 0x13; -static constexpr uint8_t INVOFF = 0x20; -static constexpr uint8_t INVON = 0x21; -static constexpr uint8_t DISPOFF = 0x28; -static constexpr uint8_t DISPON = 0x29; -static constexpr uint8_t CASET = 0x2A; -static constexpr uint8_t RASET = 0x2B; -static constexpr uint8_t RAMWR = 0x2C; -static constexpr uint8_t RAMRD = 0x2E; -static constexpr uint8_t PTLAR = 0x30; -static constexpr uint8_t TEOFF = 0x34; -static constexpr uint8_t TEON = 0x35; -static constexpr uint8_t MADCTL = 0x36; -static constexpr uint8_t COLMOD = 0x3A; +static constexpr uint8_t NOP = 0x00; +static constexpr uint8_t SWRESET = 0x01; +static constexpr uint8_t RDDID = 0x04; +static constexpr uint8_t RDDST = 0x09; +static constexpr uint8_t SLPIN = 0x10; +static constexpr uint8_t SLPOUT = 0x11; +static constexpr uint8_t PTLON = 0x12; +static constexpr uint8_t NORON = 0x13; +static constexpr uint8_t INVOFF = 0x20; +static constexpr uint8_t INVON = 0x21; +static constexpr uint8_t DISPOFF = 0x28; +static constexpr uint8_t DISPON = 0x29; +static constexpr uint8_t CASET = 0x2A; +static constexpr uint8_t RASET = 0x2B; +static constexpr uint8_t RAMWR = 0x2C; +static constexpr uint8_t RAMRD = 0x2E; +static constexpr uint8_t PTLAR = 0x30; +static constexpr uint8_t TEOFF = 0x34; +static constexpr uint8_t TEON = 0x35; +static constexpr uint8_t MADCTL = 0x36; +static constexpr uint8_t COLMOD = 0x3A; } // namespace cmd namespace data { /** @@ -64,30 +64,29 @@ namespace data { * */ /* Page Address Order ('0': Top to Bottom, '1': the opposite) */ -static constexpr uint8_t MADCTL_MY = 0x80; +static constexpr uint8_t MADCTL_MY = 0x80; /* Column Address Order ('0': Left to Right, '1': the opposite) */ -static constexpr uint8_t MADCTL_MX = 0x40; +static constexpr uint8_t MADCTL_MX = 0x40; /* Page/Column Order ('0' = Normal Mode, '1' = Reverse Mode) */ -static constexpr uint8_t MADCTL_MV = 0x20; +static constexpr uint8_t MADCTL_MV = 0x20; /* Line Address Order ('0' = LCD Refresh Top to Bottom, '1' = the opposite) */ -static constexpr uint8_t MADCTL_ML = 0x10; +static constexpr uint8_t MADCTL_ML = 0x10; /* RGB/BGR Order ('0' = RGB, '1' = BGR) */ -static constexpr uint8_t MADCTL_RGB = 0x00; +static constexpr uint8_t MADCTL_RGB = 0x00; } // namespace data -//TODO Need to sort here namespace colour { -static constexpr uint16_t BLACK = 0x0000; -static constexpr uint16_t WHITE = 0xFFFF; -static constexpr uint16_t RED = 0xF800; -static constexpr uint16_t GREEN = 0x07E0; -static constexpr uint16_t BLUE = 0x001F; -static constexpr uint16_t DARKBLUE = 0X01CF; -static constexpr uint16_t CYAN = 0x07FF; -static constexpr uint16_t MAGENTA = 0xF81F; -static constexpr uint16_t YELLOW = 0xFFE0; -static constexpr uint16_t ORANGE = 0xFC00; -static constexpr uint16_t GRAY = 0X8430; +static constexpr uint16_t BLACK = 0x0000; +static constexpr uint16_t BLUE = 0x001F; +static constexpr uint16_t CYAN = 0x07FF; +static constexpr uint16_t DARKBLUE = 0X01CF; +static constexpr uint16_t GRAY = 0X8430; +static constexpr uint16_t GREEN = 0x07E0; +static constexpr uint16_t MAGENTA = 0xF81F; +static constexpr uint16_t ORANGE = 0xFC00; +static constexpr uint16_t RED = 0xF800; +static constexpr uint16_t WHITE = 0xFFFF; +static constexpr uint16_t YELLOW = 0xFFE0; } // namespace colour } // namespace st77xx diff --git a/lib-displayudf/include/displayudf.h b/lib-displayudf/include/displayudf.h index 20a4e9664..d36ac873c 100644 --- a/lib-displayudf/include/displayudf.h +++ b/lib-displayudf/include/displayudf.h @@ -2,7 +2,7 @@ * @file displayudf.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -33,6 +33,7 @@ #if !defined (NO_EMAC) # include "network.h" +# include "net/protocol/dhcp.h" #endif #if defined (NODE_ARTNET_MULTI) @@ -241,21 +242,15 @@ class DisplayUdf final: public Display { Write(m_aLabels[static_cast(displayudf::Labels::HOSTNAME)], Network::Get()->GetHostName()); } - void ShowDhcpStatus(network::dhcp::ClientStatus nStatus) { - switch (nStatus) { - case network::dhcp::ClientStatus::IDLE: + void ShowDhcpStatus(net::dhcp::State state) { + switch (state) { + case net::dhcp::State::STATE_OFF: break; - case network::dhcp::ClientStatus::RENEW: + case net::dhcp::State::STATE_RENEWING: ClearEndOfLine(); Printf(m_aLabels[static_cast(displayudf::Labels::IP)], "DHCP renewing"); break; - case network::dhcp::ClientStatus::GOT_IP: - break; - case network::dhcp::ClientStatus::RETRYING: - ClearEndOfLine(); - Printf(m_aLabels[static_cast(displayudf::Labels::IP)], "DHCP retrying"); - break; - case network::dhcp::ClientStatus::FAILED: + case net::dhcp::State::STATE_BOUND: break; default: break; diff --git a/lib-displayudf/src/artnet/displayudfshowartnet.cpp b/lib-displayudf/src/artnet/displayudfshowartnet.cpp index 75db7572f..3f4039ed8 100644 --- a/lib-displayudf/src/artnet/displayudfshowartnet.cpp +++ b/lib-displayudf/src/artnet/displayudfshowartnet.cpp @@ -85,7 +85,11 @@ void DisplayUdf::ShowUniverseArtNetNode() { 'A' + nArtNetPortIndex, nUniverse, lightset::get_merge_mode(pArtNetNode->GetMergeMode(nPortIndex), true), +#if (ARTNET_VERSION >= 4) artnet::get_protocol_mode(pArtNetNode->GetPortProtocol4(nPortIndex), true), +#else + "Art-Net", +#endif #if defined (OUTPUT_HAVE_STYLESWITCH) pArtNetNode->GetOutputStyle(nPortIndex) == lightset::OutputStyle::CONSTANT ? 'C' : 'D', #endif diff --git a/lib-displayudf/src/network/network.cpp b/lib-displayudf/src/network/network.cpp index 2dd218479..4e4aa13e3 100644 --- a/lib-displayudf/src/network/network.cpp +++ b/lib-displayudf/src/network/network.cpp @@ -2,7 +2,7 @@ * @file network.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,10 +23,12 @@ * THE SOFTWARE. */ -#include "network.h" +#undef NDEBUG + #include "displayudf.h" +#include "net/protocol/dhcp.h" -namespace network { +namespace net { void display_emac_config() { DisplayUdf::Get()->ShowEmacInit(); } @@ -59,7 +61,7 @@ void display_emac_shutdown() { DisplayUdf::Get()->ShowShutdown(); } -void display_dhcp_status(network::dhcp::ClientStatus status) { - DisplayUdf::Get()->ShowDhcpStatus(status); +void display_dhcp_status(net::dhcp::State state) { + DisplayUdf::Get()->ShowDhcpStatus(state); } } // namespace network diff --git a/lib-displayudf/src/network/ntpclient.cpp b/lib-displayudf/src/network/ntpclient.cpp index 19cfeba5d..6d9d91496 100644 --- a/lib-displayudf/src/network/ntpclient.cpp +++ b/lib-displayudf/src/network/ntpclient.cpp @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -#include "ntp.h" +#include "net/protocol/ntp.h" #include "display.h" namespace ntpclient { diff --git a/lib-dmxmonitor/include/dmxmonitor.h b/lib-dmxmonitor/include/dmxmonitor.h index f487881df..e2fb4fa5f 100644 --- a/lib-dmxmonitor/include/dmxmonitor.h +++ b/lib-dmxmonitor/include/dmxmonitor.h @@ -72,7 +72,7 @@ class DMXMonitor: public LightSet { #endif } - void Sync([[maybe_unused]] const bool doForce = false) override {} + void Sync() override {} void Blackout([[maybe_unused]] bool bBlackout) override { DEBUG_ENTRY diff --git a/lib-dmxserial/include/dmxserial.h b/lib-dmxserial/include/dmxserial.h index 41653962d..89f6f180e 100644 --- a/lib-dmxserial/include/dmxserial.h +++ b/lib-dmxserial/include/dmxserial.h @@ -2,7 +2,7 @@ * @file dmxserial.h * */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -67,7 +67,7 @@ class DmxSerial: public LightSet { void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; void Sync(const uint32_t nPortIndex) override; - void Sync(const bool doForce = false) override; + void Sync() override; void Run(); diff --git a/lib-dmxserial/include/dmxserialtftp.h b/lib-dmxserial/include/dmxserialtftp.h index 3e1cbc22b..781191121 100644 --- a/lib-dmxserial/include/dmxserialtftp.h +++ b/lib-dmxserial/include/dmxserialtftp.h @@ -28,7 +28,7 @@ #include -#include "tftpdaemon.h" +#include "net/apps/tftpdaemon.h" class DmxSerialTFTP final: public TFTPDaemon { public: diff --git a/lib-dmxserial/src/dmxserial.cpp b/lib-dmxserial/src/dmxserial.cpp index c2a9a959c..f1d2c0a4f 100644 --- a/lib-dmxserial/src/dmxserial.cpp +++ b/lib-dmxserial/src/dmxserial.cpp @@ -2,7 +2,7 @@ * @file dmxserial.cpp * */ -/* Copyright (C) 2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -132,10 +132,8 @@ void DmxSerial::Sync([[maybe_unused]] uint32_t const nPortIndex) { // No actions here } -void DmxSerial::Sync(const bool doForce) { - if (__builtin_expect((!doForce), 1)) { - Update(m_SyncData.data, m_SyncData.nLength); - } +void DmxSerial::Sync() { + Update(m_SyncData.data, m_SyncData.nLength); } void DmxSerial::Print() { diff --git a/lib-dmxserial/src/dmxserialhandleudp.cpp b/lib-dmxserial/src/dmxserialhandleudp.cpp index 5948acdf3..f26f5e279 100644 --- a/lib-dmxserial/src/dmxserialhandleudp.cpp +++ b/lib-dmxserial/src/dmxserialhandleudp.cpp @@ -75,7 +75,7 @@ void DmxSerial::HandleUdp() { if (memcmp(s_UdpBuffer, cmd::REQUEST_FILES, length::REQUEST_FILES) == 0) { for (uint32_t i = 0; i < m_nFilesCount; i++) { const auto nLength = snprintf(s_UdpBuffer, sizeof(s_UdpBuffer) - 1, DMXSERIAL_FILE_PREFIX "%.3d" DMXSERIAL_FILE_SUFFIX "\n", m_aFileIndex[i]); - Network::Get()->SendTo(m_nHandle, s_UdpBuffer, static_cast(nLength), nIPAddressFrom, UDP::PORT); + Network::Get()->SendTo(m_nHandle, s_UdpBuffer, nLength, nIPAddressFrom, UDP::PORT); } return; } @@ -83,7 +83,7 @@ void DmxSerial::HandleUdp() { if ((nBytesReceived >= length::GET_TFTP) && (memcmp(s_UdpBuffer, cmd::GET_TFTP, length::GET_TFTP) == 0)) { if (nBytesReceived == length::GET_TFTP) { const auto nLength = snprintf(s_UdpBuffer, UDP::BUFFER_SIZE - 1, "tftp:%s\n", m_bEnableTFTP ? "On" : "Off"); - Network::Get()->SendTo(m_nHandle, s_UdpBuffer, static_cast(nLength), nIPAddressFrom, UDP::PORT); + Network::Get()->SendTo(m_nHandle, s_UdpBuffer,nLength, nIPAddressFrom, UDP::PORT); return; } @@ -113,7 +113,7 @@ void DmxSerial::HandleUdp() { } else { const auto *pError = strerror(errno); const auto nLength = snprintf(s_UdpBuffer, UDP::BUFFER_SIZE - 1, "%s\n", pError); - Network::Get()->SendTo(m_nHandle, s_UdpBuffer, static_cast(nLength), nIPAddressFrom, UDP::PORT); + Network::Get()->SendTo(m_nHandle, s_UdpBuffer, nLength, nIPAddressFrom, UDP::PORT); } return; } diff --git a/lib-e131/include/e131bridge.h b/lib-e131/include/e131bridge.h old mode 100644 new mode 100755 index 12bd5b6e0..bac902a8f --- a/lib-e131/include/e131bridge.h +++ b/lib-e131/include/e131bridge.h @@ -51,6 +51,10 @@ #include "debug.h" +#ifndef ALIGNED +# define ALIGNED __attribute__ ((aligned (4))) +#endif + namespace e131bridge { #if !defined(LIGHTSET_PORTS) # error LIGHTSET_PORTS is not defined @@ -67,13 +71,6 @@ namespace e131bridge { }; struct State { - bool IsNetworkDataLoss; - bool IsMergeMode; - bool IsSynchronized; - bool IsForcedSynchronized; - bool IsChanged; - bool bDisableMergeTimeout; - bool bDisableSynchronize; uint32_t SynchronizationTime; uint32_t DiscoveryTime; uint16_t DiscoveryPacketLength; @@ -85,6 +82,13 @@ struct State { uint8_t nReceivingDmx; lightset::FailSafe failsafe; e131bridge::Status status; + bool IsNetworkDataLoss; + bool IsMergeMode; + bool IsSynchronized; + bool IsForcedSynchronized; + bool IsChanged; + bool bDisableMergeTimeout; + bool bDisableSynchronize; }; struct Bridge { @@ -92,7 +96,7 @@ struct Bridge { uint16_t nUniverse; lightset::PortDir direction; bool bLocalMerge; - } Port[e131bridge::MAX_PORTS]; + } Port[e131bridge::MAX_PORTS] ALIGNED; }; struct Source { @@ -103,12 +107,13 @@ struct Source { }; struct OutputPort { - Source sourceA; - Source sourceB; + Source sourceA ALIGNED; + Source sourceB ALIGNED; lightset::MergeMode mergeMode; lightset::OutputStyle outputStyle; bool IsMerging; bool IsTransmitting; + bool IsDataPending; }; struct InputPort { @@ -224,19 +229,6 @@ class E131Bridge { m_pE131Sync = pE131Sync; } - const uint8_t *GetCid() const { - return m_Cid; - } - - void SetSourceName(const char *pSourceName) { - assert(pSourceName != nullptr); - strncpy(m_SourceName, pSourceName, e131::SOURCE_NAME_LENGTH - 1); - m_SourceName[e131::SOURCE_NAME_LENGTH - 1] = '\0'; - } - const char *GetSourceName() const { - return m_SourceName; - } - void SetPriority(const uint32_t nPortIndex, uint8_t nPriority) { assert(nPortIndex < e131bridge::MAX_PORTS); if ((nPriority >= e131::priority::LOWEST) && (nPriority <= e131::priority::HIGHEST)) { @@ -266,21 +258,6 @@ class E131Bridge { } m_OutputPort[nPortIndex].outputStyle = outputStyle; - -#if defined (OUTPUT_DMX_SEND) || defined (OUTPUT_DMX_SEND_MULTI) - /** - * FIXME I do not like this hack. It should be handled in dmx.cpp - */ - if (m_Bridge.Port[nPortIndex].direction == lightset::PortDir::OUTPUT - && (outputStyle == lightset::OutputStyle::CONSTANT) - && (m_pLightSet != nullptr)) { - if (m_OutputPort[nPortIndex].IsTransmitting) { - m_OutputPort[nPortIndex].IsTransmitting = false; - m_pLightSet->Stop(nPortIndex); - } - } -#endif - } lightset::OutputStyle GetOutputStyle(const uint32_t nPortIndex) const { @@ -302,6 +279,21 @@ class E131Bridge { m_State.IsNetworkDataLoss = false; // Force timeout } +#if defined (E131_HAVE_DMXIN) || defined (NODE_SHOWFILE) + void SetSourceName(const char *pSourceName) { + assert(pSourceName != nullptr); + strncpy(m_SourceName, pSourceName, e131::SOURCE_NAME_LENGTH - 1); + m_SourceName[e131::SOURCE_NAME_LENGTH - 1] = '\0'; + } + const char *GetSourceName() const { + return m_SourceName; + } + + const uint8_t *GetCid() const { + return m_Cid; + } +#endif + void Start(); void Stop(); @@ -411,12 +403,6 @@ class E131Bridge { uint32_t m_nPreviousPacketMillis { 0 }; uint32_t m_nPreviousLedpanelMillis { 0 }; - TE131DataPacket *m_pE131DataPacket { nullptr }; - TE131DiscoveryPacket *m_pE131DiscoveryPacket { nullptr }; - uint32_t m_DiscoveryIpAddress { 0 }; - uint8_t m_Cid[e131::CID_LENGTH]; - char m_SourceName[e131::SOURCE_NAME_LENGTH]; - e131bridge::State m_State; e131bridge::Bridge m_Bridge; e131bridge::OutputPort m_OutputPort[e131bridge::MAX_PORTS]; @@ -431,6 +417,17 @@ class E131Bridge { // Synchronization handler E131Sync *m_pE131Sync { nullptr }; +#if defined (E131_HAVE_DMXIN) || defined (NODE_SHOWFILE) + char m_SourceName[e131::SOURCE_NAME_LENGTH]; + uint8_t m_Cid[e131::CID_LENGTH]; +#endif + +#if defined (E131_HAVE_DMXIN) + TE131DataPacket m_E131DataPacket; + TE131DiscoveryPacket m_E131DiscoveryPacket; + uint32_t m_DiscoveryIpAddress { 0 }; +#endif + #if defined (DMXCONFIGUDP_H_) # if defined (ARTNET_VERSION) # error diff --git a/lib-e131/include/e131msgconst.h b/lib-e131/include/e131msgconst.h index 3b656c378..c0c4e5e40 100644 --- a/lib-e131/include/e131msgconst.h +++ b/lib-e131/include/e131msgconst.h @@ -2,7 +2,7 @@ * @file e131msgconst.h * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,7 +27,6 @@ #define E131MSGCONST_H_ struct E131MsgConst { - static const char PARAMS[]; static const char START[]; static const char STARTED[]; }; diff --git a/lib-e131/src/node/dmxin/discoverypacket.cpp b/lib-e131/src/node/dmxin/discoverypacket.cpp index ecc78115e..95a6fc27d 100644 --- a/lib-e131/src/node/dmxin/discoverypacket.cpp +++ b/lib-e131/src/node/dmxin/discoverypacket.cpp @@ -2,7 +2,7 @@ * @file e131bridgediscoverypacket * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -36,23 +36,23 @@ void E131Bridge::FillDiscoveryPacket() { m_State.DiscoveryPacketLength = static_cast(DISCOVERY_PACKET_SIZE(m_State.nEnabledInputPorts)); - memset(m_pE131DiscoveryPacket, 0, sizeof(struct TE131DiscoveryPacket)); + memset(&m_E131DiscoveryPacket, 0, sizeof(struct TE131DiscoveryPacket)); // Root Layer (See Section 5) - m_pE131DiscoveryPacket->RootLayer.PreAmbleSize = __builtin_bswap16(0x10); - memcpy(m_pE131DiscoveryPacket->RootLayer.ACNPacketIdentifier, E117Const::ACN_PACKET_IDENTIFIER, e117::PACKET_IDENTIFIER_LENGTH); - m_pE131DiscoveryPacket->RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DISCOVERY_ROOT_LAYER_LENGTH(m_State.nEnabledInputPorts)))); - m_pE131DiscoveryPacket->RootLayer.Vector = __builtin_bswap32(e131::vector::root::EXTENDED); - memcpy(m_pE131DiscoveryPacket->RootLayer.Cid, m_Cid, e131::CID_LENGTH); + m_E131DiscoveryPacket.RootLayer.PreAmbleSize = __builtin_bswap16(0x10); + memcpy(m_E131DiscoveryPacket.RootLayer.ACNPacketIdentifier, E117Const::ACN_PACKET_IDENTIFIER, e117::PACKET_IDENTIFIER_LENGTH); + m_E131DiscoveryPacket.RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DISCOVERY_ROOT_LAYER_LENGTH(m_State.nEnabledInputPorts)))); + m_E131DiscoveryPacket.RootLayer.Vector = __builtin_bswap32(e131::vector::root::EXTENDED); + memcpy(m_E131DiscoveryPacket.RootLayer.Cid, m_Cid, e131::CID_LENGTH); // E1.31 Framing Layer (See Section 6) - m_pE131DiscoveryPacket->FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DISCOVERY_FRAME_LAYER_LENGTH(m_State.nEnabledInputPorts)))); - m_pE131DiscoveryPacket->FrameLayer.Vector = __builtin_bswap32(e131::vector::extended::DISCOVERY); - memcpy(m_pE131DiscoveryPacket->FrameLayer.SourceName, m_SourceName, e131::SOURCE_NAME_LENGTH); + m_E131DiscoveryPacket.FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DISCOVERY_FRAME_LAYER_LENGTH(m_State.nEnabledInputPorts)))); + m_E131DiscoveryPacket.FrameLayer.Vector = __builtin_bswap32(e131::vector::extended::DISCOVERY); + memcpy(m_E131DiscoveryPacket.FrameLayer.SourceName, m_SourceName, e131::SOURCE_NAME_LENGTH); // Universe Discovery Layer (See Section 8) - m_pE131DiscoveryPacket->UniverseDiscoveryLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | DISCOVERY_LAYER_LENGTH(m_State.nEnabledInputPorts))); - m_pE131DiscoveryPacket->UniverseDiscoveryLayer.Vector = __builtin_bswap32(e131::vector::universe::DISCOVERY_UNIVERSE_LIST); + m_E131DiscoveryPacket.UniverseDiscoveryLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | DISCOVERY_LAYER_LENGTH(m_State.nEnabledInputPorts))); + m_E131DiscoveryPacket.UniverseDiscoveryLayer.Vector = __builtin_bswap32(e131::vector::universe::DISCOVERY_UNIVERSE_LIST); } void E131Bridge::SendDiscoveryPacket() { @@ -67,11 +67,11 @@ void E131Bridge::SendDiscoveryPacket() { for (uint32_t i = 0; i < e131bridge::MAX_PORTS; i++) { uint16_t nUniverse; if (GetUniverse(i, nUniverse, lightset::PortDir::INPUT)) { - m_pE131DiscoveryPacket->UniverseDiscoveryLayer.ListOfUniverses[nListOfUniverses++] = __builtin_bswap16(nUniverse); + m_E131DiscoveryPacket.UniverseDiscoveryLayer.ListOfUniverses[nListOfUniverses++] = __builtin_bswap16(nUniverse); } } - Network::Get()->SendTo(m_nHandle, m_pE131DiscoveryPacket, m_State.DiscoveryPacketLength, m_DiscoveryIpAddress, e131::UDP_PORT); + Network::Get()->SendTo(m_nHandle, &m_E131DiscoveryPacket, m_State.DiscoveryPacketLength, m_DiscoveryIpAddress, e131::UDP_PORT); } } } diff --git a/lib-e131/src/node/dmxin/handledmxin.cpp b/lib-e131/src/node/dmxin/handledmxin.cpp index 972b93a4d..1c304ce54 100644 --- a/lib-e131/src/node/dmxin/handledmxin.cpp +++ b/lib-e131/src/node/dmxin/handledmxin.cpp @@ -2,7 +2,7 @@ * @file e131bridgehandledmxin.cpp * */ -/* Copyright (C) 2019-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,21 +43,21 @@ void E131Bridge::FillDataPacket() { // Root Layer (See Section 5) - m_pE131DataPacket->RootLayer.PreAmbleSize = __builtin_bswap16(0x0010); - m_pE131DataPacket->RootLayer.PostAmbleSize = __builtin_bswap16(0x0000); - memcpy(m_pE131DataPacket->RootLayer.ACNPacketIdentifier, E117Const::ACN_PACKET_IDENTIFIER, e117::PACKET_IDENTIFIER_LENGTH); - m_pE131DataPacket->RootLayer.Vector = __builtin_bswap32(e131::vector::root::DATA); - memcpy(m_pE131DataPacket->RootLayer.Cid, m_Cid, e131::CID_LENGTH); + m_E131DataPacket.RootLayer.PreAmbleSize = __builtin_bswap16(0x0010); + m_E131DataPacket.RootLayer.PostAmbleSize = __builtin_bswap16(0x0000); + memcpy(m_E131DataPacket.RootLayer.ACNPacketIdentifier, E117Const::ACN_PACKET_IDENTIFIER, e117::PACKET_IDENTIFIER_LENGTH); + m_E131DataPacket.RootLayer.Vector = __builtin_bswap32(e131::vector::root::DATA); + memcpy(m_E131DataPacket.RootLayer.Cid, m_Cid, e131::CID_LENGTH); // E1.31 Framing Layer (See Section 6) - m_pE131DataPacket->FrameLayer.Vector = __builtin_bswap32(e131::vector::data::PACKET); - memcpy(m_pE131DataPacket->FrameLayer.SourceName, m_SourceName, e131::SOURCE_NAME_LENGTH); - m_pE131DataPacket->FrameLayer.SynchronizationAddress = __builtin_bswap16(0); // Currently not supported - m_pE131DataPacket->FrameLayer.Options = 0; + m_E131DataPacket.FrameLayer.Vector = __builtin_bswap32(e131::vector::data::PACKET); + memcpy(m_E131DataPacket.FrameLayer.SourceName, m_SourceName, e131::SOURCE_NAME_LENGTH); + m_E131DataPacket.FrameLayer.SynchronizationAddress = __builtin_bswap16(0); // Currently not supported + m_E131DataPacket.FrameLayer.Options = 0; // Data Layer - m_pE131DataPacket->DMPLayer.Vector = e131::vector::dmp::SET_PROPERTY; - m_pE131DataPacket->DMPLayer.Type = 0xa1; - m_pE131DataPacket->DMPLayer.FirstAddressProperty = __builtin_bswap16(0x0000); - m_pE131DataPacket->DMPLayer.AddressIncrement = __builtin_bswap16(0x0001); + m_E131DataPacket.DMPLayer.Vector = e131::vector::dmp::SET_PROPERTY; + m_E131DataPacket.DMPLayer.Type = 0xa1; + m_E131DataPacket.DMPLayer.FirstAddressProperty = __builtin_bswap16(0x0000); + m_E131DataPacket.DMPLayer.AddressIncrement = __builtin_bswap16(0x0001); } static uint32_t s_ReceivingMask = 0; @@ -71,21 +71,21 @@ void E131Bridge::HandleDmxIn() { if (pDmxData != nullptr) { // Root Layer (See Section 5) auto nLength = (1U + pDmxData->Statistics.nSlotsInPacket); // Add 1 for SC - m_pE131DataPacket->RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_ROOT_LAYER_LENGTH(nLength)))); + m_E131DataPacket.RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_ROOT_LAYER_LENGTH(nLength)))); // E1.31 Framing Layer (See Section 6) - m_pE131DataPacket->FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_FRAME_LAYER_LENGTH(nLength)))); - m_pE131DataPacket->FrameLayer.Priority = m_InputPort[nPortIndex].nPriority; - m_pE131DataPacket->FrameLayer.SequenceNumber = m_InputPort[nPortIndex].nSequenceNumber++; - m_pE131DataPacket->FrameLayer.Universe = __builtin_bswap16(m_Bridge.Port[nPortIndex].nUniverse); + m_E131DataPacket.FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_FRAME_LAYER_LENGTH(nLength)))); + m_E131DataPacket.FrameLayer.Priority = m_InputPort[nPortIndex].nPriority; + m_E131DataPacket.FrameLayer.SequenceNumber = m_InputPort[nPortIndex].nSequenceNumber++; + m_E131DataPacket.FrameLayer.Universe = __builtin_bswap16(m_Bridge.Port[nPortIndex].nUniverse); // Data Layer - m_pE131DataPacket->DMPLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_LAYER_LENGTH(nLength)))); - memcpy(m_pE131DataPacket->DMPLayer.PropertyValues, pDmxData, nLength); - m_pE131DataPacket->DMPLayer.PropertyValueCount = __builtin_bswap16(static_cast(nLength)); + m_E131DataPacket.DMPLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_LAYER_LENGTH(nLength)))); + memcpy(m_E131DataPacket.DMPLayer.PropertyValues, pDmxData, nLength); + m_E131DataPacket.DMPLayer.PropertyValueCount = __builtin_bswap16(static_cast(nLength)); - Network::Get()->SendTo(m_nHandle, m_pE131DataPacket, static_cast(DATA_PACKET_SIZE(nLength)), m_InputPort[nPortIndex].nMulticastIp, e131::UDP_PORT); + Network::Get()->SendTo(m_nHandle, &m_E131DataPacket, DATA_PACKET_SIZE(nLength), m_InputPort[nPortIndex].nMulticastIp, e131::UDP_PORT); if (m_Bridge.Port[nPortIndex].bLocalMerge) { - m_pReceiveBuffer = reinterpret_cast(m_pE131DataPacket); + m_pReceiveBuffer = reinterpret_cast(&m_E131DataPacket); m_nIpAddressFrom = Network::Get()->GetIp(); HandleDmx(); } @@ -123,21 +123,21 @@ void E131Bridge::HandleDmxIn() { const auto *const pDmxData = reinterpret_cast(Dmx::Get()->GetDmxCurrentData(nPortIndex)); // Root Layer (See Section 5) auto nLength = (1U + pDmxData->Statistics.nSlotsInPacket); // Add 1 for SC - m_pE131DataPacket->RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_ROOT_LAYER_LENGTH(nLength)))); + m_E131DataPacket.RootLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_ROOT_LAYER_LENGTH(nLength)))); // E1.31 Framing Layer (See Section 6) - m_pE131DataPacket->FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_FRAME_LAYER_LENGTH(nLength)))); - m_pE131DataPacket->FrameLayer.Priority = m_InputPort[nPortIndex].nPriority; - m_pE131DataPacket->FrameLayer.SequenceNumber = m_InputPort[nPortIndex].nSequenceNumber++; - m_pE131DataPacket->FrameLayer.Universe = __builtin_bswap16(m_Bridge.Port[nPortIndex].nUniverse); + m_E131DataPacket.FrameLayer.FLagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_FRAME_LAYER_LENGTH(nLength)))); + m_E131DataPacket.FrameLayer.Priority = m_InputPort[nPortIndex].nPriority; + m_E131DataPacket.FrameLayer.SequenceNumber = m_InputPort[nPortIndex].nSequenceNumber++; + m_E131DataPacket.FrameLayer.Universe = __builtin_bswap16(m_Bridge.Port[nPortIndex].nUniverse); // Data Layer - m_pE131DataPacket->DMPLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_LAYER_LENGTH(nLength)))); - memcpy(m_pE131DataPacket->DMPLayer.PropertyValues, pDmxData, nLength); - m_pE131DataPacket->DMPLayer.PropertyValueCount = __builtin_bswap16(static_cast(nLength)); + m_E131DataPacket.DMPLayer.FlagsLength = __builtin_bswap16(static_cast((0x07 << 12) | (DATA_LAYER_LENGTH(nLength)))); + memcpy(m_E131DataPacket.DMPLayer.PropertyValues, pDmxData, nLength); + m_E131DataPacket.DMPLayer.PropertyValueCount = __builtin_bswap16(static_cast(nLength)); - Network::Get()->SendTo(m_nHandle, m_pE131DataPacket, static_cast(DATA_PACKET_SIZE(nLength)), m_InputPort[nPortIndex].nMulticastIp, e131::UDP_PORT); + Network::Get()->SendTo(m_nHandle, &m_E131DataPacket, DATA_PACKET_SIZE(nLength), m_InputPort[nPortIndex].nMulticastIp, e131::UDP_PORT); if (m_Bridge.Port[nPortIndex].bLocalMerge) { - m_pReceiveBuffer = reinterpret_cast(&m_pE131DataPacket); + m_pReceiveBuffer = reinterpret_cast(&m_E131DataPacket); m_nIpAddressFrom = Network::Get()->GetIp(); HandleDmx(); } diff --git a/lib-e131/src/node/e131bridge.cpp b/lib-e131/src/node/e131bridge.cpp index bb1e06d3f..01e97c194 100755 --- a/lib-e131/src/node/e131bridge.cpp +++ b/lib-e131/src/node/e131bridge.cpp @@ -23,6 +23,12 @@ * THE SOFTWARE. */ +#if !defined(__clang__) +# pragma GCC push_options +# pragma GCC optimize ("O2") +# pragma GCC optimize ("no-tree-loop-distribute-patterns") +#endif + #include #include #include @@ -71,7 +77,7 @@ E131Bridge::E131Bridge() { m_InputPort[i].nPriority = 100; } -#if defined (E131_HAVE_DMXIN) +#if defined (E131_HAVE_DMXIN) || defined (NODE_SHOWFILE) char aSourceName[e131::SOURCE_NAME_LENGTH]; uint8_t nLength; snprintf(aSourceName, e131::SOURCE_NAME_LENGTH, "%.48s %s", Network::Get()->GetHostName(), Hardware::Get()->GetBoardName(nLength)); @@ -94,18 +100,10 @@ E131Bridge::~E131Bridge() { void E131Bridge::Start() { #if defined (E131_HAVE_DMXIN) - if (m_pE131DataPacket == nullptr) { - const auto nIpMulticast = network::convert_to_uint(239, 255, 0, 0); - m_DiscoveryIpAddress = nIpMulticast | ((e131::universe::DISCOVERY & static_cast(0xFF)) << 24) | ((e131::universe::DISCOVERY & 0xFF00) << 8); - // TE131DataPacket - m_pE131DataPacket = new TE131DataPacket; - assert(m_pE131DataPacket != nullptr); - FillDataPacket(); - // TE131DiscoveryPacket - m_pE131DiscoveryPacket = new TE131DiscoveryPacket; - assert(m_pE131DiscoveryPacket != nullptr); - FillDiscoveryPacket(); - } + const auto nIpMulticast = network::convert_to_uint(239, 255, 0, 0); + m_DiscoveryIpAddress = nIpMulticast | ((e131::universe::DISCOVERY & static_cast(0xFF)) << 24) | ((e131::universe::DISCOVERY & 0xFF00) << 8); + FillDataPacket(); + FillDiscoveryPacket(); for (uint32_t nPortIndex = 0; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { if (m_Bridge.Port[nPortIndex].direction == lightset::PortDir::INPUT) { @@ -580,6 +578,7 @@ void E131Bridge::HandleDmx() { } } else { lightset::Data::Set(m_pLightSet, nPortIndex); + m_OutputPort[nPortIndex].IsDataPending = true; } m_State.nReceivingDmx |= (1U << static_cast(lightset::PortDir::OUTPUT)); diff --git a/lib-e131/src/node/e131bridgehandlesynchronization.cpp b/lib-e131/src/node/e131bridgehandlesynchronization.cpp index c38b404de..5692e2808 100755 --- a/lib-e131/src/node/e131bridgehandlesynchronization.cpp +++ b/lib-e131/src/node/e131bridgehandlesynchronization.cpp @@ -2,7 +2,7 @@ * @file e131bridgehandlesynchronization.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -52,17 +52,18 @@ void E131Bridge::HandleSynchronization() { m_State.SynchronizationTime = m_nCurrentPacketMillis; for (uint32_t nPortIndex = 0; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { - if (m_Bridge.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) { + if (m_OutputPort[nPortIndex].IsDataPending) { m_pLightSet->Sync(nPortIndex); } } m_pLightSet->Sync(); - for (uint32_t nPortIndex = 0; nPortIndex < e131bridge::MAX_PORTS; nPortIndex++) { - if (m_Bridge.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) { - if (!m_OutputPort[nPortIndex].IsTransmitting) { - m_OutputPort[nPortIndex].IsTransmitting = true; + for (auto &outputPort : m_OutputPort) { + if (outputPort.IsDataPending) { + outputPort.IsDataPending = false; + if (!outputPort.IsTransmitting) { + outputPort.IsTransmitting = true; m_State.IsChanged = true; } } diff --git a/lib-e131/src/node/e131msgconst.cpp b/lib-e131/src/node/e131msgconst.cpp index 9044fdc50..82af7dd64 100644 --- a/lib-e131/src/node/e131msgconst.cpp +++ b/lib-e131/src/node/e131msgconst.cpp @@ -2,7 +2,7 @@ * @file e131mgsconst.cpp * */ -/* Copyright (C) 2019-2020 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,6 +25,5 @@ #include "e131msgconst.h" -const char E131MsgConst::PARAMS[] = "Configuring sACN E1.31"; const char E131MsgConst::START[] = "Starting sACN E1.31"; const char E131MsgConst::STARTED[] = "sACN E1.31 started"; diff --git a/lib-flashcode/src/gd32/flashcode.cpp b/lib-flashcode/src/gd32/flashcode.cpp index 7d9964ca9..f423d0458 100644 --- a/lib-flashcode/src/gd32/flashcode.cpp +++ b/lib-flashcode/src/gd32/flashcode.cpp @@ -41,7 +41,7 @@ FlashCode::FlashCode() { m_IsDetected = true; - printf("FMC: Detected %s with total %u bytes [%u kB]\n", GetName(), static_cast(GetSize()), static_cast(GetSize() / 1024U)); + printf("FMC: %s %u [%u]\n", GetName(), static_cast(GetSize()), static_cast(GetSize() / 1024U)); DEBUG_EXIT } diff --git a/lib-flashcodeinstall/include/flashcodeinstall.h b/lib-flashcodeinstall/include/flashcodeinstall.h index f1839e4aa..43bacdd19 100644 --- a/lib-flashcodeinstall/include/flashcodeinstall.h +++ b/lib-flashcodeinstall/include/flashcodeinstall.h @@ -35,19 +35,19 @@ #elif defined (GD32) # if defined (BOARD_GD32F107RC) # define OFFSET_UIMAGE 0x007000 // 28K -# define FIRMWARE_MAX_SIZE (78 * 1024) // 78K +# define FIRMWARE_MAX_SIZE (76 * 1024) // 76K # elif defined (BOARD_GD32F207RG) # define OFFSET_UIMAGE 0x008000 // 32K -# define FIRMWARE_MAX_SIZE (236 * 1024) // 236K +# define FIRMWARE_MAX_SIZE (234 * 1024) // 234K # elif defined (BOARD_GD32F207VC_2) # define OFFSET_UIMAGE 0x008000 // 32K -# define FIRMWARE_MAX_SIZE (110 * 1024) // 110K +# define FIRMWARE_MAX_SIZE (106 * 1024) // 106K # elif defined (BOARD_GD32F207VC_4) # define OFFSET_UIMAGE 0x008000 // 32K -# define FIRMWARE_MAX_SIZE (110 * 1024) // 110K +# define FIRMWARE_MAX_SIZE (106 * 1024) // 106K # elif defined (BOARD_GD32F207C_EVAL) # define OFFSET_UIMAGE 0x008000 // 32K -# define FIRMWARE_MAX_SIZE (110 * 1024) // 110K +# define FIRMWARE_MAX_SIZE (106 * 1024) // 106K # elif defined (BOARD_GD32F407RE) # define OFFSET_UIMAGE 0x008000 // 32K # define FIRMWARE_MAX_SIZE (116 * 1024) // 116K diff --git a/lib-h3/include/board/h3_opi_zero.h b/lib-h3/include/board/h3_opi_zero.h index dcfaf5484..a50569a8d 100644 --- a/lib-h3/include/board/h3_opi_zero.h +++ b/lib-h3/include/board/h3_opi_zero.h @@ -68,5 +68,6 @@ typedef enum H3_BOARD_OPI_ZERO { #define FT8XX_LCD_DC_GPIO GPIO_EXT_26 #define FT8XX_LCD_CS_GPIO GPIO_EXT_22 +#define FT8XX_LCD_INT_GPIO GPIO_EXT_12 #endif /* H3_OPI_ZERO_H_ */ diff --git a/lib-l6470dmx/include/sparkfundmx.h b/lib-l6470dmx/include/sparkfundmx.h index 54da8ab1d..d8afe899e 100644 --- a/lib-l6470dmx/include/sparkfundmx.h +++ b/lib-l6470dmx/include/sparkfundmx.h @@ -57,7 +57,7 @@ class SparkFunDmx: public LightSet { void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; void Sync(const uint32_t nPortIndex) override; - void Sync(const bool doForce = false) override; + void Sync() override; void Print() override; diff --git a/lib-l6470dmx/src/sparkfundmx.cpp b/lib-l6470dmx/src/sparkfundmx.cpp index 8357e708f..7179a70af 100644 --- a/lib-l6470dmx/src/sparkfundmx.cpp +++ b/lib-l6470dmx/src/sparkfundmx.cpp @@ -372,7 +372,7 @@ void SparkFunDmx::Sync([[maybe_unused]] uint32_t const nPortIndex) { //TODO Implement Sync } -void SparkFunDmx::Sync([[maybe_unused]] const bool doForce) { +void SparkFunDmx::Sync() { //TODO Implement Sync } diff --git a/lib-ltc/include/ntpserver.h b/lib-ltc/include/ntpserver.h index 40360d7ce..fe0a0e3cb 100755 --- a/lib-ltc/include/ntpserver.h +++ b/lib-ltc/include/ntpserver.h @@ -30,7 +30,7 @@ #include #include "ltc.h" -#include "ntp.h" +#include "net/protocol/ntp.h" #include "network.h" #include "debug.h" diff --git a/lib-ltc/src/arm/gd32/ltcsender.cpp b/lib-ltc/src/arm/gd32/ltcsender.cpp index c91a8686a..82b1f4d42 100644 --- a/lib-ltc/src/arm/gd32/ltcsender.cpp +++ b/lib-ltc/src/arm/gd32/ltcsender.cpp @@ -69,7 +69,6 @@ static void gpio_config(){ #if !defined (GD32F4XX) gpio_init(GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PINx); #else - gpio_af_set(LTC_OUTPUT_GPIOx, GPIO_AF_0, LTC_OUTPUT_GPIO_PINx); gpio_mode_set(LTC_OUTPUT_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, LTC_OUTPUT_GPIO_PINx); gpio_output_options_set(LTC_OUTPUT_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LTC_OUTPUT_GPIO_PINx); #endif diff --git a/lib-ltc/src/arm/gd32/platform_ltc.cpp b/lib-ltc/src/arm/gd32/platform_ltc.cpp index 8a4bc3f3c..489879288 100644 --- a/lib-ltc/src/arm/gd32/platform_ltc.cpp +++ b/lib-ltc/src/arm/gd32/platform_ltc.cpp @@ -126,7 +126,6 @@ void timer3_config() { #if !defined (GD32F4XX) gpio_init(DEBUG_TIMER3_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, DEBUG_TIMER3_GPIO_PINx); #else - gpio_af_set(DEBUG_TIMER3_GPIOx, GPIO_AF_0, DEBUG_TIMER3_GPIO_PINx); gpio_mode_set(DEBUG_TIMER3_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, DEBUG_TIMER3_GPIO_PINx); gpio_output_options_set(DEBUG_TIMER3_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, DEBUG_TIMER3_GPIO_PINx); #endif @@ -161,7 +160,6 @@ void timer10_config() { #if !defined (GD32F4XX) gpio_init(DEBUG_TIMER10_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, DEBUG_TIMER10_GPIO_PINx); #else - gpio_af_set(DEBUG_TIMER10_GPIOx, GPIO_AF_0, DEBUG_TIMER10_GPIO_PINx); gpio_mode_set(DEBUG_TIMER10_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, DEBUG_TIMER10_GPIO_PINx); gpio_output_options_set(DEBUG_TIMER10_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, DEBUG_TIMER10_GPIO_PINx); #endif @@ -199,7 +197,6 @@ void timer11_config() { #if !defined (GD32F4XX) gpio_init(DEBUG_TIMER11_GPIOx, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, DEBUG_TIMER11_GPIO_PINx); #else - gpio_af_set(DEBUG_TIMER11_GPIOx, GPIO_AF_0, DEBUG_TIMER11_GPIO_PINx); gpio_mode_set(DEBUG_TIMER11_GPIOx, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLDOWN, DEBUG_TIMER11_GPIO_PINx); gpio_output_options_set(DEBUG_TIMER11_GPIOx, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, DEBUG_TIMER11_GPIO_PINx); #endif diff --git a/lib-ltc/src/displayrgb/ltcdisplayrgb.cpp b/lib-ltc/src/displayrgb/ltcdisplayrgb.cpp index e8bc51b5b..6f52c0c48 100755 --- a/lib-ltc/src/displayrgb/ltcdisplayrgb.cpp +++ b/lib-ltc/src/displayrgb/ltcdisplayrgb.cpp @@ -372,8 +372,8 @@ void LtcDisplayRgb::Print() { printf("Display RGB panel\n"); } else { printf("Display WS28xx\n"); - printf(" Type : %s [%d]\n", PixelType::GetType(m_tLedType), static_cast(m_tLedType)); - printf(" Mapping : %s [%d]\n", PixelType::GetMap(m_tMapping), static_cast(m_tMapping)); + printf(" Type : %s [%d]\n", pixel::pixel_get_type(m_tLedType), static_cast(m_tLedType)); + printf(" Mapping : %s [%d]\n", pixel::pixel_get_map(m_tMapping), static_cast(m_tMapping)); } printf(" Master : %d\n", m_nMaster); printf(" RGB : Character 0x%.6X, Colon 0x%.6X, Message 0x%.6X\n", m_aColour[static_cast(ColourIndex::TIME)], m_aColour[static_cast(ColourIndex::COLON)], m_aColour[static_cast(ColourIndex::MESSAGE)]); diff --git a/lib-ltc/src/ltcdisplayparams.cpp b/lib-ltc/src/ltcdisplayparams.cpp index f2234285a..8aaa5078a 100755 --- a/lib-ltc/src/ltcdisplayparams.cpp +++ b/lib-ltc/src/ltcdisplayparams.cpp @@ -202,7 +202,7 @@ void LtcDisplayParams::callbackFunction(const char *pLine) { if (Sscan::Char(pLine, DevicesParamsConst::TYPE, aBuffer, nLength) == Sscan::OK) { aBuffer[nLength] = '\0'; - const auto type = PixelType::GetType(aBuffer); + const auto type = pixel::pixel_get_type(aBuffer); if (type != pixel::Type::UNDEFINED) { m_Params.nWS28xxType = static_cast(type); @@ -218,7 +218,7 @@ void LtcDisplayParams::callbackFunction(const char *pLine) { if (Sscan::Char(pLine, DevicesParamsConst::MAP, aBuffer, nLength) == Sscan::OK) { aBuffer[nLength] = '\0'; pixel::Map tMapping; - if ((tMapping = PixelType::GetMap(aBuffer)) != pixel::Map::UNDEFINED) { + if ((tMapping = pixel::pixel_get_map(aBuffer)) != pixel::Map::UNDEFINED) { m_Params.nWS28xxRgbMapping = static_cast(tMapping); m_Params.nSetList |= ltcdisplayparams::Mask::WS28XX_RGB_MAPPING; } @@ -297,13 +297,13 @@ void LtcDisplayParams::Builder(const struct ltcdisplayparams::Params *ptLtcDispl #if !defined (CONFIG_LTC_DISABLE_WS28XX) builder.AddComment("WS28xx (specific)"); builder.Add(LtcDisplayParamsConst::WS28XX_TYPE, m_Params.nWS28xxDisplayType == static_cast(ltcdisplayrgb::WS28xxType::SEGMENT) ? "7segment" : "matrix" , isMaskSet(ltcdisplayparams::Mask::WS28XX_DISPLAY_TYPE)); - builder.Add(DevicesParamsConst::TYPE, PixelType::GetType(static_cast(m_Params.nWS28xxType)), isMaskSet(ltcdisplayparams::Mask::WS28XX_TYPE)); + builder.Add(DevicesParamsConst::TYPE, pixel::pixel_get_type(static_cast(m_Params.nWS28xxType)), isMaskSet(ltcdisplayparams::Mask::WS28XX_TYPE)); builder.AddComment("Overwrite datasheet"); if (!isMaskSet(ltcdisplayparams::Mask::WS28XX_RGB_MAPPING)) { - m_Params.nWS28xxRgbMapping = static_cast(PixelType::GetMap(static_cast(m_Params.nWS28xxType))); + m_Params.nWS28xxRgbMapping = static_cast(pixel::pixel_get_map(static_cast(m_Params.nWS28xxType))); } - builder.Add(DevicesParamsConst::MAP, PixelType::GetMap(static_cast(m_Params.nWS28xxRgbMapping)), isMaskSet(ltcdisplayparams::Mask::WS28XX_RGB_MAPPING)); + builder.Add(DevicesParamsConst::MAP, pixel::pixel_get_map(static_cast(m_Params.nWS28xxRgbMapping)), isMaskSet(ltcdisplayparams::Mask::WS28XX_RGB_MAPPING)); #endif #if !defined (CONFIG_LTC_DISABLE_RGB_PANEL) @@ -357,11 +357,11 @@ void LtcDisplayParams::Dump() { #if !defined (CONFIG_LTC_DISABLE_WS28XX) if (isMaskSet(ltcdisplayparams::Mask::WS28XX_TYPE)) { - printf(" %s=%s [%d]\n", DevicesParamsConst::TYPE, PixelType::GetType(static_cast(m_Params.nWS28xxType)), static_cast(m_Params.nWS28xxType)); + printf(" %s=%s [%d]\n", DevicesParamsConst::TYPE, pixel::pixel_get_type(static_cast(m_Params.nWS28xxType)), static_cast(m_Params.nWS28xxType)); } if (isMaskSet(ltcdisplayparams::Mask::WS28XX_RGB_MAPPING)) { - printf(" %s=%s [%d]\n", DevicesParamsConst::MAP, PixelType::GetMap(static_cast(m_Params.nWS28xxRgbMapping)), static_cast(m_Params.nWS28xxRgbMapping)); + printf(" %s=%s [%d]\n", DevicesParamsConst::MAP, pixel::pixel_get_map(static_cast(m_Params.nWS28xxRgbMapping)), static_cast(m_Params.nWS28xxRgbMapping)); } #endif diff --git a/lib-ltc/src/ntpserver.cpp b/lib-ltc/src/ntpserver.cpp index 59fc14cf5..c53933a06 100755 --- a/lib-ltc/src/ntpserver.cpp +++ b/lib-ltc/src/ntpserver.cpp @@ -39,7 +39,7 @@ #include #include "ntpserver.h" -#include "ntp.h" +#include "net/protocol/ntp.h" #include "network.h" diff --git a/lib-midi/include/applemidi.h b/lib-midi/include/applemidi.h index 4efe7fa71..d91906d27 100644 --- a/lib-midi/include/applemidi.h +++ b/lib-midi/include/applemidi.h @@ -36,7 +36,7 @@ #include #include "midi.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "hardware.h" #include "network.h" diff --git a/lib-osc/src/oscsimplesend.cpp b/lib-osc/src/oscsimplesend.cpp index e56e088bc..1b20a4e35 100644 --- a/lib-osc/src/oscsimplesend.cpp +++ b/lib-osc/src/oscsimplesend.cpp @@ -122,5 +122,5 @@ void OscSimpleSend::UpdateMessage(const char *pPath, uint32_t nPathLength, char void OscSimpleSend::Send(uint32_t nMessageLength, int32_t nHandle, uint32_t nIpAddress, uint16_t nPort) { debug_dump(s_Message, nMessageLength); - Network::Get()->SendTo(nHandle, s_Message, static_cast(nMessageLength), nIpAddress, nPort); + Network::Get()->SendTo(nHandle, s_Message, nMessageLength, nIpAddress, nPort); } diff --git a/lib-pca9685dmx/include/pca9685dmxled.h b/lib-pca9685dmx/include/pca9685dmxled.h index 2b4e55610..62d8eb6d0 100644 --- a/lib-pca9685dmx/include/pca9685dmxled.h +++ b/lib-pca9685dmx/include/pca9685dmxled.h @@ -44,7 +44,7 @@ class PCA9685DmxLed final: public LightSet { void SetData(const uint32_t nPortIndex, const uint8_t *pDmxData, uint32_t nLength, const bool doUpdate = true) override; void Sync([[maybe_unused]] const uint32_t nPortIndex) override {}; - void Sync([[maybe_unused]] const bool doForce = false) override {}; + void Sync() override {}; bool SetDmxStartAddress(const uint16_t nDmxStartAddress) override { assert((nDmxStartAddress != 0) && (nDmxStartAddress <= lightset::dmx::UNIVERSE_SIZE)); diff --git a/lib-pca9685dmx/include/pca9685dmxservo.h b/lib-pca9685dmx/include/pca9685dmxservo.h index d0272eb72..28b3dfb76 100644 --- a/lib-pca9685dmx/include/pca9685dmxservo.h +++ b/lib-pca9685dmx/include/pca9685dmxservo.h @@ -44,7 +44,7 @@ class PCA9685DmxServo final: public LightSet { void SetData(const uint32_t nPortIndex, const uint8_t *pDmxData, uint32_t nLength, const bool doUpdate = true) override; void Sync([[maybe_unused]] const uint32_t nPortIndex) override {}; - void Sync([[maybe_unused]] const bool doForce = false) override {}; + void Sync() override {}; bool SetDmxStartAddress(const uint16_t nDmxStartAddress) override { assert((nDmxStartAddress != 0) && (nDmxStartAddress <= lightset::dmx::UNIVERSE_SIZE)); diff --git a/lib-rdm/Rules.mk b/lib-rdm/Rules.mk index 61183c445..b87e2d934 100644 --- a/lib-rdm/Rules.mk +++ b/lib-rdm/Rules.mk @@ -31,7 +31,7 @@ else ifneq (, $(shell test -d '../lib-dmxreceiver' && echo -n yes)) EXTRA_INCLUDES+=../lib-dmxreceiver/include EXTRA_SRCDIR+=src/responder - endif + endif DEFINES+=CONFIG_RDM_ENABLE_SUBDEVICES CONFIG_RDM_SUBDEVICES_USE_I2C CONFIG_RDM_SUBDEVICES_USE_SPI DEFINES+=CONFIG_RDM_ENABLE_MANUFACTURER_PIDS CONFIG_RDM_MANUFACTURER_PIDS_SET DEFINES+=RDM_RESPONDER diff --git a/lib-rdm/include/rdmdevice.h b/lib-rdm/include/rdmdevice.h index 3b4c4e37a..e09067787 100644 --- a/lib-rdm/include/rdmdevice.h +++ b/lib-rdm/include/rdmdevice.h @@ -70,10 +70,33 @@ class RDMDevice { } const uint8_t *GetUID() const { +#if defined (NO_EMAC) || !defined(CONFIG_RDMDEVICE_UUID_IP) +#else + const auto nIp = Network::Get()->GetIp(); +# if !defined(CONFIG_RDMDEVICE_REVERSE_UID) + m_aUID[5] = static_cast(nIp >> 24); + m_aUID[4] = (nIp >> 16) & 0xFF; + m_aUID[3] = (nIp >> 8) & 0xFF; + m_aUID[2] = nIp & 0xFF; +# else + m_aUID[2] = static_cast(nIp >> 24); + m_aUID[3] = (nIp >> 16) & 0xFF; + m_aUID[4] = (nIp >> 8) & 0xFF; + m_aUID[5] = nIp & 0xFF; +# endif +#endif return m_aUID; } const uint8_t *GetSN() const { +#if defined (NO_EMAC) || !defined(CONFIG_RDMDEVICE_UUID_IP) +#else + GetUID(); + m_aSN[0] = m_aUID[5]; + m_aSN[1] = m_aUID[4]; + m_aSN[2] = m_aUID[3]; + m_aSN[3] = m_aUID[2]; +#endif return m_aSN; } diff --git a/lib-rdm/include/rdmdiscovery.h b/lib-rdm/include/rdmdiscovery.h index f01bda277..beac8fa62 100755 --- a/lib-rdm/include/rdmdiscovery.h +++ b/lib-rdm/include/rdmdiscovery.h @@ -109,7 +109,7 @@ class RDMDiscovery { private: RDMMessage m_Message; - uint8_t *m_pResponse; + uint8_t *m_pResponse { nullptr }; uint8_t m_Uid[RDM_UID_SIZE]; uint32_t m_nPortIndex { 0 }; RDMTod *m_pRDMTod { nullptr }; diff --git a/lib-rdm/src/controller/rdmdiscovery.cpp b/lib-rdm/src/controller/rdmdiscovery.cpp index 8a9c61b02..e1a3a4660 100755 --- a/lib-rdm/src/controller/rdmdiscovery.cpp +++ b/lib-rdm/src/controller/rdmdiscovery.cpp @@ -256,7 +256,7 @@ void RDMDiscovery::NewState(const rdmdiscovery::State state, const bool doStateL void RDMDiscovery::Process() { switch (m_State) { - case rdmdiscovery::State::LATE_RESPONSE: //TODO LATE_RESPONSE + case rdmdiscovery::State::LATE_RESPONSE: ///< LATE_RESPONSE m_Message.Receive(m_nPortIndex); if ((Hardware::Get()->Micros() - m_LateResponse.nMicros) > rdmdiscovery::LATE_RESPONSE_TIME_OUT) { @@ -265,7 +265,7 @@ void RDMDiscovery::Process() { return; break; - case rdmdiscovery::State::UNMUTE: //TODO UNMUTE + case rdmdiscovery::State::UNMUTE: ///< UNMUTE if (m_UnMute.nCounter == 0) { m_UnMute.nCounter = rdmdiscovery::UNMUTE_COUNTER; m_UnMute.bCommandRunning = false; @@ -302,7 +302,7 @@ void RDMDiscovery::Process() { return; break; - case rdmdiscovery::State::MUTE: //TODO MUTE + case rdmdiscovery::State::MUTE: ///< MUTE if (m_Mute.nTodEntries == 0) { m_Mute.bCommandRunning = false; NEW_STATE(rdmdiscovery::State::DISCOVERY, false); @@ -358,7 +358,7 @@ void RDMDiscovery::Process() { return; break; - case rdmdiscovery::State::DISCOVERY: //TODO DISCOVERY + case rdmdiscovery::State::DISCOVERY: ///< DISCOVERY if (m_Discovery.bCommandRunning) { m_pResponse = const_cast(m_Message.Receive(m_nPortIndex)); @@ -414,7 +414,7 @@ void RDMDiscovery::Process() { return; break; - case rdmdiscovery::State::DISCOVERY_SINGLE_DEVICE: //TODO DISCOVERY_SINGLE_DEVICE + case rdmdiscovery::State::DISCOVERY_SINGLE_DEVICE: ///< DISCOVERY_SINGLE_DEVICE if (m_DiscoverySingleDevice.nCounter == 0) { m_DiscoverySingleDevice.nCounter = rdmdiscovery::QUIKFIND_DISCOVERY_COUNTER; m_DiscoverySingleDevice.bCommandRunning = false; @@ -466,7 +466,7 @@ void RDMDiscovery::Process() { return; break; - case rdmdiscovery::State::DUB: //TODO DUB + case rdmdiscovery::State::DUB: ///< DUB if (m_pResponse == nullptr) { #ifndef NDEBUG puts("No responses"); @@ -490,7 +490,7 @@ void RDMDiscovery::Process() { NEW_STATE(rdmdiscovery::State::DISCOVERY, true); break; - case rdmdiscovery::State::QUICKFIND: //TODO QUICKFIND + case rdmdiscovery::State::QUICKFIND: ///< QUICKFIND if (m_QuikFind.nCounter == 0) { m_QuikFind.bCommandRunning = false; NEW_STATE(rdmdiscovery::State::QUICKFIND_DISCOVERY, false); @@ -550,7 +550,7 @@ void RDMDiscovery::Process() { return; break; - case rdmdiscovery::State::QUICKFIND_DISCOVERY: //TODO QUICKFIND_DISCOVERY + case rdmdiscovery::State::QUICKFIND_DISCOVERY: ///< QUICKFIND_DISCOVERY if (m_QuikFindDiscovery.nCounter == 0) { m_QuikFindDiscovery.nCounter = rdmdiscovery::QUIKFIND_DISCOVERY_COUNTER; m_QuikFindDiscovery.bCommandRunning = false; @@ -594,7 +594,7 @@ void RDMDiscovery::Process() { return; break; - case rdmdiscovery::State::FINISHED: //TODO FINISHED + case rdmdiscovery::State::FINISHED: ///< FINISHED m_bIsFinished = true; NEW_STATE(rdmdiscovery::State::IDLE, false); #ifndef NDEBUG diff --git a/lib-rdm/src/llrp/llrpdevice.cpp b/lib-rdm/src/llrp/llrpdevice.cpp index 7ba930ec7..e63664fb7 100755 --- a/lib-rdm/src/llrp/llrpdevice.cpp +++ b/lib-rdm/src/llrp/llrpdevice.cpp @@ -131,7 +131,7 @@ void LLRPDevice::HandleRdmCommand() { } uint8_t DestinationCid[16]; - memcpy(DestinationCid, pRDMCommand->Common.RootLayerPDU.SenderCid, 16); // TODO Optimize / cleanup + memcpy(DestinationCid, pRDMCommand->Common.RootLayerPDU.SenderCid, 16); const auto nMessageLength = static_cast(pReply[2] + 1); // RDM Command length without SC @@ -148,7 +148,7 @@ void LLRPDevice::HandleRdmCommand() { const auto nLength = sizeof(struct TRootLayerPreAmble) + RDM_ROOT_LAYER_LENGTH(nMessageLength); - Network::Get()->SendTo(s_nHandleLLRP, pRDMCommand, static_cast(nLength) , llrp::device::IPV4_LLRP_RESPONSE, llrp::device::LLRP_PORT); + Network::Get()->SendTo(s_nHandleLLRP, pRDMCommand, nLength , llrp::device::IPV4_LLRP_RESPONSE, llrp::device::LLRP_PORT); #ifdef SHOW_RDM_MESSAGE rdm::message_print(pReply); diff --git a/lib-rdm/src/llrp/llrpdevicedump.cpp b/lib-rdm/src/llrp/llrpdevicedump.cpp index 446bc6731..e108d7a3f 100755 --- a/lib-rdm/src/llrp/llrpdevicedump.cpp +++ b/lib-rdm/src/llrp/llrpdevicedump.cpp @@ -57,7 +57,7 @@ void LLRPDevice::DumpCommon() { } puts(""); - pPdu = (uint8_t *)pCommon->LlrpPDU.FlagsLength; + pPdu = reinterpret_cast(pCommon->LlrpPDU.FlagsLength); nLength = (((pPdu[0] & 0x0fu) << 16) | static_cast((pPdu[1] << 8)) | static_cast(pPdu[2])); printf("LlrpPDU PDU length=%d, High 4 bits=0x%.1x\n", nLength, static_cast(pCommon->LlrpPDU.FlagsLength[0]) >> 4); diff --git a/lib-rdm/src/llrp/rdmhandlere1372.cpp b/lib-rdm/src/llrp/rdmhandlere1372.cpp index dc8a68c06..b2fa97c65 100755 --- a/lib-rdm/src/llrp/rdmhandlere1372.cpp +++ b/lib-rdm/src/llrp/rdmhandlere1372.cpp @@ -2,7 +2,7 @@ * @file rdmhandlere137.cpp * */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,6 +23,10 @@ * THE SOFTWARE. */ +#if defined (DEBUG_RDM_LLRP) +# undef NDEBUG +#endif + #include #include "rdmhandler.h" @@ -43,9 +47,9 @@ enum { bool RDMHandler::CheckInterfaceID([[maybe_unused]] const struct TRdmMessageNoSc *pRdmDataIn) { #if !defined(DMX_WORKSHOP_DEFECT) - const uint32_t nInterfaceID = (pRdmDataIn->param_data[0] << 24) + const auto nInterfaceID = static_cast((pRdmDataIn->param_data[0] << 24) + (pRdmDataIn->param_data[1] << 16) - + (pRdmDataIn->param_data[2] << 8) + pRdmDataIn->param_data[3]; + + (pRdmDataIn->param_data[2] << 8) + pRdmDataIn->param_data[3]); if (nInterfaceID != Network::Get()->GetIfIndex()) { RespondMessageNack(E120_NR_DATA_OUT_OF_RANGE); @@ -81,7 +85,7 @@ void RDMHandler::GetInterfaceList([[maybe_unused]] uint16_t nSubDevice) { void RDMHandler::GetInterfaceName([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -104,7 +108,7 @@ void RDMHandler::GetInterfaceName([[maybe_unused]] uint16_t nSubDevice) { void RDMHandler::GetHardwareAddress([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -127,7 +131,7 @@ void RDMHandler::GetHardwareAddress([[maybe_unused]] uint16_t nSubDevice) { void RDMHandler::GetDHCPMode([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -150,7 +154,7 @@ void RDMHandler::GetDHCPMode([[maybe_unused]] uint16_t nSubDevice) { void RDMHandler::SetDHCPMode([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -165,16 +169,10 @@ void RDMHandler::SetDHCPMode([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] return; } - if (pRdmDataIn->param_data[4] == static_cast(network::dhcp::Mode::ACTIVE)) { - Network::Get()->SetQueuedDhcp(); - RespondMessageAck(); - - DEBUG_EXIT - return; - } + const auto mode = static_cast(pRdmDataIn->param_data[4]); - if (pRdmDataIn->param_data[4] == static_cast(network::dhcp::Mode::INACTIVE)) { - Network::Get()->SetQueuedStaticIp(); + if ((mode == network::dhcp::Mode::ACTIVE) || mode == network::dhcp::Mode::INACTIVE) { + Network::Get()->SetQueuedDhcp(mode); RespondMessageAck(); DEBUG_EXIT @@ -189,21 +187,23 @@ void RDMHandler::SetDHCPMode([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] void RDMHandler::GetNameServers([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); - const uint16_t nNameServerIndex = pRdmDataIn->param_data[0]; + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto nNameServerIndex = pRdmDataIn->param_data[0]; - if (nNameServerIndex > 2) { + if ((nNameServerIndex >= Network::Get()->GetNameServers()) || (nNameServerIndex > 2)) { RespondMessageNack(E120_NR_DATA_OUT_OF_RANGE); DEBUG_EXIT return; } - // TODO The Network class does not have GetNameServers - auto *pRdmDataOut = reinterpret_cast(m_pRdmDataOut); - memset(&pRdmDataOut->param_data[1], 0, 4); + uint32_t nIpAddress = Network::Get()->GetNameServer(nNameServerIndex); + const auto *p = reinterpret_cast(&nIpAddress); + + pRdmDataOut->param_data[0] = nNameServerIndex; + memcpy(&pRdmDataOut->param_data[1], p, 4); pRdmDataOut->param_data_length = 5; @@ -215,7 +215,7 @@ void RDMHandler::GetNameServers([[maybe_unused]] uint16_t nSubDevice) { void RDMHandler::GetZeroconf([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -238,7 +238,7 @@ void RDMHandler::GetZeroconf([[maybe_unused]] uint16_t nSubDevice) { void RDMHandler::SetZeroconf([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -262,7 +262,7 @@ void RDMHandler::SetZeroconf([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] } if (pRdmDataIn->param_data[4] == 0) { - Network::Get()->SetQueuedStaticIp(); + Network::Get()->SetQueuedStaticIp(0, 0); RespondMessageAck(); DEBUG_EXIT @@ -277,7 +277,7 @@ void RDMHandler::SetZeroconf([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] void RDMHandler::RenewDhcp([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -299,7 +299,7 @@ void RDMHandler::RenewDhcp([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] u return; } - Network::Get()->EnableDhcp(); // TODO This will cause a time-out -> queued message + Network::Get()->EnableDhcp(); RespondMessageAck(); @@ -309,7 +309,7 @@ void RDMHandler::RenewDhcp([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] u void RDMHandler::GetAddressNetmask([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -337,7 +337,7 @@ void RDMHandler::GetAddressNetmask([[maybe_unused]] uint16_t nSubDevice) { void RDMHandler::GetStaticAddress([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -364,7 +364,7 @@ void RDMHandler::GetStaticAddress([[maybe_unused]] uint16_t nSubDevice) { void RDMHandler::SetStaticAddress([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (pRdmDataIn->param_data_length != 9) { RespondMessageNack(E120_NR_FORMAT_ERROR); @@ -393,7 +393,7 @@ void RDMHandler::SetStaticAddress([[maybe_unused]] bool IsBroadcast, [[maybe_unu void RDMHandler::ApplyConfiguration([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -416,7 +416,7 @@ void RDMHandler::ApplyConfiguration([[maybe_unused]] bool IsBroadcast, [[maybe_u void RDMHandler::GetDefaultRoute([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); if (!CheckInterfaceID(pRdmDataIn)) { @@ -442,14 +442,37 @@ void RDMHandler::GetDefaultRoute([[maybe_unused]] uint16_t nSubDevice) { void RDMHandler::SetDefaultRoute([[maybe_unused]] bool IsBroadcast, [[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY - RespondMessageNack(E137_2_NR_ACTION_NOT_SUPPORTED); + const auto *pRdmDataIn = reinterpret_cast(m_pRdmDataIn); + + if (pRdmDataIn->param_data_length != 8) { + RespondMessageNack(E120_NR_FORMAT_ERROR); + + DEBUG_EXIT + return; + } + + if (!CheckInterfaceID(pRdmDataIn)) { + + DEBUG_EXIT + return; + } + + uint32_t nIpAddress; + auto *p = reinterpret_cast(&nIpAddress); + memcpy(p, &pRdmDataIn->param_data[4], 4); + + Network::Get()->SetQueuedDefaultRoute(nIpAddress); + + RespondMessageAck(); + + DEBUG_EXIT } void RDMHandler::GetHostName([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY const auto *pHostName = Network::Get()->GetHostName(); - HandleString(pHostName, static_cast(strlen(pHostName))); + HandleString(pHostName, static_cast(strlen(pHostName))); RespondMessageAck(); @@ -481,7 +504,7 @@ void RDMHandler::GetDomainName([[maybe_unused]] uint16_t nSubDevice) { DEBUG_ENTRY const auto *pDomainName = Network::Get()->GetDomainName(); - HandleString(pDomainName, static_cast(strlen(pDomainName))); + HandleString(pDomainName, static_cast(strlen(pDomainName))); RespondMessageAck(); diff --git a/lib-rdm/src/rdmdevice.cpp b/lib-rdm/src/rdmdevice.cpp index ba89f2776..1b4d55a20 100644 --- a/lib-rdm/src/rdmdevice.cpp +++ b/lib-rdm/src/rdmdevice.cpp @@ -64,11 +64,13 @@ RDMDevice *RDMDevice::s_pThis; RDMDevice::RDMDevice() { DEBUG_ENTRY - assert(s_pThis == nullptr); s_pThis = this; -#if defined (NO_EMAC) + m_aUID[0] = RDMConst::MANUFACTURER_ID[0]; + m_aUID[1] = RDMConst::MANUFACTURER_ID[1]; + +#if defined (NO_EMAC) || !defined(CONFIG_RDMDEVICE_UUID_IP) uint8_t aMacAddress[network::MAC_SIZE]; Network::Get()->MacAddressCopyTo(aMacAddress); @@ -76,28 +78,14 @@ RDMDevice::RDMDevice() { m_aUID[3] = aMacAddress[3]; m_aUID[4] = aMacAddress[4]; m_aUID[5] = aMacAddress[5]; -#else - const auto nIp = Network::Get()->GetIp(); -# if !defined(CONFIG_RDMDEVICE_REVERSE_UID) - m_aUID[5] = static_cast(nIp >> 24); - m_aUID[4] = (nIp >> 16) & 0xFF; - m_aUID[3] = (nIp >> 8) & 0xFF; - m_aUID[2] = nIp & 0xFF; -# else - m_aUID[2] = static_cast(nIp >> 24); - m_aUID[3] = (nIp >> 16) & 0xFF; - m_aUID[4] = (nIp >> 8) & 0xFF; - m_aUID[5] = nIp & 0xFF; -# endif -#endif - - m_aUID[0] = RDMConst::MANUFACTURER_ID[0]; - m_aUID[1] = RDMConst::MANUFACTURER_ID[1]; m_aSN[0] = m_aUID[5]; m_aSN[1] = m_aUID[4]; m_aSN[2] = m_aUID[3]; m_aSN[3] = m_aUID[2]; +#else + // Calculated with GetUID and GetSN +#endif m_nFactoryRootLabelLength = sizeof(DEVICE_LABEL) - 1; memcpy(m_aFactoryRootLabel, DEVICE_LABEL, m_nFactoryRootLabelLength); diff --git a/lib-remoteconfig/include/remoteconfig.h b/lib-remoteconfig/include/remoteconfig.h index 1a3b72c6a..b851f56c2 100644 --- a/lib-remoteconfig/include/remoteconfig.h +++ b/lib-remoteconfig/include/remoteconfig.h @@ -2,7 +2,7 @@ * @file remoteconfig.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -239,7 +239,9 @@ class RemoteConfig { void HandleReboot(); void HandleFactory(); void HandleList(); +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) void HandleUptime(); +#endif void HandleVersion(); void HandleGetNoParams() { diff --git a/lib-remoteconfig/include/tftp/tftpfileserver.h b/lib-remoteconfig/include/tftp/tftpfileserver.h index ebc1b02cf..16a4c7d32 100755 --- a/lib-remoteconfig/include/tftp/tftpfileserver.h +++ b/lib-remoteconfig/include/tftp/tftpfileserver.h @@ -2,7 +2,7 @@ * @file tftpfileserver.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,7 +29,7 @@ #include #include -#include "tftpdaemon.h" +#include "net/apps/tftpdaemon.h" #if defined (GD32) # include "gd32.h" diff --git a/lib-remoteconfig/src/httpd/httpd.cpp b/lib-remoteconfig/src/httpd/httpd.cpp index d508031f8..a3f643610 100755 --- a/lib-remoteconfig/src/httpd/httpd.cpp +++ b/lib-remoteconfig/src/httpd/httpd.cpp @@ -31,7 +31,7 @@ #include "httpd/httpd.h" #include "network.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "../../lib-network/config/net_config.h" diff --git a/lib-remoteconfig/src/httpd/httpdhandlerequest.cpp b/lib-remoteconfig/src/httpd/httpdhandlerequest.cpp index 965b097c1..cd94534fc 100755 --- a/lib-remoteconfig/src/httpd/httpdhandlerequest.cpp +++ b/lib-remoteconfig/src/httpd/httpdhandlerequest.cpp @@ -46,7 +46,7 @@ #include "hardware.h" #include "network.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "display.h" #if defined(RDM_CONTROLLER) @@ -264,7 +264,8 @@ http::Status HttpDeamonHandleRequest::ParseHeaderField(char *pLine) { DEBUG_ENTRY char *pToken; - assert(pLine != 0); + assert(pLine != nullptr); + if ((pToken = strtok(pLine, ":")) == nullptr) { return http::Status::BAD_REQUEST; } diff --git a/lib-remoteconfig/src/remoteconfig.cpp b/lib-remoteconfig/src/remoteconfig.cpp index e8d4d0789..dfa594cc9 100644 --- a/lib-remoteconfig/src/remoteconfig.cpp +++ b/lib-remoteconfig/src/remoteconfig.cpp @@ -2,7 +2,7 @@ * @file remoteconfig.cpp * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -41,7 +41,7 @@ #include "hardware.h" #include "network.h" #if !defined (CONFIG_REMOTECONFIG_MINIMUM) -# include "mdns.h" +# include "net/apps/mdns.h" #endif #include "display.h" @@ -184,10 +184,10 @@ namespace get { enum class Command { REBOOT, LIST, - UPTIME, VERSION, DISPLAY, #if !defined (CONFIG_REMOTECONFIG_MINIMUM) + UPTIME, # if (defined (NODE_ARTNET) || defined (NODE_NODE)) && (defined (RDM_CONTROLLER) || defined (RDM_RESPONDER)) RDM, # endif @@ -211,13 +211,13 @@ enum class Command { } // namespace udp } // namespace remoteconfig -const struct RemoteConfig::Commands RemoteConfig::s_GET[] = { +constexpr struct RemoteConfig::Commands RemoteConfig::s_GET[] = { { &RemoteConfig::HandleReboot, "reboot##", 8, false }, { &RemoteConfig::HandleList, "list#", 5, false }, - { &RemoteConfig::HandleUptime, "uptime#", 7, false }, { &RemoteConfig::HandleVersion, "version#", 8, false }, { &RemoteConfig::HandleDisplayGet, "display#", 8, false }, #if !defined (CONFIG_REMOTECONFIG_MINIMUM) + { &RemoteConfig::HandleUptime, "uptime#", 7, false }, # if (defined (NODE_ARTNET) || defined (NODE_NODE)) && (defined (RDM_CONTROLLER) || defined (RDM_RESPONDER)) { &RemoteConfig::HandleRdmGet, "rdm#", 4, false }, # endif @@ -227,7 +227,7 @@ const struct RemoteConfig::Commands RemoteConfig::s_GET[] = { { &RemoteConfig::HandleFactory, "factory##", 9, false } }; -const struct RemoteConfig::Commands RemoteConfig::s_SET[] = { +constexpr struct RemoteConfig::Commands RemoteConfig::s_SET[] = { #if !defined (CONFIG_REMOTECONFIG_MINIMUM) # if (defined (NODE_ARTNET) || defined (NODE_NODE)) && (defined (RDM_CONTROLLER) || defined (RDM_RESPONDER)) { &RemoteConfig::HandleRdmSet, "rdm#", 4, true }, @@ -413,6 +413,7 @@ void RemoteConfig::HandleRequest() { } } +#if !defined (CONFIG_REMOTECONFIG_MINIMUM) void RemoteConfig::HandleUptime() { DEBUG_ENTRY @@ -422,29 +423,20 @@ void RemoteConfig::HandleUptime() { } const auto nUptime = Hardware::Get()->GetUpTime(); - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::UPTIME)].nLength; + const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "uptime: %us\n", static_cast(nUptime)); - if (m_nBytesReceived == nCmdLength) { - const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "uptime: %us\n", static_cast(nUptime)); - Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); - DEBUG_EXIT - return; - } + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } +#endif void RemoteConfig::HandleVersion() { DEBUG_ENTRY - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::VERSION)].nLength; - if (m_nBytesReceived == nCmdLength) { - const auto *p = FirmwareVersion::Get()->GetPrint(); - const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "version:%s", p); - Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); - DEBUG_EXIT - return; - } + const auto *p = FirmwareVersion::Get()->GetPrint(); + const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "version:%s", p); + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } @@ -452,13 +444,7 @@ void RemoteConfig::HandleVersion() { void RemoteConfig::HandleList() { DEBUG_ENTRY - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::LIST)].nLength; - - if (m_nBytesReceived != nCmdLength) { - DEBUG_EXIT - return; - } - + constexpr auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::LIST)].nLength; auto *pListResponse = &s_pUdpBuffer[nCmdLength + 2U]; const auto nListResponseBufferLength = remoteconfig::udp::BUFFER_SIZE - (nCmdLength + 2U); int32_t nListLength; @@ -478,7 +464,7 @@ void RemoteConfig::HandleList() { static_cast(m_nActiveOutputs)); } - Network::Get()->SendTo(m_nHandle, pListResponse, static_cast(nListLength), m_nIPAddressFrom, remoteconfig::udp::PORT); + Network::Get()->SendTo(m_nHandle, pListResponse, static_cast(nListLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } @@ -486,7 +472,7 @@ void RemoteConfig::HandleList() { void RemoteConfig::HandleDisplaySet() { DEBUG_ENTRY - const auto nCmdLength = s_SET[static_cast(remoteconfig::udp::set::Command::DISPLAY)].nLength; + constexpr auto nCmdLength = s_SET[static_cast(remoteconfig::udp::set::Command::DISPLAY)].nLength; if (m_nBytesReceived != (nCmdLength + 1U)) { DEBUG_EXIT @@ -502,13 +488,10 @@ void RemoteConfig::HandleDisplaySet() { void RemoteConfig::HandleDisplayGet() { DEBUG_ENTRY - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::DISPLAY)].nLength; const bool isOn = !(Display::Get()->isSleep()); + const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "display:%s\n", isOn ? "On" : "Off"); - if (m_nBytesReceived == nCmdLength) { - const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "display:%s\n", isOn ? "On" : "Off"); - Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); - } + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } @@ -534,13 +517,10 @@ void RemoteConfig::HandleRdmSet() { void RemoteConfig::HandleRdmGet() { DEBUG_ENTRY - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::RDM)].nLength; const bool isOn = ArtNetNode::Get()->GetRdm(); + const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "rdm:%s\n", isOn ? "On" : "Off"); - if (m_nBytesReceived == nCmdLength) { - const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "rdm:%s\n", isOn ? "On" : "Off"); - Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); - } + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } @@ -556,7 +536,7 @@ uint32_t RemoteConfig::HandleGet(void *pBuffer, uint32_t nBufferLength) { uint32_t nSize; int32_t nIndex; - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::GET)].nLength; + constexpr auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::GET)].nLength; if (pBuffer == nullptr) { nSize = remoteconfig::udp::BUFFER_SIZE - nCmdLength; @@ -582,7 +562,7 @@ uint32_t RemoteConfig::HandleGet(void *pBuffer, uint32_t nBufferLength) { (this->*(handler->GetHandler))(nSize); if (pBuffer == nullptr) { - Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nSize), m_nIPAddressFrom, remoteconfig::udp::PORT); + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, nSize, m_nIPAddressFrom, remoteconfig::udp::PORT); } else { memcpy(pBuffer, s_pUdpBuffer, std::min(nSize, nBufferLength)); } @@ -1260,7 +1240,7 @@ void RemoteConfig::TftpExit() { void RemoteConfig::HandleTftpSet() { DEBUG_ENTRY - const auto nCmdLength = s_SET[static_cast(remoteconfig::udp::set::Command::TFTP)].nLength; + constexpr auto nCmdLength = s_SET[static_cast(remoteconfig::udp::set::Command::TFTP)].nLength; if (m_nBytesReceived != (nCmdLength + 1U)) { DEBUG_EXIT @@ -1283,14 +1263,8 @@ void RemoteConfig::HandleTftpGet() { PlatformHandleTftpGet(); - const auto nCmdLength = s_GET[static_cast(remoteconfig::udp::get::Command::TFTP)].nLength; - - if (m_nBytesReceived == nCmdLength) { - const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "tftp:%s\n", m_bEnableTFTP ? "On" : "Off"); - Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); - DEBUG_EXIT - return; - } + const auto nLength = snprintf(s_pUdpBuffer, remoteconfig::udp::BUFFER_SIZE - 1, "tftp:%s\n", m_bEnableTFTP ? "On" : "Off"); + Network::Get()->SendTo(m_nHandle, s_pUdpBuffer, static_cast(nLength), m_nIPAddressFrom, remoteconfig::udp::PORT); DEBUG_EXIT } diff --git a/lib-remoteconfig/src/remoteconfigfactory.cpp b/lib-remoteconfig/src/remoteconfigfactory.cpp index 0d70db95e..1aa0d9b4b 100644 --- a/lib-remoteconfig/src/remoteconfigfactory.cpp +++ b/lib-remoteconfig/src/remoteconfigfactory.cpp @@ -2,7 +2,7 @@ * @file remoteconfigfactory.cpp * */ -/* Copyright (C) 2021 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,9 +32,7 @@ void RemoteConfig::HandleFactory() { DEBUG_ENTRY - for (uint32_t i = 0; i < static_cast(configstore::Store::LAST); i++) { - ConfigStore::Get()->ResetSetList(static_cast(i)); - } + ConfigStore::Get()->ResetSetListAll(); DEBUG_EXIT } diff --git a/lib-remoteconfig/src/remoteconfigreboot.cpp b/lib-remoteconfig/src/remoteconfigreboot.cpp index 7ff69c17a..643f72b67 100644 --- a/lib-remoteconfig/src/remoteconfigreboot.cpp +++ b/lib-remoteconfig/src/remoteconfigreboot.cpp @@ -51,8 +51,6 @@ void RemoteConfig::HandleReboot() { while (ConfigStore::Get()->Flash()) ; - Network::Get()->Shutdown(); - Display::Get()->Cls(); Display::Get()->TextStatus("Rebooting ..."); diff --git a/lib-remoteconfig/src/remoteconfigstatic.cpp b/lib-remoteconfig/src/remoteconfigstatic.cpp index 9973d2c4a..d3356fe60 100644 --- a/lib-remoteconfig/src/remoteconfigstatic.cpp +++ b/lib-remoteconfig/src/remoteconfigstatic.cpp @@ -38,7 +38,7 @@ using namespace remoteconfig; #if !defined (CONFIG_REMOTECONFIG_MINIMUM) -const RemoteConfig::Txt RemoteConfig::s_TXT[] = { +constexpr RemoteConfig::Txt RemoteConfig::s_TXT[] = { { &RemoteConfig::HandleGetRconfigTxt, &RemoteConfig::HandleSetRconfigTxt, "rconfig.txt", 11}, { &RemoteConfig::HandleGetEnvTxt, &RemoteConfig::HandleSetEnvTxt, "env.txt", 7 }, { &RemoteConfig::HandleGetNetworkTxt, &RemoteConfig::HandleSetNetworkTxt, "network.txt", 11}, diff --git a/lib-remoteconfig/src/shell/shellcmd.cpp b/lib-remoteconfig/src/shell/shellcmd.cpp index 723353a34..53c27cbbb 100644 --- a/lib-remoteconfig/src/shell/shellcmd.cpp +++ b/lib-remoteconfig/src/shell/shellcmd.cpp @@ -3,7 +3,7 @@ * */ /* Copyright (C) 2020 by hippy mailto:dmxout@gmail.com - * Copyright (C) 2020-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl + * Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -53,7 +53,7 @@ #ifndef NDEBUG # include "../debug/i2cdetect.h" -# include "ntpclient.h" +# include "net/apps/ntpclient.h" # include "gps.h" extern "C" { void h3_board_dump(void); @@ -336,11 +336,8 @@ void Shell::CmdGet() { } void Shell::CmdDhcp() { - if (Network::Get()->EnableDhcp()) { - Puts(msg::info::DHCP); - } else { - Puts(msg::error::DHCP); - } + Network::Get()->EnableDhcp(); + Puts(msg::info::DHCP); } void Shell::CmdDate() { diff --git a/lib-showfile/include/showfileosc.h b/lib-showfile/include/showfileosc.h index 54f995945..660563945 100644 --- a/lib-showfile/include/showfileosc.h +++ b/lib-showfile/include/showfileosc.h @@ -2,7 +2,7 @@ * @file showfileosc.h * */ -/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -96,13 +96,13 @@ class ShowFileOSC { void ShowFiles(); private: - uint16_t m_nPortIncoming; - uint16_t m_nPortOutgoing; int32_t m_nHandle { -1 }; + char *m_pBuffer { nullptr }; uint32_t m_nRemoteIp { 0 }; + uint32_t m_nBytesReceived; uint16_t m_nRemotePort { 0 }; - uint16_t m_nBytesReceived; - char *m_pBuffer { nullptr }; + uint16_t m_nPortIncoming; + uint16_t m_nPortOutgoing; }; #endif /* SHOWFILEOSC_H_ */ diff --git a/lib-showfile/include/showfiletftp.h b/lib-showfile/include/showfiletftp.h index f7e3cd58d..954678505 100644 --- a/lib-showfile/include/showfiletftp.h +++ b/lib-showfile/include/showfiletftp.h @@ -28,7 +28,7 @@ #include -#include "tftpdaemon.h" +#include "net/apps/tftpdaemon.h" #include "debug.h" diff --git a/lib-tlc59711dmx/include/tlc59711dmx.h b/lib-tlc59711dmx/include/tlc59711dmx.h index b972545cb..dc2618235 100644 --- a/lib-tlc59711dmx/include/tlc59711dmx.h +++ b/lib-tlc59711dmx/include/tlc59711dmx.h @@ -48,7 +48,7 @@ class TLC59711Dmx final: public LightSet { void SetData(const uint32_t nPortIndex, const uint8_t *pDmxData, uint32_t nLength, const bool doUpdate = true) override; void Sync(const uint32_t nPortIndex) override; - void Sync(const bool doForce = false) override; + void Sync() override; #if defined (CONFIG_TLC59711DMX_ENABLE_PCT) void SetMaxPct(uint32_t nIndexLed, uint32_t nPct); diff --git a/lib-tlc59711dmx/src/tlc59711dmx.cpp b/lib-tlc59711dmx/src/tlc59711dmx.cpp index bccb4f07b..efabf640b 100644 --- a/lib-tlc59711dmx/src/tlc59711dmx.cpp +++ b/lib-tlc59711dmx/src/tlc59711dmx.cpp @@ -24,9 +24,6 @@ */ #include -#ifndef NDEBUG // FIXME Remove debug information -# include -#endif #include #include "tlc59711dmx.h" @@ -129,7 +126,7 @@ void TLC59711Dmx::SetMaxPct(uint32_t nIndexLed, uint32_t nPct) { } } -# ifndef NDEBUG // FIXME Remove debug information +# if 0 for (uint32_t nIndexLed = 0; nIndexLed < m_nCount; nIndexLed++) { if (m_type == tlc59711::Type::RGB) { const auto nIndexArray = nIndexLed * 3U; @@ -191,8 +188,8 @@ void TLC59711Dmx::Sync([[maybe_unused]] uint32_t const nPortIndex) { // No actions here } -void TLC59711Dmx::Sync(const bool doForce) { - if ((!doForce) && (!m_bBlackout)) { +void TLC59711Dmx::Sync() { + if (!m_bBlackout) { m_pTLC59711->Update(); } } diff --git a/lib-widget/src/hdmi/widgetmonitor.cpp b/lib-widget/src/hdmi/widgetmonitor.cpp index 4995c8091..9c72bc305 100644 --- a/lib-widget/src/hdmi/widgetmonitor.cpp +++ b/lib-widget/src/hdmi/widgetmonitor.cpp @@ -2,7 +2,7 @@ * @file widgetmonitor.cpp * */ -/* Copyright (C) 2015-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2015-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,6 +39,8 @@ #include "hardware.h" +static constexpr auto DISPLAY_LEVEL = 1; + /* RDM START CODE (Slot 0) */ #define E120_SC_RDM 0xCC @@ -170,16 +172,15 @@ void WidgetMonitor::Sniffer() { void WidgetMonitor::Update() { const auto tMode = Widget::Get()->GetMode(); - const auto display_level = 1; // FIXME - if (tMode != Mode::RDM_SNIFFER && display_level == 0) { + if (tMode != Mode::RDM_SNIFFER && DISPLAY_LEVEL == 0) { return; } struct TWidgetConfiguration widget_params; WidgetConfiguration::Get(&widget_params); - if (display_level > 1) { + if (DISPLAY_LEVEL > 1) { WidgetMonitor::Uptime(MonitorLine::TIME); } @@ -230,11 +231,10 @@ void WidgetMonitor::Update() { void WidgetMonitor::RdmData(int nLine, uint16_t nDataLength, const uint8_t *pData, bool isSent) { auto *p = (uint8_t *) pData; bool is_rdm_command = (*p == E120_SC_RDM); - const auto display_level = 1 ; // FIXME WidgetMonitor::Line(nLine, "RDM [%s], l:%d\n", isSent ? "Sent" : "Received", (int) nDataLength); - if (display_level == 0) { + if (DISPLAY_LEVEL == 0) { return; } diff --git a/linux_artnet/src/main.cpp b/linux_artnet/src/main.cpp index 738a91c91..57636c424 100644 --- a/linux_artnet/src/main.cpp +++ b/linux_artnet/src/main.cpp @@ -2,7 +2,7 @@ * @file main.cpp * */ -/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2017-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,7 +35,7 @@ #include "display.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "artnetnode.h" #include "artnetparams.h" diff --git a/linux_ddp/src/main.cpp b/linux_ddp/src/main.cpp index d728dc11c..773cd5e45 100644 --- a/linux_ddp/src/main.cpp +++ b/linux_ddp/src/main.cpp @@ -35,7 +35,7 @@ #include "display.h" #include "displayudfparams.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "ddpdisplay.h" diff --git a/linux_e131/src/main.cpp b/linux_e131/src/main.cpp index 51bae7711..935aa5b61 100644 --- a/linux_e131/src/main.cpp +++ b/linux_e131/src/main.cpp @@ -36,7 +36,7 @@ #include "display.h" #include "displayudfparams.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "e131bridge.h" #include "e131params.h" diff --git a/linux_osc/src/main.cpp b/linux_osc/src/main.cpp index 9fbdcdd5c..01f2617ca 100644 --- a/linux_osc/src/main.cpp +++ b/linux_osc/src/main.cpp @@ -35,7 +35,7 @@ #include "display.h" #include "displayudfparams.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "handler.h" diff --git a/linux_pp/src/main.cpp b/linux_pp/src/main.cpp index 0974f4c9b..35080458e 100644 --- a/linux_pp/src/main.cpp +++ b/linux_pp/src/main.cpp @@ -35,7 +35,7 @@ #include "display.h" #include "displayudfparams.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "pp.h" diff --git a/opi_dmx_monitor/firmware/main.cpp b/opi_dmx_monitor/firmware/main.cpp index 61a50b6d5..43ce29a67 100644 --- a/opi_dmx_monitor/firmware/main.cpp +++ b/opi_dmx_monitor/firmware/main.cpp @@ -64,7 +64,7 @@ int main() { display.TextStatus(NetworkConst::MSG_NETWORK_INIT, CONSOLE_YELLOW); Network nw; display.TextStatus(NetworkConst::MSG_NETWORK_STARTED, CONSOLE_GREEN); - nw.Print(); + #endif console_clear(); diff --git a/opi_emac_artnet_dmx/Makefile.H3 b/opi_emac_artnet_dmx/Makefile.H3 index 8ce9d0bf1..c753b7780 100644 --- a/opi_emac_artnet_dmx/Makefile.H3 +++ b/opi_emac_artnet_dmx/Makefile.H3 @@ -23,7 +23,7 @@ DEFINES+=ENABLE_HTTPD ENABLE_CONTENT DEFINES+=DISABLE_RTC -DEFINES+=NDEBUG +#DEFINES+=NDEBUG LIBS= diff --git a/opi_emac_artnet_dmx/firmware/main.cpp b/opi_emac_artnet_dmx/firmware/main.cpp index dce8a7978..f93550412 100644 --- a/opi_emac_artnet_dmx/firmware/main.cpp +++ b/opi_emac_artnet_dmx/firmware/main.cpp @@ -30,7 +30,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -83,9 +83,6 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("Art-Net " STR(LIGHTSET_PORTS) " Node DMX/RDM"); - nw.Print(); - - display.TextStatus(ArtNetMsgConst::PARAMS, CONSOLE_YELLOW); ArtNetNode node; diff --git a/opi_emac_artnet_dmx_multi/Makefile.H3 b/opi_emac_artnet_dmx_multi/Makefile.H3 index 6ab125026..0812e13db 100644 --- a/opi_emac_artnet_dmx_multi/Makefile.H3 +++ b/opi_emac_artnet_dmx_multi/Makefile.H3 @@ -29,8 +29,7 @@ endif DEFINES+=DISABLE_RTC -#DEFINES+=LOGIC_ANALYZER -#DEFINES+=NDEBUG +DEFINES+=NDEBUG LIBS= diff --git a/opi_emac_artnet_dmx_multi/firmware/main.cpp b/opi_emac_artnet_dmx_multi/firmware/main.cpp index 14629e29f..adc57fad8 100644 --- a/opi_emac_artnet_dmx_multi/firmware/main.cpp +++ b/opi_emac_artnet_dmx_multi/firmware/main.cpp @@ -30,7 +30,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -83,9 +83,6 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("Art-Net " STR(LIGHTSET_PORTS) " Node DMX/RDM"); - nw.Print(); - - display.TextStatus(ArtNetMsgConst::PARAMS, CONSOLE_YELLOW); ArtNetNode node; diff --git a/opi_emac_artnet_monitor/firmware/main.cpp b/opi_emac_artnet_monitor/firmware/main.cpp index 0100c7739..dc14bbd34 100644 --- a/opi_emac_artnet_monitor/firmware/main.cpp +++ b/opi_emac_artnet_monitor/firmware/main.cpp @@ -30,9 +30,9 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" -#include "ntpclient.h" +#include "net/apps/ntpclient.h" #include "console.h" #include "h3/showsystime.h" @@ -92,7 +92,7 @@ int main() { console_set_fg_color(CONSOLE_WHITE); console_set_top_row(2); - nw.Print(); + NtpClient ntpClient; ntpClient.Start(); @@ -100,8 +100,6 @@ int main() { ShowSystime showSystime; - display.TextStatus(ArtNetMsgConst::PARAMS, CONSOLE_YELLOW); - ArtNetNode node; ArtNetParams artnetParams; diff --git a/opi_emac_artnet_rdm_l6470/firmware/main.cpp b/opi_emac_artnet_rdm_l6470/firmware/main.cpp index 357c95da8..0a0af52a2 100644 --- a/opi_emac_artnet_rdm_l6470/firmware/main.cpp +++ b/opi_emac_artnet_rdm_l6470/firmware/main.cpp @@ -31,9 +31,9 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" -#include "ntpclient.h" +#include "net/apps/ntpclient.h" #include "displayudf.h" #include "displayudfparams.h" @@ -99,7 +99,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("Art-Net 4 Stepper L6470"); - nw.Print(); + NtpClient ntpClient; ntpClient.Start(); @@ -145,8 +145,6 @@ int main() { snprintf(aDescription, sizeof(aDescription) - 1, "Sparkfun [%d]", nMotorsConnected); } - display.TextStatus(ArtNetMsgConst::PARAMS, CONSOLE_YELLOW); - ArtNetNode node; ArtNetParams artnetParams; diff --git a/opi_emac_artnet_rdm_pca9685/firmware/main.cpp b/opi_emac_artnet_rdm_pca9685/firmware/main.cpp index e86fb0ce8..aa1d01992 100755 --- a/opi_emac_artnet_rdm_pca9685/firmware/main.cpp +++ b/opi_emac_artnet_rdm_pca9685/firmware/main.cpp @@ -31,9 +31,9 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" -#include "ntpclient.h" +#include "net/apps/ntpclient.h" #include "displayudf.h" #include "displayudfparams.h" @@ -94,7 +94,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("Art-Net 4 PCA9685"); - nw.Print(); + NtpClient ntpClient; ntpClient.Start(); @@ -106,8 +106,6 @@ int main() { pca9685DmxParams.Load(); pca9685DmxParams.Set(&pca9685Dmx); - display.TextStatus(ArtNetMsgConst::PARAMS, CONSOLE_YELLOW); - ArtNetNode node; ArtNetParams artnetParams; diff --git a/opi_emac_artnet_serial/firmware/main.cpp b/opi_emac_artnet_serial/firmware/main.cpp index e42f537bd..920ff2467 100644 --- a/opi_emac_artnet_serial/firmware/main.cpp +++ b/opi_emac_artnet_serial/firmware/main.cpp @@ -29,7 +29,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -84,9 +84,6 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("Art-Net 4 Node Serial [UART/SPI/I2C] {1 Universe}"); - nw.Print(); - - display.TextStatus(ArtNetMsgConst::PARAMS, CONSOLE_YELLOW); ArtNetNode node; diff --git a/opi_emac_e131_artnet/firmware/main.cpp b/opi_emac_e131_artnet/firmware/main.cpp index 85fe303b8..f734cfa7c 100644 --- a/opi_emac_e131_artnet/firmware/main.cpp +++ b/opi_emac_e131_artnet/firmware/main.cpp @@ -29,7 +29,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -80,9 +80,6 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("sACN E1.31 -> Art-Net"); - nw.Print(); - - display.TextStatus(E131MsgConst::PARAMS, CONSOLE_YELLOW); E131Bridge bridge; diff --git a/opi_emac_e131_artnet/include/artnetoutput.h b/opi_emac_e131_artnet/include/artnetoutput.h index d85a041bc..d8747c7c1 100644 --- a/opi_emac_e131_artnet/include/artnetoutput.h +++ b/opi_emac_e131_artnet/include/artnetoutput.h @@ -43,7 +43,7 @@ class ArtNetOutput: public E131Sync, public LightSet { void SetData(const uint32_t nPortIndex, const uint8_t *pData, uint32_t nLength, const bool doUpdate = true) override; void Sync(const uint32_t nPortIndex) override; - void Sync(const bool doForce = false) override; + void Sync() override; private: uint16_t m_nUniverse[e131bridge::MAX_PORTS]; diff --git a/opi_emac_e131_artnet/lib/artnetoutput.cpp b/opi_emac_e131_artnet/lib/artnetoutput.cpp index 58dd4e84a..abbb09e88 100644 --- a/opi_emac_e131_artnet/lib/artnetoutput.cpp +++ b/opi_emac_e131_artnet/lib/artnetoutput.cpp @@ -2,7 +2,7 @@ * @file artnetoutput.cpp * */ -/* Copyright (C) 2020-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -93,7 +93,7 @@ void ArtNetOutput::Sync([[maybe_unused]] uint32_t const nPortIndex) { //TODO Implement Sync } -void ArtNetOutput::Sync([[maybe_unused]] const bool doForce) { +void ArtNetOutput::Sync() { DEBUG_ENTRY //TODO Implement Sync diff --git a/opi_emac_e131_dmx/firmware/main.cpp b/opi_emac_e131_dmx/firmware/main.cpp index 28e42d851..b9b6dd8f3 100644 --- a/opi_emac_e131_dmx/firmware/main.cpp +++ b/opi_emac_e131_dmx/firmware/main.cpp @@ -29,7 +29,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -90,10 +90,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("sACN E1.31 DMX"); - nw.Print(); - - display.TextStatus(E131MsgConst::PARAMS, CONSOLE_YELLOW); - + E131Bridge bridge; E131Params e131params; diff --git a/opi_emac_e131_dmx_multi/firmware/main.cpp b/opi_emac_e131_dmx_multi/firmware/main.cpp index 477a77c0c..dde627958 100644 --- a/opi_emac_e131_dmx_multi/firmware/main.cpp +++ b/opi_emac_e131_dmx_multi/firmware/main.cpp @@ -29,7 +29,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -90,10 +90,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("sACN E1.31 DMX"); - nw.Print(); - - display.TextStatus(E131MsgConst::PARAMS, CONSOLE_YELLOW); - + E131Bridge bridge; E131Params e131params; diff --git a/opi_emac_e131_monitor/firmware/main.cpp b/opi_emac_e131_monitor/firmware/main.cpp index f93792a9f..b552f7ef3 100644 --- a/opi_emac_e131_monitor/firmware/main.cpp +++ b/opi_emac_e131_monitor/firmware/main.cpp @@ -30,9 +30,9 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" -#include "ntpclient.h" +#include "net/apps/ntpclient.h" #include "console.h" #include "h3/showsystime.h" @@ -97,7 +97,7 @@ int main() { console_set_fg_color(CONSOLE_WHITE); console_set_top_row(2); - nw.Print(); + NtpClient ntpClient; ntpClient.Start(); @@ -125,8 +125,6 @@ int main() { llrpOnlyDevice.Print(); - display.TextStatus(E131MsgConst::PARAMS, CONSOLE_YELLOW); - E131Bridge bridge; E131Params e131params; diff --git a/opi_emac_llrp_tftpd/Makefile.H3 b/opi_emac_llrp_tftpd/Makefile.H3 index 1248278d6..fcf48330a 100644 --- a/opi_emac_llrp_tftpd/Makefile.H3 +++ b/opi_emac_llrp_tftpd/Makefile.H3 @@ -9,7 +9,21 @@ DEFINES+=ENABLE_HTTPD ENABLE_CONTENT DEFINES+=ENET_LINK_CHECK_REG_POLL -DEFINES+=NDEBUG +DEFINES+=DEBUG_STACK +DEFINES+=DEBUG_HEAP + +#DEFINES+=DEBUG_NET_IP +#DEFINES+=DEBUG_NET_UDP +#DEFINES+=DEBUG_NET_ARP +#DEFINES+=DEBUG_NET_ACD +DEFINES+=DEBUG_NET_DHCP +DEFINES+=DEBUG_NET_NETIF +DEFINES+=DEBUG_NET_NET +DEFINES+=DEBUG_NETWORK + +DEFINES+=DEBUG_RDM_LLRP + +#DEFINES+=NDEBUG LIBS= diff --git a/opi_emac_llrp_tftpd/firmware/main.cpp b/opi_emac_llrp_tftpd/firmware/main.cpp index 704a2f281..3858e14e5 100755 --- a/opi_emac_llrp_tftpd/firmware/main.cpp +++ b/opi_emac_llrp_tftpd/firmware/main.cpp @@ -24,12 +24,12 @@ */ #include +#include #include "hardware.h" #include "network.h" #include "networkconst.h" - #include "displayudf.h" #include "displayudfparams.h" #include "flashcodeinstall.h" @@ -41,9 +41,9 @@ # include "rdmnetllrponly.h" #endif -#include "mdns.h" +#include "net/apps/mdns.h" -#include "ntpclient.h" +#include "net/apps/ntpclient.h" #include "factorydefaults.h" @@ -57,8 +57,6 @@ void Hardware::RebootHandler() { while (ConfigStore::Get()->Flash()) ; - Network::Get()->Shutdown(); - printf("Rebooting ...\n"); Display::Get()->Cls(); @@ -78,7 +76,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("RDMNet LLRP device only"); - nw.Print(); + NtpClient ntpClient; ntpClient.Start(); @@ -119,6 +117,8 @@ int main() { hw.SetMode(hardware::ledblink::Mode::NORMAL); auto t1 = time(nullptr); + struct tm tmHwClock; + memset(&tmHwClock, 0, sizeof(struct tm)); for (;;) { nw.Run(); @@ -138,12 +138,11 @@ int main() { auto *tm = localtime(<ime); struct tm tmlocal; memcpy(&tmlocal, tm, sizeof(struct tm)); - struct tm tmHwClock; HwClock::Get()->Get(&tmHwClock); display.Printf(7, "%.2d:%.2d:%.2d %.2d:%.2d:%.2d", tmlocal.tm_hour, tmlocal.tm_min, tmlocal.tm_sec, tmHwClock.tm_hour, tmHwClock.tm_min, tmHwClock.tm_sec); - printf("%.2d:%.2d:%.2d %.2d:%.2d:%.2d\n", + printf("%.2d:%.2d:%.2d %.2d:%.2d:%.2d\r", tmlocal.tm_hour, tmlocal.tm_min, tmlocal.tm_sec, tmHwClock.tm_hour, tmHwClock.tm_min, tmHwClock.tm_sec); } diff --git a/opi_emac_ltc_smpte/firmware/main.cpp b/opi_emac_ltc_smpte/firmware/main.cpp index be382b45a..29c6ba726 100644 --- a/opi_emac_ltc_smpte/firmware/main.cpp +++ b/opi_emac_ltc_smpte/firmware/main.cpp @@ -31,7 +31,7 @@ #include "hardware.h" #include "network.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "display.h" @@ -92,7 +92,7 @@ #endif // System Time -#include "ntpclient.h" +#include "net/apps/ntpclient.h" #include "gpstimeclient.h" #include "gpsparams.h" @@ -132,8 +132,6 @@ void Hardware::RebootHandler() { while (ConfigStore::Get()->Flash()) ; - Network::Get()->Shutdown(); - Display::Get()->Cls(); Display::Get()->TextStatus("Rebooting ..."); } @@ -154,7 +152,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("LTC SMPTE"); - nw.Print(); + #if defined(ENABLE_SHELL) Shell shell; diff --git a/opi_emac_ltc_smpte/include/ltcsource.h b/opi_emac_ltc_smpte/include/ltcsource.h index 143713b89..8ccd6a6ac 100644 --- a/opi_emac_ltc_smpte/include/ltcsource.h +++ b/opi_emac_ltc_smpte/include/ltcsource.h @@ -30,7 +30,7 @@ #include "ltcsourceconst.h" #include "display.h" #include "gps.h" -#include "ntpclient.h" +#include "net/apps/ntpclient.h" #include "tcnetdisplay.h" namespace ltc { diff --git a/opi_emac_ltc_smpte/lib/mcpbuttons.cpp b/opi_emac_ltc_smpte/lib/mcpbuttons.cpp index e95d067b4..4072cca8f 100644 --- a/opi_emac_ltc_smpte/lib/mcpbuttons.cpp +++ b/opi_emac_ltc_smpte/lib/mcpbuttons.cpp @@ -390,7 +390,6 @@ void McpButtons::HandleRunActionSelect() { Display::Get()->Cls(); Display::Get()->TextStatus("Reboot ..."); - Network::Get()->Shutdown(); Hardware::Get()->Reboot(); return; diff --git a/opi_emac_ltc_smpte/lib/networkdisplay.cpp b/opi_emac_ltc_smpte/lib/networkdisplay.cpp index 0b483dbbd..c5021dea9 100644 --- a/opi_emac_ltc_smpte/lib/networkdisplay.cpp +++ b/opi_emac_ltc_smpte/lib/networkdisplay.cpp @@ -2,7 +2,7 @@ * @file networkdisplay.cpp * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,29 +23,39 @@ * THE SOFTWARE. */ -#include "network.h" +#include #include "display.h" -namespace network { +#include "network.h" +#include "net/protocol/dhcp.h" + +namespace net { +static constexpr auto LINE_IP = 2U; + void display_emac_config() { - Display::Get()->ClearEndOfLine(); - Display::Get()->Printf(3, "Ethernet config"); + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet config"); } void display_emac_start() { - Display::Get()->ClearEndOfLine(); - Display::Get()->Printf(3, "Ethernet start"); + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet start"); } void display_emac_status(const bool isLinkUp) { - Display::Get()->ClearEndOfLine(); - Display::Get()->Printf(3, "Ethernet Link %s", isLinkUp ? "UP" : "DOWN"); + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet Link "); + if (isLinkUp) { + Display::Get()->PutString("UP"); + } else { + Display::Get()->PutString("DOWN"); + } } void display_ip() { - Display::Get()->ClearEndOfLine(); - Display::Get()->Printf(3, IPSTR "/%d %c", IP2STR(Network::Get()->GetIp()), static_cast(Network::Get()->GetNetmaskCIDR()), Network::Get()->GetAddressingMode()); + Display::Get()->ClearLine(LINE_IP); + Display::Get()->Printf(LINE_IP, "" IPSTR "/%d %c", IP2STR(Network::Get()->GetIp()), Network::Get()->GetNetmaskCIDR(), Network::Get()->GetAddressingMode()); } void display_netmask() { @@ -59,24 +69,27 @@ void display_hostname() { } void display_emac_shutdown() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet shutdown"); } -// DHCP Client -void display_dhcp_status(network::dhcp::ClientStatus nStatus) { - switch (nStatus) { - case network::dhcp::ClientStatus::IDLE: +void display_dhcp_status(net::dhcp::State state) { + Display::Get()->ClearLine(LINE_IP); + + switch (state) { + case net::dhcp::State::STATE_OFF: break; - case network::dhcp::ClientStatus::RENEW: - Display::Get()->ClearEndOfLine(); - Display::Get()->Printf(3, "DHCP renewing"); + case net::dhcp::State::STATE_RENEWING: + Display::Get()->PutString("DHCP renewing"); break; - case network::dhcp::ClientStatus::GOT_IP: + case net::dhcp::State::STATE_BOUND: + Display::Get()->PutString("Got IP"); break; - case network::dhcp::ClientStatus::RETRYING: - Display::Get()->ClearEndOfLine(); - Display::Get()->Printf(3, "DHCP retrying"); + case net::dhcp::State::STATE_REQUESTING: + Display::Get()->PutString("DHCP requesting"); break; - case network::dhcp::ClientStatus::FAILED: + case net::dhcp::State::STATE_BACKING_OFF: + Display::Get()->PutString("DHCP Error"); break; default: break; diff --git a/opi_emac_ltc_smpte/lib/ntpclientdisplay.cpp b/opi_emac_ltc_smpte/lib/ntpclientdisplay.cpp index 4d5108080..9f6043271 100644 --- a/opi_emac_ltc_smpte/lib/ntpclientdisplay.cpp +++ b/opi_emac_ltc_smpte/lib/ntpclientdisplay.cpp @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -#include "ntp.h" +#include "net/protocol/ntp.h" #include "display.h" namespace ntpclient { diff --git a/opi_emac_osc_client/firmware/main.cpp b/opi_emac_osc_client/firmware/main.cpp index ec5a26c79..a855f0d26 100644 --- a/opi_emac_osc_client/firmware/main.cpp +++ b/opi_emac_osc_client/firmware/main.cpp @@ -32,7 +32,7 @@ #include "display.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "oscclient.h" #include "oscclientparams.h" @@ -68,7 +68,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("OSC Client"); - nw.Print(); + OscClientParams params; OscClient client; diff --git a/opi_emac_osc_client/lib/networkdisplay.cpp b/opi_emac_osc_client/lib/networkdisplay.cpp index af3db144f..c5021dea9 100644 --- a/opi_emac_osc_client/lib/networkdisplay.cpp +++ b/opi_emac_osc_client/lib/networkdisplay.cpp @@ -2,7 +2,7 @@ * @file networkdisplay.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,24 +23,76 @@ * THE SOFTWARE. */ +#include + +#include "display.h" + #include "network.h" +#include "net/protocol/dhcp.h" -namespace network { -void display_emac_config() {} -void display_emac_start() {} -void display_emac_status([[maybe_unused]] const bool isLinkUp) {} +namespace net { +static constexpr auto LINE_IP = 2U; -void display_ip() {} +void display_emac_config() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet config"); +} -void display_netmask() {} +void display_emac_start() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet start"); +} -void display_gateway() {} +void display_emac_status(const bool isLinkUp) { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet Link "); + if (isLinkUp) { + Display::Get()->PutString("UP"); + } else { + Display::Get()->PutString("DOWN"); + } +} -void display_hostname() {} +void display_ip() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->Printf(LINE_IP, "" IPSTR "/%d %c", IP2STR(Network::Get()->GetIp()), Network::Get()->GetNetmaskCIDR(), Network::Get()->GetAddressingMode()); +} -void display_emac_shutdown() {} +void display_netmask() { + display_ip(); +} -// DHCP Client -void display_dhcp_status([[maybe_unused]] network::dhcp::ClientStatus nStatus) {} -} // namespace network +void display_gateway() { +} + +void display_hostname() { +} +void display_emac_shutdown() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet shutdown"); +} + +void display_dhcp_status(net::dhcp::State state) { + Display::Get()->ClearLine(LINE_IP); + + switch (state) { + case net::dhcp::State::STATE_OFF: + break; + case net::dhcp::State::STATE_RENEWING: + Display::Get()->PutString("DHCP renewing"); + break; + case net::dhcp::State::STATE_BOUND: + Display::Get()->PutString("Got IP"); + break; + case net::dhcp::State::STATE_REQUESTING: + Display::Get()->PutString("DHCP requesting"); + break; + case net::dhcp::State::STATE_BACKING_OFF: + Display::Get()->PutString("DHCP Error"); + break; + default: + break; + } +} +} // namespace network diff --git a/opi_emac_osc_dmx/firmware/main.cpp b/opi_emac_osc_dmx/firmware/main.cpp index 23269924c..9de088735 100644 --- a/opi_emac_osc_dmx/firmware/main.cpp +++ b/opi_emac_osc_dmx/firmware/main.cpp @@ -32,7 +32,7 @@ #include "display.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "oscserver.h" #include "oscserverparams.h" @@ -69,7 +69,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("OSC Server DMX"); - nw.Print(); + OSCServerParams params; OscServer server; diff --git a/opi_emac_osc_dmx/lib/networkdisplay.cpp b/opi_emac_osc_dmx/lib/networkdisplay.cpp index af3db144f..c5021dea9 100644 --- a/opi_emac_osc_dmx/lib/networkdisplay.cpp +++ b/opi_emac_osc_dmx/lib/networkdisplay.cpp @@ -2,7 +2,7 @@ * @file networkdisplay.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,24 +23,76 @@ * THE SOFTWARE. */ +#include + +#include "display.h" + #include "network.h" +#include "net/protocol/dhcp.h" -namespace network { -void display_emac_config() {} -void display_emac_start() {} -void display_emac_status([[maybe_unused]] const bool isLinkUp) {} +namespace net { +static constexpr auto LINE_IP = 2U; -void display_ip() {} +void display_emac_config() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet config"); +} -void display_netmask() {} +void display_emac_start() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet start"); +} -void display_gateway() {} +void display_emac_status(const bool isLinkUp) { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet Link "); + if (isLinkUp) { + Display::Get()->PutString("UP"); + } else { + Display::Get()->PutString("DOWN"); + } +} -void display_hostname() {} +void display_ip() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->Printf(LINE_IP, "" IPSTR "/%d %c", IP2STR(Network::Get()->GetIp()), Network::Get()->GetNetmaskCIDR(), Network::Get()->GetAddressingMode()); +} -void display_emac_shutdown() {} +void display_netmask() { + display_ip(); +} -// DHCP Client -void display_dhcp_status([[maybe_unused]] network::dhcp::ClientStatus nStatus) {} -} // namespace network +void display_gateway() { +} + +void display_hostname() { +} +void display_emac_shutdown() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet shutdown"); +} + +void display_dhcp_status(net::dhcp::State state) { + Display::Get()->ClearLine(LINE_IP); + + switch (state) { + case net::dhcp::State::STATE_OFF: + break; + case net::dhcp::State::STATE_RENEWING: + Display::Get()->PutString("DHCP renewing"); + break; + case net::dhcp::State::STATE_BOUND: + Display::Get()->PutString("Got IP"); + break; + case net::dhcp::State::STATE_REQUESTING: + Display::Get()->PutString("DHCP requesting"); + break; + case net::dhcp::State::STATE_BACKING_OFF: + Display::Get()->PutString("DHCP Error"); + break; + default: + break; + } +} +} // namespace network diff --git a/opi_emac_osc_monitor/firmware/main.cpp b/opi_emac_osc_monitor/firmware/main.cpp index 02e1b44f3..20bf856c0 100644 --- a/opi_emac_osc_monitor/firmware/main.cpp +++ b/opi_emac_osc_monitor/firmware/main.cpp @@ -34,9 +34,9 @@ #include "console.h" #include "h3/showsystime.h" -#include "ntpclient.h" +#include "net/apps/ntpclient.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "display.h" #include "displayhandler.h" @@ -81,7 +81,7 @@ int main() { console_set_fg_color(CONSOLE_WHITE); console_set_top_row(2); - nw.Print(); + ShowSystime showSystime; diff --git a/opi_emac_osc_monitor/lib/networkdisplay.cpp b/opi_emac_osc_monitor/lib/networkdisplay.cpp index af3db144f..c5021dea9 100644 --- a/opi_emac_osc_monitor/lib/networkdisplay.cpp +++ b/opi_emac_osc_monitor/lib/networkdisplay.cpp @@ -2,7 +2,7 @@ * @file networkdisplay.cpp * */ -/* Copyright (C) 2022-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -23,24 +23,76 @@ * THE SOFTWARE. */ +#include + +#include "display.h" + #include "network.h" +#include "net/protocol/dhcp.h" -namespace network { -void display_emac_config() {} -void display_emac_start() {} -void display_emac_status([[maybe_unused]] const bool isLinkUp) {} +namespace net { +static constexpr auto LINE_IP = 2U; -void display_ip() {} +void display_emac_config() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet config"); +} -void display_netmask() {} +void display_emac_start() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet start"); +} -void display_gateway() {} +void display_emac_status(const bool isLinkUp) { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet Link "); + if (isLinkUp) { + Display::Get()->PutString("UP"); + } else { + Display::Get()->PutString("DOWN"); + } +} -void display_hostname() {} +void display_ip() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->Printf(LINE_IP, "" IPSTR "/%d %c", IP2STR(Network::Get()->GetIp()), Network::Get()->GetNetmaskCIDR(), Network::Get()->GetAddressingMode()); +} -void display_emac_shutdown() {} +void display_netmask() { + display_ip(); +} -// DHCP Client -void display_dhcp_status([[maybe_unused]] network::dhcp::ClientStatus nStatus) {} -} // namespace network +void display_gateway() { +} + +void display_hostname() { +} +void display_emac_shutdown() { + Display::Get()->ClearLine(LINE_IP); + Display::Get()->PutString("Ethernet shutdown"); +} + +void display_dhcp_status(net::dhcp::State state) { + Display::Get()->ClearLine(LINE_IP); + + switch (state) { + case net::dhcp::State::STATE_OFF: + break; + case net::dhcp::State::STATE_RENEWING: + Display::Get()->PutString("DHCP renewing"); + break; + case net::dhcp::State::STATE_BOUND: + Display::Get()->PutString("Got IP"); + break; + case net::dhcp::State::STATE_REQUESTING: + Display::Get()->PutString("DHCP requesting"); + break; + case net::dhcp::State::STATE_BACKING_OFF: + Display::Get()->PutString("DHCP Error"); + break; + default: + break; + } +} +} // namespace network diff --git a/opi_emac_osc_monitor/lib/ntpclient.cpp b/opi_emac_osc_monitor/lib/ntpclient.cpp index 855022fc6..b60412b7f 100644 --- a/opi_emac_osc_monitor/lib/ntpclient.cpp +++ b/opi_emac_osc_monitor/lib/ntpclient.cpp @@ -23,7 +23,7 @@ * THE SOFTWARE. */ -#include "ntp.h" +#include "net/protocol/ntp.h" #include "display.h" namespace ntpclient { diff --git a/opi_emac_showfile_artnet/firmware/main.cpp b/opi_emac_showfile_artnet/firmware/main.cpp index 71fa549f9..e53ee8a71 100755 --- a/opi_emac_showfile_artnet/firmware/main.cpp +++ b/opi_emac_showfile_artnet/firmware/main.cpp @@ -30,7 +30,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -62,8 +62,6 @@ void Hardware::RebootHandler() { while (ConfigStore::Get()->Flash()) ; - Network::Get()->Shutdown(); - printf("Rebooting ...\n"); Display::Get()->Cls(); @@ -83,7 +81,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("Showfile player"); - nw.Print(); + ShowFile showFile; diff --git a/opi_emac_showfile_e131/firmware/main.cpp b/opi_emac_showfile_e131/firmware/main.cpp index 7e74e8614..e8cf3bd01 100755 --- a/opi_emac_showfile_e131/firmware/main.cpp +++ b/opi_emac_showfile_e131/firmware/main.cpp @@ -30,7 +30,7 @@ #include "network.h" #include "networkconst.h" -#include "mdns.h" +#include "net/apps/mdns.h" #include "displayudf.h" #include "displayudfparams.h" @@ -62,8 +62,6 @@ void Hardware::RebootHandler() { while (ConfigStore::Get()->Flash()) ; - Network::Get()->Shutdown(); - printf("Rebooting ...\n"); Display::Get()->Cls(); @@ -83,7 +81,7 @@ int main() { FlashCodeInstall spiFlashInstall; fw.Print("Showfile player"); - nw.Print(); + ShowFile showFile; diff --git a/opi_midi_monitor/firmware/main.cpp b/opi_midi_monitor/firmware/main.cpp index df709d9d3..ae2b603e0 100644 --- a/opi_midi_monitor/firmware/main.cpp +++ b/opi_midi_monitor/firmware/main.cpp @@ -66,7 +66,7 @@ int main() { midi.Init(midi::Direction::INPUT); #if !defined(NO_EMAC) - nw.Print(); + RemoteConfigParams remoteConfigParams; remoteConfigParams.Load(); diff --git a/opi_rdm_responder/firmware/main.cpp b/opi_rdm_responder/firmware/main.cpp index 5622e2723..7ba062611 100644 --- a/opi_rdm_responder/firmware/main.cpp +++ b/opi_rdm_responder/firmware/main.cpp @@ -30,7 +30,7 @@ #include "network.h" #if !defined(NO_EMAC) # include "networkconst.h" -# include "mdns.h" +# include "net/apps/mdns.h" #endif #include "displayudf.h" @@ -89,16 +89,16 @@ int main() { fw.Print("RDM Responder"); #if !defined(NO_EMAC) - nw.Print(); + #endif PixelDmxConfiguration pixelDmxConfiguration; PixelDmxParams pixelDmxParams; pixelDmxParams.Load(); - pixelDmxParams.Set(&pixelDmxConfiguration); + pixelDmxParams.Set(); - WS28xxDmx pixelDmx(&pixelDmxConfiguration); + WS28xxDmx pixelDmx; const auto nTestPattern = static_cast(pixelDmxParams.GetTestPattern()); PixelTestPattern pixelTestPattern(nTestPattern, 1); @@ -107,10 +107,10 @@ int main() { char aDescription[rdm::personality::DESCRIPTION_MAX_LENGTH]; snprintf(aDescription, sizeof(aDescription) - 1U, "%s:%u G%u [%s]", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); RDMPersonality *personalities[2] = { new RDMPersonality(aDescription, &pixelDmx), @@ -178,12 +178,11 @@ int main() { displayUdfParams.Set(&display); display.Show(); - display.Printf(7, "%s:%d G%d %s", - PixelType::GetType(pixelDmxConfiguration.GetType()), + pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount(), - PixelType::GetMap(pixelDmxConfiguration.GetMap())); + pixel::pixel_get_map(pixelDmxConfiguration.GetMap())); if (isConfigMode) { display.ClearLine(3); diff --git a/opi_rdm_responder/lib/display.cpp b/opi_rdm_responder/lib/display.cpp index a94290548..014a40747 100644 --- a/opi_rdm_responder/lib/display.cpp +++ b/opi_rdm_responder/lib/display.cpp @@ -45,10 +45,10 @@ void PixelDmxParamsRdm::Display(const uint8_t *pData) { } DisplayUdf::Get()->Printf(7, "%-8s %-2d G%-2d %-5s", - PixelType::GetType(static_cast(pData[static_cast(SlotInfo::TYPE)])), + pixel::pixel_get_type(static_cast(pData[static_cast(SlotInfo::TYPE)])), pData[static_cast(SlotInfo::COUNT)], pData[static_cast(SlotInfo::GROUPING_COUNT)], - PixelType::GetMap(static_cast(pData[static_cast(SlotInfo::MAP)]))); + pixel::pixel_get_map(static_cast(pData[static_cast(SlotInfo::MAP)]))); if (pData[nLastIndex] == 0xFF) { if (!s_IsProgrammed) { diff --git a/opi_rdm_responder/lib/personalityupdate.cpp b/opi_rdm_responder/lib/personalityupdate.cpp index 291a34cc3..b1354b393 100644 --- a/opi_rdm_responder/lib/personalityupdate.cpp +++ b/opi_rdm_responder/lib/personalityupdate.cpp @@ -2,7 +2,7 @@ * @file personalityupdate.cpp * */ -/* Copyright (C) 2021-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -39,10 +39,10 @@ void RDMResponder::PersonalityUpdate(uint32_t nPersonality) { DisplayUdf::Get()->ClearEndOfLine(); DisplayUdf::Get()->Printf(7, "%s:%d G%d %s", - PixelType::GetType(WS28xxDmx::Get()->GetType()), - WS28xxDmx::Get()->GetCount(), - WS28xxDmx::Get()->GetGroupingCount(), - PixelType::GetMap(WS28xxDmx::Get()->GetMap())); + pixel::pixel_get_type(PixelConfiguration::Get().GetType()), + PixelConfiguration::Get().GetCount(), + PixelDmxConfiguration::Get().GetGroupingCount(), + pixel::pixel_get_map(PixelConfiguration::Get().GetMap())); DisplayUdf::Get()->Show(); if (nPersonality == 1) { diff --git a/opi_rdm_responder_l6470/firmware/main.cpp b/opi_rdm_responder_l6470/firmware/main.cpp index c13f5a53e..c1b049c5a 100644 --- a/opi_rdm_responder_l6470/firmware/main.cpp +++ b/opi_rdm_responder_l6470/firmware/main.cpp @@ -82,7 +82,7 @@ int main() { fw.Print(); #if !defined(NO_EMAC) - nw.Print(); + #endif LightSet *pBoard; diff --git a/rpi_wifi_artnet_monitor/firmware/main.cpp b/rpi_wifi_artnet_monitor/firmware/main.cpp index 31e8cfbe9..bbe3f9817 100755 --- a/rpi_wifi_artnet_monitor/firmware/main.cpp +++ b/rpi_wifi_artnet_monitor/firmware/main.cpp @@ -147,7 +147,7 @@ int main() { assert(pWS28xxDmx != nullptr); pSpi = pWS28xxDmx; - display.Printf(7, "%s:%d G%d", PixelType::GetType(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); + display.Printf(7, "%s:%d G%d", pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); const auto nUniverses = pWS28xxDmx->GetUniverses(); diff --git a/rpi_wifi_e131_dmx/Makefile.BCM b/rpi_wifi_e131_dmx/Makefile.BCM index a19689d0f..5a796b5f8 100644 --- a/rpi_wifi_e131_dmx/Makefile.BCM +++ b/rpi_wifi_e131_dmx/Makefile.BCM @@ -6,7 +6,7 @@ DEFINES+=ENABLE_MMU DEFINES+=DISABLE_RTC DEFINES+=NDEBUG -LIBS=e131 uuid dmxsend dmx ws28xxdmx ws28xx dmxmonitor lightset display +LIBS=e131 dmxsend dmx ws28xxdmx ws28xx dmxmonitor lightset display SRCDIR=firmware diff --git a/rpi_wifi_e131_monitor/Makefile.BCM b/rpi_wifi_e131_monitor/Makefile.BCM index a19689d0f..5a796b5f8 100755 --- a/rpi_wifi_e131_monitor/Makefile.BCM +++ b/rpi_wifi_e131_monitor/Makefile.BCM @@ -6,7 +6,7 @@ DEFINES+=ENABLE_MMU DEFINES+=DISABLE_RTC DEFINES+=NDEBUG -LIBS=e131 uuid dmxsend dmx ws28xxdmx ws28xx dmxmonitor lightset display +LIBS=e131 dmxsend dmx ws28xxdmx ws28xx dmxmonitor lightset display SRCDIR=firmware diff --git a/rpi_wifi_osc_dmx/lib/handler.cpp b/rpi_wifi_osc_dmx/lib/handler.cpp deleted file mode 100644 index 15505dc30..000000000 --- a/rpi_wifi_osc_dmx/lib/handler.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @file handler.cpp - * - */ -/* Copyright (C) 2019-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include - -#include "handler.h" - -#include "pixeltype.h" -#include "ws28xxdmx.h" -#include "pixeldmxparams.h" - -#include "oscsimplesend.h" - -#include "debug.h" - -Handler::Handler(WS28xxDmx *pWS28xxDmx): - m_pWS28xxDmx(pWS28xxDmx), - m_nCount(WS28xx::Get()->GetCount()), - m_TypeString(const_cast(PixelType::GetType(WS28xx::Get()->GetType()))) -{ - DEBUG_ENTRY - - DEBUG_EXIT -} - -void Handler::Info(int32_t nHandle, uint32_t nRemoteIp, uint16_t nPortOutgoing) { - OscSimpleSend MsgSendLedType(nHandle, nRemoteIp, nPortOutgoing, "/info/ledtype", "s", m_TypeString); - OscSimpleSend MsgSendLedCount(nHandle, nRemoteIp, nPortOutgoing, "/info/ledcount", "i", static_cast(m_nCount)); -} diff --git a/rpi_wifi_osc_monitor/firmware/main.cpp b/rpi_wifi_osc_monitor/firmware/main.cpp index dd8fc258a..951ecd984 100755 --- a/rpi_wifi_osc_monitor/firmware/main.cpp +++ b/rpi_wifi_osc_monitor/firmware/main.cpp @@ -145,7 +145,7 @@ int main() { assert(pPixelDmx != nullptr); pSpi = pPixelDmx; - display.Printf(7, "%s:%d G%d", PixelType::GetType(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); + display.Printf(7, "%s:%d G%d", pixel::pixel_get_type(pixelDmxConfiguration.GetType()), pixelDmxConfiguration.GetCount(), pixelDmxConfiguration.GetGroupingCount()); server.SetOutput(pSpi); server.SetOscServerHandler(new Handler(pPixelDmx)); diff --git a/rpi_wifi_osc_monitor/lib/handler.cpp b/rpi_wifi_osc_monitor/lib/handler.cpp index 15505dc30..cfe453117 100755 --- a/rpi_wifi_osc_monitor/lib/handler.cpp +++ b/rpi_wifi_osc_monitor/lib/handler.cpp @@ -39,7 +39,7 @@ Handler::Handler(WS28xxDmx *pWS28xxDmx): m_pWS28xxDmx(pWS28xxDmx), m_nCount(WS28xx::Get()->GetCount()), - m_TypeString(const_cast(PixelType::GetType(WS28xx::Get()->GetType()))) + m_TypeString(const_cast(pixel::pixel_get_type(WS28xx::Get()->GetType()))) { DEBUG_ENTRY From 7eba7c2c24a2e51d269f9af2c4de851a9c5f54ae Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 30 Aug 2024 11:11:18 +0200 Subject: [PATCH 11/17] Removed lib-uuid --- lib-uuid/.cproject | 129 ----------------- lib-uuid/.project | 26 ---- lib-uuid/.settings/language.settings.xml | 27 ---- lib-uuid/Makefile.BCM | 6 - lib-uuid/Makefile.H3 | 6 - lib-uuid/src/uuid_internal.h | 39 ------ lib-uuid/src/uuid_parse.c | 171 ----------------------- lib-uuid/src/uuid_unparse.c | 133 ------------------ 8 files changed, 537 deletions(-) delete mode 100644 lib-uuid/.cproject delete mode 100644 lib-uuid/.project delete mode 100644 lib-uuid/.settings/language.settings.xml delete mode 100644 lib-uuid/Makefile.BCM delete mode 100644 lib-uuid/Makefile.H3 delete mode 100644 lib-uuid/src/uuid_internal.h delete mode 100644 lib-uuid/src/uuid_parse.c delete mode 100644 lib-uuid/src/uuid_unparse.c diff --git a/lib-uuid/.cproject b/lib-uuid/.cproject deleted file mode 100644 index 51ce1a4cf..000000000 --- a/lib-uuid/.cproject +++ /dev/null @@ -1,129 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib-uuid/.project b/lib-uuid/.project deleted file mode 100644 index 22913528b..000000000 --- a/lib-uuid/.project +++ /dev/null @@ -1,26 +0,0 @@ - - - lib-uuid - - - - - - org.eclipse.cdt.managedbuilder.core.genmakebuilder - clean,full,incremental, - - - - - org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder - full,incremental, - - - - - - org.eclipse.cdt.core.cnature - org.eclipse.cdt.managedbuilder.core.managedBuildNature - org.eclipse.cdt.managedbuilder.core.ScannerConfigNature - - diff --git a/lib-uuid/.settings/language.settings.xml b/lib-uuid/.settings/language.settings.xml deleted file mode 100644 index bacc0e1ec..000000000 --- a/lib-uuid/.settings/language.settings.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/lib-uuid/Makefile.BCM b/lib-uuid/Makefile.BCM deleted file mode 100644 index 53a69699f..000000000 --- a/lib-uuid/Makefile.BCM +++ /dev/null @@ -1,6 +0,0 @@ -# -DEFINES = NDEBUG -# -EXTRA_INCLUDES = -# -include ../firmware-template-bcm/lib/Rules.mk \ No newline at end of file diff --git a/lib-uuid/Makefile.H3 b/lib-uuid/Makefile.H3 deleted file mode 100644 index d9af62c4e..000000000 --- a/lib-uuid/Makefile.H3 +++ /dev/null @@ -1,6 +0,0 @@ -# -DEFINES = NDEBUG -# -EXTRA_INCLUDES = -# -include ../firmware-template-h3/lib/Rules.mk \ No newline at end of file diff --git a/lib-uuid/src/uuid_internal.h b/lib-uuid/src/uuid_internal.h deleted file mode 100644 index 1a4530d6a..000000000 --- a/lib-uuid/src/uuid_internal.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @file uuid_internal.h - * - */ -/* Copyright (C) 2016-2023 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef UUID_INTERNAL_H_ -#define UUID_INTERNAL_H_ - -#include - -struct uuid { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint16_t clock_seq; - uint8_t node[6]; -}; - -#endif /* UUID_INTERNAL_H_ */ diff --git a/lib-uuid/src/uuid_parse.c b/lib-uuid/src/uuid_parse.c deleted file mode 100644 index 462b96a30..000000000 --- a/lib-uuid/src/uuid_parse.c +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @file uuid_parse.c - * - */ -/** - * This code is inspired by: - * http://code.metager.de/source/xref/linux/utils/util-linux/libuuid/src/ - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ -/* Copyright (C) 2016-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "uuid_internal.h" - -static uint32_t hex_uint32(const char *s) { - uint32_t ret = 0; - uint8_t nibble; - - while (*s != '\0') { - char d = *s; - - if (isxdigit((int) d) == 0) { - break; - } - - nibble = d > '9' ? (uint8_t)((uint8_t)( d | 0x20) - 'a' + 10) : (uint8_t) (d - '0'); - ret = (ret << 4) | nibble; - s++; - } - - return ret; -} - -static void uuid_pack(const struct uuid *uu, uuid_t ptr) { - uint32_t tmp; - unsigned char *out = ptr; - - assert(uu != NULL); - - tmp = uu->time_low; - out[3] = (unsigned char) tmp; - tmp >>= 8; - out[2] = (unsigned char) tmp; - tmp >>= 8; - out[1] = (unsigned char) tmp; - tmp >>= 8; - out[0] = (unsigned char) tmp; - - tmp = uu->time_mid; - out[5] = (unsigned char) tmp; - tmp >>= 8; - out[4] = (unsigned char) tmp; - - tmp = uu->time_hi_and_version; - out[7] = (unsigned char) tmp; - tmp >>= 8; - out[6] = (unsigned char) tmp; - - tmp = uu->clock_seq; - out[9] = (unsigned char) tmp; - tmp >>= 8; - out[8] = (unsigned char) tmp; - - memcpy(out + 10, uu->node, 6); -} - -int uuid_parse(const char *in, uuid_t uu) { - struct uuid uuid; - int i; - const char *cp; - char buf[3]; - - assert(in != NULL); - - if (strlen(in) != 36) { - return -1; - } - - for (i = 0, cp = in; i <= 36; i++, cp++) { - - if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) { - if (*cp == '-') { - continue; - } else { - return -1; - } - } - - if (i == 36) { - if (*cp == 0) { - continue; - } - } - - if (!isxdigit(*cp)) { - return -1; - } - } - - uuid.time_low = hex_uint32(in); - uuid.time_mid = (uint16_t)(hex_uint32(in + 9)); - uuid.time_hi_and_version = (uint16_t)(hex_uint32(in + 14)); - uuid.clock_seq = (uint16_t)(hex_uint32(in + 19)); - - cp = in + 24; - buf[2] = 0; - - for (i = 0; i < 6; i++) { - buf[0] = *cp++; - buf[1] = *cp++; - uuid.node[i] = (uint8_t)(hex_uint32(buf)); - } - - uuid_pack(&uuid, uu); - - return 0; -} diff --git a/lib-uuid/src/uuid_unparse.c b/lib-uuid/src/uuid_unparse.c deleted file mode 100644 index 5c012495c..000000000 --- a/lib-uuid/src/uuid_unparse.c +++ /dev/null @@ -1,133 +0,0 @@ -/** - * @file uuid_unparse.c - * - */ -/** - * This code is inspired by: - * http://code.metager.de/source/xref/linux/utils/util-linux/libuuid/src/ - * - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR - * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ -/* Copyright (C) 2016-2021 by Arjan van Vught mailto:info@orangepi-dmx.nl - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include - -#include "uuid_internal.h" - -#ifndef ALIGNED - #define ALIGNED __attribute__ ((aligned (4))) -#endif - -static const char *fmt_lower ALIGNED = "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; -static const char *fmt_upper ALIGNED = "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"; - -#ifdef UUID_UNPARSE_DEFAULT_UPPER -#define FMT_DEFAULT fmt_upper -#else -#define FMT_DEFAULT fmt_lower -#endif - -static void uuid_unpack(const uuid_t in, struct uuid *uu) { - const uint8_t *ptr = in; - uint32_t tmp; - - assert(uu != NULL); - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - tmp = (tmp << 8) | *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_low = tmp; - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_mid = (uint16_t)(tmp); - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_hi_and_version = (uint16_t)(tmp); - - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->clock_seq = (uint16_t)(tmp); - - memcpy(uu->node, ptr, 6); -} - -static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt) { - struct uuid uuid; - - assert(out != NULL); - assert(fmt != NULL); - - uuid_unpack(uu, &uuid); - - sprintf(out, fmt, uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, - uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, uuid.node[0], - uuid.node[1], uuid.node[2], uuid.node[3], uuid.node[4], - uuid.node[5]); -} - -void uuid_unparse_lower(const uuid_t uu, char *out) { - uuid_unparse_x(uu, out, fmt_lower); -} - -void uuid_unparse_upper(const uuid_t uu, char *out) { - uuid_unparse_x(uu, out, fmt_upper); -} - -void uuid_unparse(const uuid_t uu, char *out) { - uuid_unparse_x(uu, out, FMT_DEFAULT); -} From e22c460dfa35f83955767887f594c2c6ca13eb6a Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 30 Aug 2024 11:12:38 +0200 Subject: [PATCH 12/17] Improved HTTP server *. pre-work for support upgrading firmware with browser. --- lib-network/include/emac/network.h | 2 +- lib-network/include/linux/network.h | 2 +- lib-network/include/net.h | 2 +- lib-network/src/linux/networktcp.cpp | 2 +- lib-network/src/net/tcp.cpp | 2 +- lib-remoteconfig/.cproject | 13 + .../.settings/language.settings.xml | 2 +- lib-remoteconfig/Makefile.Linux | 2 +- lib-remoteconfig/Rules.mk | 1 + .../http/content/generate_content | Bin 22080 -> 22136 bytes .../http/content/generate_json_switch | Bin 16528 -> 16528 bytes .../http/content/generate_json_switch.cpp | 3 +- lib-remoteconfig/http/content/json_switch.h | 1 + lib-remoteconfig/include/httpd/http.h | 4 +- .../include/httpd/httpdhandlerequest.h | 16 +- lib-remoteconfig/include/remoteconfigjson.h | 4 + .../src/httpd/get_file_content.cpp | 30 +- .../src/httpd/httpdhandlerequest.cpp | 300 ++++++++++-------- 18 files changed, 227 insertions(+), 159 deletions(-) mode change 100644 => 100755 lib-remoteconfig/Makefile.Linux diff --git a/lib-network/include/emac/network.h b/lib-network/include/emac/network.h index b06ea59e6..ffd368aef 100755 --- a/lib-network/include/emac/network.h +++ b/lib-network/include/emac/network.h @@ -224,7 +224,7 @@ class Network { return net::tcp_read(nHandleListen, ppBuffer, HandleConnection); } - void TcpWrite(const int32_t nHandleListen, const uint8_t *pBuffer, uint16_t nLength, const uint32_t HandleConnection) { + void TcpWrite(const int32_t nHandleListen, const uint8_t *pBuffer, uint32_t nLength, const uint32_t HandleConnection) { net::tcp_write(nHandleListen, pBuffer, nLength, HandleConnection); } diff --git a/lib-network/include/linux/network.h b/lib-network/include/linux/network.h index 331325f30..2df099687 100644 --- a/lib-network/include/linux/network.h +++ b/lib-network/include/linux/network.h @@ -212,7 +212,7 @@ class Network { int32_t TcpBegin(uint16_t nLocalPort); uint16_t TcpRead(const int32_t nHandle, const uint8_t **ppBuffer, uint32_t &HandleConnection); - void TcpWrite(const int32_t nHandle, const uint8_t *pBuffer, uint16_t nLength, const uint32_t HandleConnection); + void TcpWrite(const int32_t nHandle, const uint8_t *pBuffer, uint32_t nLength, const uint32_t HandleConnection); int32_t TcpEnd(const int32_t nHandle); private: diff --git a/lib-network/include/net.h b/lib-network/include/net.h index d9b688aec..a60df0048 100755 --- a/lib-network/include/net.h +++ b/lib-network/include/net.h @@ -71,7 +71,7 @@ void igmp_leave(uint32_t); int tcp_begin(const uint16_t); uint16_t tcp_read(const int32_t, const uint8_t **, uint32_t &); -void tcp_write(const int32_t, const uint8_t *, uint16_t, const uint32_t); +void tcp_write(const int32_t, const uint8_t *, uint32_t, const uint32_t); /** * Must be provided by the application diff --git a/lib-network/src/linux/networktcp.cpp b/lib-network/src/linux/networktcp.cpp index c76040a33..4d898ad99 100755 --- a/lib-network/src/linux/networktcp.cpp +++ b/lib-network/src/linux/networktcp.cpp @@ -189,7 +189,7 @@ uint16_t Network::TcpRead(const int32_t nHandle, const uint8_t **ppBuffer, uint3 return 0; } -void Network::TcpWrite(const int32_t nHandle, const uint8_t *pBuffer, uint16_t nLength, const uint32_t HandleConnectionIndex) { +void Network::TcpWrite(const int32_t nHandle, const uint8_t *pBuffer, uint32_t nLength, const uint32_t HandleConnectionIndex) { assert(nHandle < MAX_PORTS_ALLOWED); DEBUG_PRINTF("Write client on fd %d [%u]", poll_set[nHandle][HandleConnectionIndex].fd, HandleConnectionIndex); diff --git a/lib-network/src/net/tcp.cpp b/lib-network/src/net/tcp.cpp index 9ff4a50b5..c219828b1 100644 --- a/lib-network/src/net/tcp.cpp +++ b/lib-network/src/net/tcp.cpp @@ -1168,7 +1168,7 @@ static void _write(struct tcb *pTCB, const uint8_t *pBuffer, const uint32_t nLen pTCB->SND.WND -= nLength; } -void tcp_write(const int32_t nHandleListen, const uint8_t *pBuffer, uint16_t nLength, uint32_t nHandleConnection) { +void tcp_write(const int32_t nHandleListen, const uint8_t *pBuffer, uint32_t nLength, uint32_t nHandleConnection) { assert(nHandleListen >= 0); assert(nHandleListen < TCP_MAX_PORTS_ALLOWED); assert(pBuffer != nullptr); diff --git a/lib-remoteconfig/.cproject b/lib-remoteconfig/.cproject index 02488039a..d0752ea05 100644 --- a/lib-remoteconfig/.cproject +++ b/lib-remoteconfig/.cproject @@ -77,6 +77,8 @@ + + @@ -170,6 +172,8 @@ + + @@ -311,6 +315,9 @@ + + + @@ -379,6 +383,8 @@ + + @@ -399,6 +407,8 @@ + + diff --git a/lib-artnet/.settings/language.settings.xml b/lib-artnet/.settings/language.settings.xml index 6bfe2d1cb..c2e9d316b 100644 --- a/lib-artnet/.settings/language.settings.xml +++ b/lib-artnet/.settings/language.settings.xml @@ -26,7 +26,7 @@ - + diff --git a/lib-artnet/include/artnet.h b/lib-artnet/include/artnet.h index 6fa60b3c9..4e17fb1a0 100644 --- a/lib-artnet/include/artnet.h +++ b/lib-artnet/include/artnet.h @@ -199,6 +199,14 @@ struct PortCommand { static constexpr uint8_t RDM_DISABLE3 = 0xd3; ///< Disable RDM on output port 3 }; +struct TodControlCommand { + static constexpr uint8_t ATC_NONE = 0x00; ///< No action. + static constexpr uint8_t ATC_FLUSH = 0x01; ///< The port flushes its TOD and instigates full discovery. + static constexpr uint8_t ATC_END = 0x02; ///< The port ends current discovery but does not flush ToD. + static constexpr uint8_t ATC_INCON = 0x03; ///< The port enables incremental discovery. + static constexpr uint8_t ATC_INCOFF = 0x04; ///< The port disables incremental discovery. +}; + struct Program { static constexpr uint8_t NO_CHANGE = 0x7F; static constexpr uint8_t DEFAULTS = 0x00; @@ -239,16 +247,19 @@ struct Status2 { }; struct Status3 { - static constexpr uint8_t NETWORKLOSS_MASK = (3U << 6); ///< bit 76 - static constexpr uint8_t NETWORKLOSS_LAST_STATE = (0 << 6); ///< bit 76 = 00 If network data is lost, it will hold last state - static constexpr uint8_t NETWORKLOSS_OFF_STATE = (1U << 6); ///< bit 76 = 01 If network data is lost, it will set all outputs to off state - static constexpr uint8_t NETWORKLOSS_ON_STATE = (2U << 6); ///< bit 76 = 10 If network data is lost, it will set all outputs to full on - static constexpr uint8_t NETWORKLOSS_PLAYBACK = (3U << 6); ///< bit 76 = 11 If network data is lost, it will playback the fail-over scene - static constexpr uint8_t FAILSAFE_NO_CONTROL = (0 << 5); ///< bit 5 = 0 Node is not able to control failsafe mode by ArtCommand - static constexpr uint8_t FAILSAFE_CONTROL = (1U << 5); ///< bit 5 = 1 Node is able to control failsafe mode by ArtCommand - static constexpr uint8_t SUPPORTS_LLRP = (1U << 4); ///< bit 4 = 1 Node supports LLRP (Low Level Recovery Protocol - static constexpr uint8_t OUTPUT_NO_SWITCH = (0 << 3); ///< bit 3 = 0 Outputs cannot be switched to an input - static constexpr uint8_t OUTPUT_SWITCH = (1U << 3); ///< bit 3 = 1 Outputs can be switched to an input + static constexpr uint8_t NETWORKLOSS_MASK = (3U << 6); ///< bit 76 + static constexpr uint8_t NETWORKLOSS_LAST_STATE = (0 << 6); ///< bit 76 = 00 If network data is lost, it will hold last state + static constexpr uint8_t NETWORKLOSS_OFF_STATE = (1U << 6); ///< bit 76 = 01 If network data is lost, it will set all outputs to off state + static constexpr uint8_t NETWORKLOSS_ON_STATE = (2U << 6); ///< bit 76 = 10 If network data is lost, it will set all outputs to full on + static constexpr uint8_t NETWORKLOSS_PLAYBACK = (3U << 6); ///< bit 76 = 11 If network data is lost, it will playback the fail-over scene + static constexpr uint8_t FAILSAFE_NO_CONTROL = (0 << 5); ///< bit 5 = 0 Node is not able to control failsafe mode by ArtCommand + static constexpr uint8_t FAILSAFE_CONTROL = (1U << 5); ///< bit 5 = 1 Node is able to control failsafe mode by ArtCommand + static constexpr uint8_t SUPPORTS_LLRP = (1U << 4); ///< bit 4 = 1 Node supports LLRP (Low Level Recovery Protocol + static constexpr uint8_t OUTPUT_NO_SWITCH = (0 << 3); ///< bit 3 = 0 Outputs cannot be switched to an input + static constexpr uint8_t OUTPUT_SWITCH = (1U << 3); ///< bit 3 = 1 Outputs can be switched to an input + static constexpr uint8_t SUPPORTS_RDMNET = (1U << 2); ///< bit 2 = 1 Node supports RDMnet + static constexpr uint8_t SUPPORTS_BACKGROUNDQUEUE = (1U << 1); ///< bit 1 = 1 BackgroundQueue is supported + static constexpr uint8_t SUPPORTS_BACKGROUNDDISCOVERY = (1U << 0); ///< bit 0 = 1 Programmable background discovery is supported. }; struct Flags { @@ -281,6 +292,10 @@ struct GoodOutputB { static constexpr uint8_t RDM_ENABLED = (0 << 7); ///< bit 7 = 0 RDM is enabled. static constexpr uint8_t STYLE_CONSTANT = (1U << 6); ///< bit 6 = 1 Output style is continuous. static constexpr uint8_t STYLE_DELTA = (0 << 6); ///< bit 6 = 0 Output style is delta. + static constexpr uint8_t DISCOVERY_NOT_RUNNING = (1U << 5); ///< bit 5 = 1 Discovery is currently not running. + static constexpr uint8_t DISCOVERY_IS_RUNNING = (0 << 5); ///< bit 5 = 0 Discovery is currently running. + static constexpr uint8_t DISCOVERY_DISABLED = (1U << 4); ///< bit 4 = 1 Background discovery is disabled. + static constexpr uint8_t DISCOVERY_ENABLED = (0 << 4); ///< bit 4 = 0 Background Discovery is enabled. }; struct GoodInput { @@ -401,7 +416,15 @@ struct ArtPollReply { uint8_t GoodOutputB[artnet::PORTS]; ///< This array defines output status of the node. uint8_t Status3; ///< General Status register uint8_t DefaultUidResponder[6]; ///< RDMnet & LLRP UID - uint8_t Filler[15]; ///< Transmit as zero. For future expansion. + uint8_t UserHi; ///< Available for user specific data + uint8_t UserLo; ///< Available for user specific data + uint8_t RefreshRateHi; ///< Hi byte of RefreshRate + uint8_t RefreshRateLo; ///< Lo Byte of RefreshRate. + ///< RefreshRate allows the device to specify the maximum refresh rate, expressed in Hz, at which it can process ArtDmx. + ///< This is designed to allow refresh rates above DMX512 rates, for gateways that implement other protocols such as SPI. + ///< A value of 0 to 44 represents the maximum DMX512 rate of 44Hz. + uint8_t BackgroundQueuePolicy; ///< The BackgroundQueuePolicy defines the method by with the node retrieves STATUS_MESSAGE and QUEUED_MESSAGE pids from the connected RDM devices. + uint8_t Filler[10]; ///< Transmit as zero. For future expansion. }PACKED; /** diff --git a/lib-artnet/include/artnetnode.h b/lib-artnet/include/artnetnode.h index 10a8eead8..19704fd7a 100755 --- a/lib-artnet/include/artnetnode.h +++ b/lib-artnet/include/artnetnode.h @@ -395,6 +395,12 @@ class ArtNetNode { return !((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) == artnet::GoodOutputB::RDM_DISABLED); } + void SetRdmDiscovery(const uint32_t nPortIndex, const bool bEnable); + bool GetRdmDiscovery(const uint32_t nPortIndex) const { + assert(nPortIndex < artnetnode::MAX_PORTS); + return !((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::DISCOVERY_DISABLED) == artnet::GoodOutputB::DISCOVERY_DISABLED); + } + #if defined (RDM_CONTROLLER) void SetRdmController(ArtNetRdmController *pArtNetRdmController, const bool doEnable = true); @@ -425,7 +431,11 @@ class ArtNetNode { bool RdmIsRunning(const uint32_t nPortIndex, bool& bIsIncremental) { uint32_t nRdmnPortIndex; if (m_pArtNetRdmController->IsRunning(nRdmnPortIndex, bIsIncremental)) { - return (nRdmnPortIndex == nPortIndex); + const auto isRunning = (nRdmnPortIndex == nPortIndex); + if (isRunning) { + assert(!((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::DISCOVERY_NOT_RUNNING) == artnet::GoodOutputB::DISCOVERY_NOT_RUNNING)); + } + return isRunning; } return false; @@ -646,7 +656,10 @@ class ArtNetNode { #if defined (RDM_CONTROLLER) bool RdmDiscoveryRun() { - if ((GetPortDirection(m_State.rdm.nDiscoveryPortIndex) == lightset::PortDir::OUTPUT) && (GetRdm(m_State.rdm.nDiscoveryPortIndex))) { + if ((GetPortDirection(m_State.rdm.nDiscoveryPortIndex) == lightset::PortDir::OUTPUT) + && (GetRdm(m_State.rdm.nDiscoveryPortIndex)) + && (GetRdmDiscovery(m_State.rdm.nDiscoveryPortIndex))) + { uint32_t nPortIndex; bool bIsIncremental; @@ -663,6 +676,8 @@ class ArtNetNode { m_pLightSet->Start(nPortIndex); } + m_OutputPort[m_State.rdm.nDiscoveryPortIndex].GoodOutputB |= artnet::GoodOutputB::DISCOVERY_NOT_RUNNING; + m_State.rdm.nDiscoveryPortIndex++; return (m_State.rdm.nDiscoveryPortIndex != artnetnode::MAX_PORTS); } @@ -670,6 +685,7 @@ class ArtNetNode { if (!m_pArtNetRdmController->IsRunning(nPortIndex, bIsIncremental)) { DEBUG_PRINTF("RDM Discovery Incremental -> %u", static_cast(m_State.rdm.nDiscoveryPortIndex)); m_pArtNetRdmController->Incremental(m_State.rdm.nDiscoveryPortIndex); + m_OutputPort[m_State.rdm.nDiscoveryPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::DISCOVERY_NOT_RUNNING); } return true; diff --git a/lib-artnet/include/artnetrdmcontroller.h b/lib-artnet/include/artnetrdmcontroller.h index 73a5c1b15..437c0e1f3 100755 --- a/lib-artnet/include/artnetrdmcontroller.h +++ b/lib-artnet/include/artnetrdmcontroller.h @@ -61,6 +61,19 @@ class ArtNetRdmController final: public RDMDeviceController, RDMDiscovery { DEBUG_EXIT } + void Stop(const uint32_t nPortIndex) { + DEBUG_ENTRY + assert(nPortIndex < artnetnode::MAX_PORTS); + bool bIsIncremental; + uint32_t _nPortIndex; + if (IsRunning(_nPortIndex, bIsIncremental)) { + if (_nPortIndex == nPortIndex) { + RDMDiscovery::Stop(); + } + } + DEBUG_EXIT + } + uint32_t GetUidCount(const uint32_t nPortIndex) { assert(nPortIndex < artnetnode::MAX_PORTS); return m_pRDMTod[nPortIndex].GetUidCount(); diff --git a/lib-artnet/src/node/artnetnode.cpp b/lib-artnet/src/node/artnetnode.cpp index 0c5b113c1..13f841249 100755 --- a/lib-artnet/src/node/artnetnode.cpp +++ b/lib-artnet/src/node/artnetnode.cpp @@ -113,7 +113,7 @@ ArtNetNode::ArtNetNode() { memset(&m_OutputPort[nPortIndex], 0, sizeof(struct artnetnode::OutputPort)); m_OutputPort[nPortIndex].SourceA.nPhysical = 0x100; m_OutputPort[nPortIndex].SourceB.nPhysical = 0x100; - m_OutputPort[nPortIndex].GoodOutputB = artnet::GoodOutputB::RDM_DISABLED; + m_OutputPort[nPortIndex].GoodOutputB = artnet::GoodOutputB::RDM_DISABLED | artnet::GoodOutputB::DISCOVERY_NOT_RUNNING; memset(&m_InputPort[nPortIndex], 0, sizeof(struct artnetnode::InputPort)); m_InputPort[nPortIndex].nDestinationIp = Network::Get()->GetBroadcastIp(); } @@ -187,7 +187,7 @@ void ArtNetNode::Start() { /* * Status 3 */ - m_ArtPollReply.Status3 = artnet::Status3::NETWORKLOSS_LAST_STATE | artnet::Status3::FAILSAFE_CONTROL; + m_ArtPollReply.Status3 = artnet::Status3::NETWORKLOSS_LAST_STATE | artnet::Status3::FAILSAFE_CONTROL | artnet::Status3::SUPPORTS_BACKGROUNDDISCOVERY; #if defined (ARTNET_HAVE_DMXIN) m_ArtPollReply.Status3 |= artnet::Status3::OUTPUT_SWITCH; #endif diff --git a/lib-artnet/src/node/artnetnodehandlepoll.cpp b/lib-artnet/src/node/artnetnodehandlepoll.cpp index 9ea3926c2..2e630d53e 100644 --- a/lib-artnet/src/node/artnetnodehandlepoll.cpp +++ b/lib-artnet/src/node/artnetnodehandlepoll.cpp @@ -130,7 +130,12 @@ void ArtNetNode::SendPollRelply(const uint32_t nBindIndex, const uint32_t nDesti ProcessPollRelply(nPortIndex, nPortsInput, nPortsOutput); + const auto nRefreshRate = m_pLightSet->GetRefreshRate(); + m_ArtPollReply.RefreshRateLo = static_cast(nRefreshRate); + m_ArtPollReply.RefreshRateHi = static_cast(nRefreshRate >> 8); + m_ArtPollReply.NumPortsLo = static_cast(std::max(nPortsInput, nPortsOutput)); + m_State.ArtPollReplyCount++; uint8_t nSysNameLenght; diff --git a/lib-artnet/src/node/rdm/controller/handlerdm.cpp b/lib-artnet/src/node/rdm/controller/handlerdm.cpp index e6057fd30..a1d760073 100755 --- a/lib-artnet/src/node/rdm/controller/handlerdm.cpp +++ b/lib-artnet/src/node/rdm/controller/handlerdm.cpp @@ -46,7 +46,7 @@ void ArtNetNode::HandleTodControl() { const auto *const pArtTodControl = reinterpret_cast(m_pReceiveBuffer); - if (pArtTodControl->Command != 0x01) { // Not a AtcFlush + if (pArtTodControl->Command == artnet::TodControlCommand::ATC_NONE) { DEBUG_EXIT return; } @@ -58,12 +58,31 @@ void ArtNetNode::HandleTodControl() { continue; } - if ((m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) && - ((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) != artnet::GoodOutputB::RDM_DISABLED)) { - m_pArtNetRdmController->Full(nPortIndex); - } else if (m_Node.Port[nPortIndex].direction == lightset::PortDir::INPUT) { - m_pArtNetRdmController->TodReset(nPortIndex); - } + if ((m_Node.Port[nPortIndex].direction == lightset::PortDir::OUTPUT) && + ((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::RDM_DISABLED) != artnet::GoodOutputB::RDM_DISABLED)) { + switch (pArtTodControl->Command) { + case artnet::TodControlCommand::ATC_FLUSH: + m_pArtNetRdmController->Full(nPortIndex); + m_OutputPort[nPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::DISCOVERY_NOT_RUNNING); + break; + case artnet::TodControlCommand::ATC_END: + m_pArtNetRdmController->Stop(nPortIndex); + m_OutputPort[nPortIndex].GoodOutputB |= artnet::GoodOutputB::DISCOVERY_NOT_RUNNING; + break; + case artnet::TodControlCommand::ATC_INCON: + m_OutputPort[nPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::DISCOVERY_DISABLED); + break; + case artnet::TodControlCommand::ATC_INCOFF: + m_OutputPort[nPortIndex].GoodOutputB |= artnet::GoodOutputB::DISCOVERY_DISABLED; + break; + default: + break; + } + } else if (m_Node.Port[nPortIndex].direction == lightset::PortDir::INPUT) { + if (pArtTodControl->Command == artnet::TodControlCommand::ATC_FLUSH) { + m_pArtNetRdmController->TodReset(nPortIndex); + } + } } DEBUG_EXIT diff --git a/lib-artnet/src/node/rdm/controller/json_get_portstatus.cpp b/lib-artnet/src/node/rdm/controller/json_get_portstatus.cpp index 43ab4a954..446a96a78 100755 --- a/lib-artnet/src/node/rdm/controller/json_get_portstatus.cpp +++ b/lib-artnet/src/node/rdm/controller/json_get_portstatus.cpp @@ -37,11 +37,15 @@ static uint32_t get_portstatus(const uint32_t nPortIndex, char *pOutBuffer, cons if (direction == lightset::PortDir::OUTPUT) { if (ArtNetNode::Get()->GetRdm(nPortIndex)) { - bool bIsIncremental; - if (ArtNetNode::Get()->RdmIsRunning(nPortIndex, bIsIncremental)) { - status = bIsIncremental ? "Incremental" : "Full"; + if (ArtNetNode::Get()->GetRdmDiscovery(nPortIndex)) { + bool bIsIncremental; + if (ArtNetNode::Get()->RdmIsRunning(nPortIndex, bIsIncremental)) { + status = bIsIncremental ? "Incremental" : "Full"; + } else { + status = "Idle"; + } } else { - status = "Idle"; + status = "Disabled"; } } else { return 0; diff --git a/lib-artnet/src/node/rdm/setrdm.cpp b/lib-artnet/src/node/rdm/setrdm.cpp index 79b661bdd..ffa774de6 100755 --- a/lib-artnet/src/node/rdm/setrdm.cpp +++ b/lib-artnet/src/node/rdm/setrdm.cpp @@ -54,3 +54,23 @@ void ArtNetNode::SetRdm(const uint32_t nPortIndex, const bool bEnable) { DEBUG_EXIT } + +void ArtNetNode::SetRdmDiscovery(const uint32_t nPortIndex, const bool bEnable) { + DEBUG_ENTRY + assert(nPortIndex < artnetnode::MAX_PORTS); + + const auto isEnabled = !((m_OutputPort[nPortIndex].GoodOutputB & artnet::GoodOutputB::DISCOVERY_DISABLED) == artnet::GoodOutputB::DISCOVERY_DISABLED); + + if (isEnabled == bEnable) { + DEBUG_EXIT + return; + } + + if (!bEnable) { + m_OutputPort[nPortIndex].GoodOutputB |= artnet::GoodOutputB::DISCOVERY_DISABLED; + } else { + m_OutputPort[nPortIndex].GoodOutputB &= static_cast(~artnet::GoodOutputB::DISCOVERY_DISABLED); + } + + DEBUG_EXIT +} diff --git a/lib-dmx/include/dmxsend.h b/lib-dmx/include/dmxsend.h index 7377695e9..ed44a85df 100755 --- a/lib-dmx/include/dmxsend.h +++ b/lib-dmx/include/dmxsend.h @@ -124,6 +124,10 @@ class DmxSend final: public LightSet { } #endif + uint32_t GetRefreshRate() override { + return 1000000U / Dmx::Get()->GetDmxPeriodTime(); + } + void Blackout([[maybe_unused]] bool bBlackout) override { Dmx::Get()->Blackout(); } From d4311a0ff6e860e13b8d3c06417e838a100949d6 Mon Sep 17 00:00:00 2001 From: Arjan van Vught Date: Fri, 30 Aug 2024 11:56:09 +0200 Subject: [PATCH 17/17] Updated SOFTWARE_VERSION[] --- .../.settings/language.settings.xml | 4 +- opi_dmx_monitor/include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- opi_dmx_usb_pro/include/software_version.h | 4 +- .../.settings/language.settings.xml | 28 +- opi_emac_artnet_dmx/Makefile.H3 | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 8 +- opi_emac_artnet_pixel/Makefile.H3 | 2 +- .../include/software_version.h | 4 +- opi_emac_artnet_pixel_dmx/.cproject | 459 +++++++++--------- .../.settings/language.settings.xml | 8 +- .../include/software_version.h | 4 +- opi_emac_artnet_pixel_dmx_multi/.cproject | 459 +++++++++--------- .../.settings/language.settings.xml | 8 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 8 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- opi_emac_e131_dmx/include/software_version.h | 4 +- .../.settings/language.settings.xml | 28 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 8 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 28 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 28 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 28 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 28 +- opi_emac_llrp_tftpd/Makefile.H3 | 13 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- opi_emac_ltc_smpte/include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- opi_emac_osc_dmx/include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 28 +- opi_emac_osc_pixel/include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- opi_midi_monitor/include/software_version.h | 4 +- .../.settings/language.settings.xml | 4 +- opi_rdm_responder/include/software_version.h | 4 +- .../.settings/language.settings.xml | 2 +- .../include/software_version.h | 4 +- 73 files changed, 688 insertions(+), 667 deletions(-) diff --git a/opi_dmx_monitor/.settings/language.settings.xml b/opi_dmx_monitor/.settings/language.settings.xml index a8d39501e..f59168be8 100644 --- a/opi_dmx_monitor/.settings/language.settings.xml +++ b/opi_dmx_monitor/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + @@ -17,7 +17,7 @@ - + diff --git a/opi_dmx_monitor/include/software_version.h b/opi_dmx_monitor/include/software_version.h index a23c61057..1e6e3d163 100644 --- a/opi_dmx_monitor/include/software_version.h +++ b/opi_dmx_monitor/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.6"; +constexpr char SOFTWARE_VERSION[] = "2.7"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_dmx_usb_pro/.settings/language.settings.xml b/opi_dmx_usb_pro/.settings/language.settings.xml index 11b75c55b..acb67b46e 100644 --- a/opi_dmx_usb_pro/.settings/language.settings.xml +++ b/opi_dmx_usb_pro/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_dmx_usb_pro/include/software_version.h b/opi_dmx_usb_pro/include/software_version.h index 7b3c1b895..3e246e5df 100644 --- a/opi_dmx_usb_pro/include/software_version.h +++ b/opi_dmx_usb_pro/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.7"; +constexpr char SOFTWARE_VERSION[] = "2.8"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_artnet_dmx/.settings/language.settings.xml b/opi_emac_artnet_dmx/.settings/language.settings.xml index 5c24e0b79..1181ae0f1 100644 --- a/opi_emac_artnet_dmx/.settings/language.settings.xml +++ b/opi_emac_artnet_dmx/.settings/language.settings.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opi_emac_artnet_dmx/Makefile.H3 b/opi_emac_artnet_dmx/Makefile.H3 index c753b7780..8ce9d0bf1 100644 --- a/opi_emac_artnet_dmx/Makefile.H3 +++ b/opi_emac_artnet_dmx/Makefile.H3 @@ -23,7 +23,7 @@ DEFINES+=ENABLE_HTTPD ENABLE_CONTENT DEFINES+=DISABLE_RTC -#DEFINES+=NDEBUG +DEFINES+=NDEBUG LIBS= diff --git a/opi_emac_artnet_dmx/include/software_version.h b/opi_emac_artnet_dmx/include/software_version.h index 9a19f9fd0..f36d12ec5 100644 --- a/opi_emac_artnet_dmx/include/software_version.h +++ b/opi_emac_artnet_dmx/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "4.6"; +constexpr char SOFTWARE_VERSION[] = "4.7"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_artnet_dmx_multi/.settings/language.settings.xml b/opi_emac_artnet_dmx_multi/.settings/language.settings.xml index a1d5f6898..1181ae0f1 100644 --- a/opi_emac_artnet_dmx_multi/.settings/language.settings.xml +++ b/opi_emac_artnet_dmx_multi/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_artnet_dmx_multi/include/software_version.h b/opi_emac_artnet_dmx_multi/include/software_version.h index a61c1f2c0..03b15753c 100644 --- a/opi_emac_artnet_dmx_multi/include/software_version.h +++ b/opi_emac_artnet_dmx_multi/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "3.9"; +constexpr char SOFTWARE_VERSION[] = "4.0"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_artnet_monitor/.settings/language.settings.xml b/opi_emac_artnet_monitor/.settings/language.settings.xml index a1d5f6898..1181ae0f1 100644 --- a/opi_emac_artnet_monitor/.settings/language.settings.xml +++ b/opi_emac_artnet_monitor/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_artnet_monitor/include/software_version.h b/opi_emac_artnet_monitor/include/software_version.h index d9dc8804b..613f7331d 100644 --- a/opi_emac_artnet_monitor/include/software_version.h +++ b/opi_emac_artnet_monitor/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "3.0"; +constexpr char SOFTWARE_VERSION[] = "3.1"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_artnet_pixel/.settings/language.settings.xml b/opi_emac_artnet_pixel/.settings/language.settings.xml index d605d1bf0..687bfa1b8 100644 --- a/opi_emac_artnet_pixel/.settings/language.settings.xml +++ b/opi_emac_artnet_pixel/.settings/language.settings.xml @@ -2,13 +2,13 @@ - + + + + - - - diff --git a/opi_emac_artnet_pixel/Makefile.H3 b/opi_emac_artnet_pixel/Makefile.H3 index 2b69f6ed9..beba8120e 100644 --- a/opi_emac_artnet_pixel/Makefile.H3 +++ b/opi_emac_artnet_pixel/Makefile.H3 @@ -25,7 +25,7 @@ DEFINES+=DISABLE_RTC DEFINES+=DEBUG_PIXEL DEFINES+=DEBUG_STACK DEFINES+=DEBUG_HEAP -#DEFINES+=NDEBUG +DEFINES+=NDEBUG LIBS= diff --git a/opi_emac_artnet_pixel/include/software_version.h b/opi_emac_artnet_pixel/include/software_version.h index 41fda7df9..5562eb079 100644 --- a/opi_emac_artnet_pixel/include/software_version.h +++ b/opi_emac_artnet_pixel/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "4.7"; +constexpr char SOFTWARE_VERSION[] = "4.8"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_artnet_pixel_dmx/.cproject b/opi_emac_artnet_pixel_dmx/.cproject index a5e63b8cb..286d7282a 100755 --- a/opi_emac_artnet_pixel_dmx/.cproject +++ b/opi_emac_artnet_pixel_dmx/.cproject @@ -1,225 +1,236 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opi_emac_artnet_pixel_dmx/.settings/language.settings.xml b/opi_emac_artnet_pixel_dmx/.settings/language.settings.xml index 0f29dc624..6df7f0b3a 100755 --- a/opi_emac_artnet_pixel_dmx/.settings/language.settings.xml +++ b/opi_emac_artnet_pixel_dmx/.settings/language.settings.xml @@ -2,13 +2,13 @@ - + + + + - - - diff --git a/opi_emac_artnet_pixel_dmx/include/software_version.h b/opi_emac_artnet_pixel_dmx/include/software_version.h index f8dfd1cb7..767352b85 100644 --- a/opi_emac_artnet_pixel_dmx/include/software_version.h +++ b/opi_emac_artnet_pixel_dmx/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.1"; +constexpr char SOFTWARE_VERSION[] = "2.2"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_artnet_pixel_dmx_multi/.cproject b/opi_emac_artnet_pixel_dmx_multi/.cproject index 7b5dad594..25dca63e4 100755 --- a/opi_emac_artnet_pixel_dmx_multi/.cproject +++ b/opi_emac_artnet_pixel_dmx_multi/.cproject @@ -1,225 +1,236 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opi_emac_artnet_pixel_dmx_multi/.settings/language.settings.xml b/opi_emac_artnet_pixel_dmx_multi/.settings/language.settings.xml index 8a478e2db..33b55b219 100755 --- a/opi_emac_artnet_pixel_dmx_multi/.settings/language.settings.xml +++ b/opi_emac_artnet_pixel_dmx_multi/.settings/language.settings.xml @@ -2,13 +2,13 @@ - + + + + - - - diff --git a/opi_emac_artnet_pixel_dmx_multi/include/software_version.h b/opi_emac_artnet_pixel_dmx_multi/include/software_version.h index 9bc64c07a..70a7f41cb 100644 --- a/opi_emac_artnet_pixel_dmx_multi/include/software_version.h +++ b/opi_emac_artnet_pixel_dmx_multi/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.1"; +constexpr char SOFTWARE_VERSION[] = "2.2"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_artnet_pixel_multi/.settings/language.settings.xml b/opi_emac_artnet_pixel_multi/.settings/language.settings.xml index 51f1e42eb..072b44258 100644 --- a/opi_emac_artnet_pixel_multi/.settings/language.settings.xml +++ b/opi_emac_artnet_pixel_multi/.settings/language.settings.xml @@ -2,13 +2,13 @@ - + + + + - - - diff --git a/opi_emac_artnet_pixel_multi/include/software_version.h b/opi_emac_artnet_pixel_multi/include/software_version.h index c23d2bf70..2b5c09491 100644 --- a/opi_emac_artnet_pixel_multi/include/software_version.h +++ b/opi_emac_artnet_pixel_multi/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "3.2"; +constexpr char SOFTWARE_VERSION[] = "3.3"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_artnet_rdm_l6470/.settings/language.settings.xml b/opi_emac_artnet_rdm_l6470/.settings/language.settings.xml index a1d5f6898..1181ae0f1 100644 --- a/opi_emac_artnet_rdm_l6470/.settings/language.settings.xml +++ b/opi_emac_artnet_rdm_l6470/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_artnet_rdm_l6470/include/software_version.h b/opi_emac_artnet_rdm_l6470/include/software_version.h index e7299779f..5d0ab9767 100644 --- a/opi_emac_artnet_rdm_l6470/include/software_version.h +++ b/opi_emac_artnet_rdm_l6470/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.8"; +constexpr char SOFTWARE_VERSION[] = "2.9"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_artnet_rdm_pca9685/.settings/language.settings.xml b/opi_emac_artnet_rdm_pca9685/.settings/language.settings.xml index 974ade292..44ab003c7 100755 --- a/opi_emac_artnet_rdm_pca9685/.settings/language.settings.xml +++ b/opi_emac_artnet_rdm_pca9685/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_artnet_rdm_pca9685/include/software_version.h b/opi_emac_artnet_rdm_pca9685/include/software_version.h index 2721e611b..fb86beff7 100755 --- a/opi_emac_artnet_rdm_pca9685/include/software_version.h +++ b/opi_emac_artnet_rdm_pca9685/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2023-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "1.3"; +constexpr char SOFTWARE_VERSION[] = "1.4"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_artnet_serial/.settings/language.settings.xml b/opi_emac_artnet_serial/.settings/language.settings.xml index a1d5f6898..1181ae0f1 100644 --- a/opi_emac_artnet_serial/.settings/language.settings.xml +++ b/opi_emac_artnet_serial/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_artnet_serial/include/software_version.h b/opi_emac_artnet_serial/include/software_version.h index ceb9bc579..661f54433 100644 --- a/opi_emac_artnet_serial/include/software_version.h +++ b/opi_emac_artnet_serial/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.5"; +constexpr char SOFTWARE_VERSION[] = "2.6"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_ddp_pixel_dmx_multi/.settings/language.settings.xml b/opi_emac_ddp_pixel_dmx_multi/.settings/language.settings.xml index c4aa98fed..2ee77a4e4 100755 --- a/opi_emac_ddp_pixel_dmx_multi/.settings/language.settings.xml +++ b/opi_emac_ddp_pixel_dmx_multi/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_ddp_pixel_dmx_multi/include/software_version.h b/opi_emac_ddp_pixel_dmx_multi/include/software_version.h index bd472480e..c5152360d 100644 --- a/opi_emac_ddp_pixel_dmx_multi/include/software_version.h +++ b/opi_emac_ddp_pixel_dmx_multi/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.0"; +constexpr char SOFTWARE_VERSION[] = "2.1"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_ddp_pixel_multi/.settings/language.settings.xml b/opi_emac_ddp_pixel_multi/.settings/language.settings.xml index c4aa98fed..2ee77a4e4 100755 --- a/opi_emac_ddp_pixel_multi/.settings/language.settings.xml +++ b/opi_emac_ddp_pixel_multi/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_ddp_pixel_multi/include/software_version.h b/opi_emac_ddp_pixel_multi/include/software_version.h index f8dfd1cb7..767352b85 100644 --- a/opi_emac_ddp_pixel_multi/include/software_version.h +++ b/opi_emac_ddp_pixel_multi/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.1"; +constexpr char SOFTWARE_VERSION[] = "2.2"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_e131_artnet/.settings/language.settings.xml b/opi_emac_e131_artnet/.settings/language.settings.xml index c2745bd44..18c8d9d16 100644 --- a/opi_emac_e131_artnet/.settings/language.settings.xml +++ b/opi_emac_e131_artnet/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_e131_artnet/include/software_version.h b/opi_emac_e131_artnet/include/software_version.h index 3a3c6d5a0..80dc9877d 100644 --- a/opi_emac_e131_artnet/include/software_version.h +++ b/opi_emac_e131_artnet/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2020-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.7"; +constexpr char SOFTWARE_VERSION[] = "2.8"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_e131_dmx/.settings/language.settings.xml b/opi_emac_e131_dmx/.settings/language.settings.xml index c2745bd44..18c8d9d16 100644 --- a/opi_emac_e131_dmx/.settings/language.settings.xml +++ b/opi_emac_e131_dmx/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_e131_dmx/include/software_version.h b/opi_emac_e131_dmx/include/software_version.h index d3edd1224..a5522bb98 100644 --- a/opi_emac_e131_dmx/include/software_version.h +++ b/opi_emac_e131_dmx/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "4.2"; +constexpr char SOFTWARE_VERSION[] = "4.3"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_e131_dmx_multi/.settings/language.settings.xml b/opi_emac_e131_dmx_multi/.settings/language.settings.xml index db1114fcb..18c8d9d16 100644 --- a/opi_emac_e131_dmx_multi/.settings/language.settings.xml +++ b/opi_emac_e131_dmx_multi/.settings/language.settings.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opi_emac_e131_dmx_multi/include/software_version.h b/opi_emac_e131_dmx_multi/include/software_version.h index 925e00fbe..d25e610ac 100644 --- a/opi_emac_e131_dmx_multi/include/software_version.h +++ b/opi_emac_e131_dmx_multi/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "3.3"; +constexpr char SOFTWARE_VERSION[] = "3.4"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_e131_monitor/.settings/language.settings.xml b/opi_emac_e131_monitor/.settings/language.settings.xml index c2745bd44..18c8d9d16 100644 --- a/opi_emac_e131_monitor/.settings/language.settings.xml +++ b/opi_emac_e131_monitor/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_e131_monitor/include/software_version.h b/opi_emac_e131_monitor/include/software_version.h index d9dc8804b..613f7331d 100644 --- a/opi_emac_e131_monitor/include/software_version.h +++ b/opi_emac_e131_monitor/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "3.0"; +constexpr char SOFTWARE_VERSION[] = "3.1"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_e131_pixel/.settings/language.settings.xml b/opi_emac_e131_pixel/.settings/language.settings.xml index 6ebcd02cd..f98e6b990 100644 --- a/opi_emac_e131_pixel/.settings/language.settings.xml +++ b/opi_emac_e131_pixel/.settings/language.settings.xml @@ -2,13 +2,13 @@ - + + + + - - - diff --git a/opi_emac_e131_pixel/include/software_version.h b/opi_emac_e131_pixel/include/software_version.h index 2f7e933bf..3fd825717 100644 --- a/opi_emac_e131_pixel/include/software_version.h +++ b/opi_emac_e131_pixel/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "4.3"; +constexpr char SOFTWARE_VERSION[] = "4.4"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_e131_pixel_dmx/.settings/language.settings.xml b/opi_emac_e131_pixel_dmx/.settings/language.settings.xml index 24da222f5..afc2c550e 100755 --- a/opi_emac_e131_pixel_dmx/.settings/language.settings.xml +++ b/opi_emac_e131_pixel_dmx/.settings/language.settings.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opi_emac_e131_pixel_dmx/include/software_version.h b/opi_emac_e131_pixel_dmx/include/software_version.h index f8dfd1cb7..767352b85 100644 --- a/opi_emac_e131_pixel_dmx/include/software_version.h +++ b/opi_emac_e131_pixel_dmx/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.1"; +constexpr char SOFTWARE_VERSION[] = "2.2"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_e131_pixel_dmx_multi/.settings/language.settings.xml b/opi_emac_e131_pixel_dmx_multi/.settings/language.settings.xml index 4ee141130..9206d991a 100755 --- a/opi_emac_e131_pixel_dmx_multi/.settings/language.settings.xml +++ b/opi_emac_e131_pixel_dmx_multi/.settings/language.settings.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opi_emac_e131_pixel_dmx_multi/include/software_version.h b/opi_emac_e131_pixel_dmx_multi/include/software_version.h index f8dfd1cb7..767352b85 100644 --- a/opi_emac_e131_pixel_dmx_multi/include/software_version.h +++ b/opi_emac_e131_pixel_dmx_multi/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2021-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.1"; +constexpr char SOFTWARE_VERSION[] = "2.2"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_e131_pixel_multi/.settings/language.settings.xml b/opi_emac_e131_pixel_multi/.settings/language.settings.xml index abb930d82..f6b801d90 100644 --- a/opi_emac_e131_pixel_multi/.settings/language.settings.xml +++ b/opi_emac_e131_pixel_multi/.settings/language.settings.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opi_emac_e131_pixel_multi/include/software_version.h b/opi_emac_e131_pixel_multi/include/software_version.h index c23d2bf70..2b5c09491 100644 --- a/opi_emac_e131_pixel_multi/include/software_version.h +++ b/opi_emac_e131_pixel_multi/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "3.2"; +constexpr char SOFTWARE_VERSION[] = "3.3"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_llrp_tftpd/.settings/language.settings.xml b/opi_emac_llrp_tftpd/.settings/language.settings.xml index ff0787730..85b17cef6 100644 --- a/opi_emac_llrp_tftpd/.settings/language.settings.xml +++ b/opi_emac_llrp_tftpd/.settings/language.settings.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opi_emac_llrp_tftpd/Makefile.H3 b/opi_emac_llrp_tftpd/Makefile.H3 index fcf48330a..a0ed3c50c 100644 --- a/opi_emac_llrp_tftpd/Makefile.H3 +++ b/opi_emac_llrp_tftpd/Makefile.H3 @@ -16,14 +16,13 @@ DEFINES+=DEBUG_HEAP #DEFINES+=DEBUG_NET_UDP #DEFINES+=DEBUG_NET_ARP #DEFINES+=DEBUG_NET_ACD -DEFINES+=DEBUG_NET_DHCP -DEFINES+=DEBUG_NET_NETIF -DEFINES+=DEBUG_NET_NET -DEFINES+=DEBUG_NETWORK +#DEFINES+=DEBUG_NET_DHCP +#DEFINES+=DEBUG_NET_NETIF +#DEFINES+=DEBUG_NET_NET +#DEFINES+=DEBUG_NETWORK +#DEFINES+=DEBUG_RDM_LLRP -DEFINES+=DEBUG_RDM_LLRP - -#DEFINES+=NDEBUG +DEFINES+=NDEBUG LIBS= diff --git a/opi_emac_llrp_tftpd/include/software_version.h b/opi_emac_llrp_tftpd/include/software_version.h index e7299779f..5d0ab9767 100755 --- a/opi_emac_llrp_tftpd/include/software_version.h +++ b/opi_emac_llrp_tftpd/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.8"; +constexpr char SOFTWARE_VERSION[] = "2.9"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_ltc_smpte/.settings/language.settings.xml b/opi_emac_ltc_smpte/.settings/language.settings.xml index 11b75c55b..acb67b46e 100644 --- a/opi_emac_ltc_smpte/.settings/language.settings.xml +++ b/opi_emac_ltc_smpte/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_ltc_smpte/include/software_version.h b/opi_emac_ltc_smpte/include/software_version.h index 11d039520..1b93e9d9a 100644 --- a/opi_emac_ltc_smpte/include/software_version.h +++ b/opi_emac_ltc_smpte/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "4.5"; +constexpr char SOFTWARE_VERSION[] = "4.6"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_osc_client/.settings/language.settings.xml b/opi_emac_osc_client/.settings/language.settings.xml index 0d35fb0c0..41450214c 100644 --- a/opi_emac_osc_client/.settings/language.settings.xml +++ b/opi_emac_osc_client/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_osc_client/include/software_version.h b/opi_emac_osc_client/include/software_version.h index 3a829de9a..d62e76e4b 100644 --- a/opi_emac_osc_client/include/software_version.h +++ b/opi_emac_osc_client/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.9"; +constexpr char SOFTWARE_VERSION[] = "3.0"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_osc_dmx/.settings/language.settings.xml b/opi_emac_osc_dmx/.settings/language.settings.xml index 0d35fb0c0..41450214c 100644 --- a/opi_emac_osc_dmx/.settings/language.settings.xml +++ b/opi_emac_osc_dmx/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_osc_dmx/include/software_version.h b/opi_emac_osc_dmx/include/software_version.h index 925e00fbe..d25e610ac 100644 --- a/opi_emac_osc_dmx/include/software_version.h +++ b/opi_emac_osc_dmx/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "3.3"; +constexpr char SOFTWARE_VERSION[] = "3.4"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_osc_monitor/.settings/language.settings.xml b/opi_emac_osc_monitor/.settings/language.settings.xml index 0d35fb0c0..41450214c 100644 --- a/opi_emac_osc_monitor/.settings/language.settings.xml +++ b/opi_emac_osc_monitor/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_osc_monitor/include/software_version.h b/opi_emac_osc_monitor/include/software_version.h index d9dc8804b..613f7331d 100644 --- a/opi_emac_osc_monitor/include/software_version.h +++ b/opi_emac_osc_monitor/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "3.0"; +constexpr char SOFTWARE_VERSION[] = "3.1"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_osc_pixel/.settings/language.settings.xml b/opi_emac_osc_pixel/.settings/language.settings.xml index f50caea2a..41450214c 100644 --- a/opi_emac_osc_pixel/.settings/language.settings.xml +++ b/opi_emac_osc_pixel/.settings/language.settings.xml @@ -1,15 +1,15 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/opi_emac_osc_pixel/include/software_version.h b/opi_emac_osc_pixel/include/software_version.h index 96b5efa25..4c9ec8e65 100644 --- a/opi_emac_osc_pixel/include/software_version.h +++ b/opi_emac_osc_pixel/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "3.5"; +constexpr char SOFTWARE_VERSION[] = "3.6"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_pp_pixel_multi/.settings/language.settings.xml b/opi_emac_pp_pixel_multi/.settings/language.settings.xml index c4aa98fed..2ee77a4e4 100755 --- a/opi_emac_pp_pixel_multi/.settings/language.settings.xml +++ b/opi_emac_pp_pixel_multi/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_pp_pixel_multi/include/software_version.h b/opi_emac_pp_pixel_multi/include/software_version.h index 064a6fce9..1eda41ac5 100644 --- a/opi_emac_pp_pixel_multi/include/software_version.h +++ b/opi_emac_pp_pixel_multi/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2022-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "1.7"; +constexpr char SOFTWARE_VERSION[] = "1.8"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_showfile_artnet/.settings/language.settings.xml b/opi_emac_showfile_artnet/.settings/language.settings.xml index 57d7d0996..8cc4991c1 100755 --- a/opi_emac_showfile_artnet/.settings/language.settings.xml +++ b/opi_emac_showfile_artnet/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_showfile_artnet/include/software_version.h b/opi_emac_showfile_artnet/include/software_version.h index 67dfa21a0..98022402d 100755 --- a/opi_emac_showfile_artnet/include/software_version.h +++ b/opi_emac_showfile_artnet/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "1.2"; +constexpr char SOFTWARE_VERSION[] = "1.3"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_emac_showfile_e131/.settings/language.settings.xml b/opi_emac_showfile_e131/.settings/language.settings.xml index 57d7d0996..8cc4991c1 100755 --- a/opi_emac_showfile_e131/.settings/language.settings.xml +++ b/opi_emac_showfile_e131/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_emac_showfile_e131/include/software_version.h b/opi_emac_showfile_e131/include/software_version.h index 67dfa21a0..98022402d 100755 --- a/opi_emac_showfile_e131/include/software_version.h +++ b/opi_emac_showfile_e131/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "1.2"; +constexpr char SOFTWARE_VERSION[] = "1.3"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_midi_monitor/.settings/language.settings.xml b/opi_midi_monitor/.settings/language.settings.xml index a8fb5fdb7..d75828d83 100644 --- a/opi_midi_monitor/.settings/language.settings.xml +++ b/opi_midi_monitor/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_midi_monitor/include/software_version.h b/opi_midi_monitor/include/software_version.h index e7299779f..5d0ab9767 100644 --- a/opi_midi_monitor/include/software_version.h +++ b/opi_midi_monitor/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.8"; +constexpr char SOFTWARE_VERSION[] = "2.9"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_rdm_responder/.settings/language.settings.xml b/opi_rdm_responder/.settings/language.settings.xml index 5d374ff29..e4dd18efe 100644 --- a/opi_rdm_responder/.settings/language.settings.xml +++ b/opi_rdm_responder/.settings/language.settings.xml @@ -4,8 +4,8 @@ - - + + diff --git a/opi_rdm_responder/include/software_version.h b/opi_rdm_responder/include/software_version.h index d4ef1d1d6..f3fd1eefc 100644 --- a/opi_rdm_responder/include/software_version.h +++ b/opi_rdm_responder/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2018-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.9"; +constexpr char SOFTWARE_VERSION[] = "3.0"; #endif /* SOFTWARE_VERSION_H_ */ diff --git a/opi_rdm_responder_l6470/.settings/language.settings.xml b/opi_rdm_responder_l6470/.settings/language.settings.xml index b4bf82e48..97757dcde 100644 --- a/opi_rdm_responder_l6470/.settings/language.settings.xml +++ b/opi_rdm_responder_l6470/.settings/language.settings.xml @@ -5,7 +5,7 @@ - + diff --git a/opi_rdm_responder_l6470/include/software_version.h b/opi_rdm_responder_l6470/include/software_version.h index 7b3c1b895..3e246e5df 100644 --- a/opi_rdm_responder_l6470/include/software_version.h +++ b/opi_rdm_responder_l6470/include/software_version.h @@ -2,7 +2,7 @@ * @file software_version.h * */ -/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@orangepi-dmx.nl +/* Copyright (C) 2019-2024 by Arjan van Vught mailto:info@gd32-dmx.org * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -26,6 +26,6 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -constexpr char SOFTWARE_VERSION[] = "2.7"; +constexpr char SOFTWARE_VERSION[] = "2.8"; #endif /* SOFTWARE_VERSION_H_ */