diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..67d95d7 --- /dev/null +++ b/.clang-format @@ -0,0 +1,135 @@ +--- +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: false +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: false +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: false +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: true + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 120 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + SortPriority: 0 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + SortPriority: 0 + - Regex: '.*' + Priority: 1 + SortPriority: 0 +IncludeIsMainRegex: '(Test)?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 2 +NamespaceIndentation: None +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 1000 +PointerAlignment: Right +ReflowComments: false +SortIncludes: true +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +Standard: Latest +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Never +... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..4349350 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,11 @@ +--- +Checks: 'clang-analyzer-*,bugprone-*,readability-*,cppcoreguidelines-*,-readability-avoid-const-params-in-decls,-cppcoreguidelines-avoid-non-const-global-variables,-bugprone-easily-swappable-parameters,-altera-*,-readability-uppercase-literal-suffix,-bugprone-branch-clone,-cppcoreguidelines-pro-*,-readability-function-cognitive-complexity,-cppcoreguidelines-avoid-magic-numbers,-clang-analyzer-security.insecureAPI.*' +WarningsAsErrors: '' +HeaderFilterRegex: '' +CheckOptions: + - key: readability-magic-numbers.IgnoredFloatingPointValues + value: '0.0;1.0;100.0;' + - key: readability-magic-numbers.IgnoredIntegerValues + value: '0;1;2;3;4;5;6;7;8;9;255;256;65535;15;4294967295' + - key: readability-braces-around-statements.ShortStatementLines + value: '2' diff --git a/.clangd b/.clangd new file mode 100644 index 0000000..ce466fa --- /dev/null +++ b/.clangd @@ -0,0 +1,5 @@ +--- +CompileFlags: + Add: + - "-I/home/dennisgunia/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/avr/include/" + - "-I" diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index a376df5..216715c 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -1,59 +1,22 @@ { - "env": { - "myIncludePath": ["${workspaceFolder}/include", "${workspaceFolder}/src"], - "myDefines": ["DEBUG", "MY_FEATURE=1"] - }, - "configurations": [ - { - "name": "Linux", - "compilerPath": "/usr/bin/avr-gcc", - "compilerArgs": ["-mmcu=atmega8", "-DF_CPU=16000000UL", "-Os"], - "intelliSenseMode": "linux-gcc-x86", - "includePath": ["${myIncludePath}", "/usr/include"], - "defines": ["${myDefines}"], - "cStandard": "gnu11", - "cppStandard": "gnu++14", - "configurationProvider": "ms-vscode.cmake-tools", - "forcedInclude": ["${workspaceFolder}/common.h"], - "compileCommands": "${workspaceFolder}/build/compile_commands.json", - "dotConfig": "${workspaceFolder}/.config", - "mergeConfigurations": true, - "customConfigurationVariables": { - "myVar": "myvalue" - }, - "browse": { - "path": ["${myIncludePath}", "/usr/include", "${workspaceFolder}"], - "limitSymbolsToIncludedHeaders": true, - "databaseFilename": "${workspaceFolder}/.vscode/browse.vc.db" - } - }, - { - "name": "Mac", - "compilerPath": "/usr/bin/clang", - "intelliSenseMode": "macos-clang-x64", - "includePath": ["${myIncludePath}"], - "defines": ["${myDefines}"], - "cStandard": "c11", - "cppStandard": "c++17", - "macFrameworkPath": ["/System/Library/Frameworks", "/Library/Frameworks"], - "browse": { - "path": ["${myIncludePath}", "${workspaceFolder}"] - } - }, - { - "name": "Win32", - "compilerPath": "C:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.28.29333/bin/Hostx64/x64/cl.exe", - "intelliSenseMode": "windows-msvc-x64", - "includePath": ["${myIncludePath}"], - "defines": ["${myDefines}", "_WINDOWS"], - "cStandard": "c17", - "cppStandard": "c++20", - "windowsSdkVersion": "10.0.19041.0", - "browse": { - "path": ["${myIncludePath}", "${workspaceFolder}"] - } - } - ], - "version": 4, - "enableConfigurationSquiggles": true - } \ No newline at end of file + "env": { + "arduino_path": "/home/dennisgunia/.arduino15/packages/arduino", + "arduino_avr_include2_path": "${env:arduino_path}/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/avr/include" + }, + "configurations": [ + { + "name": "linux-gcc-x64", + "compilerPath": "/usr/bin/gcc", + "includePath": [ + "${workspaceFolder}/**", + "~/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/avr/include" + ], + "defines": [], + "cStandard": "c11", + "cppStandard": "c++20", + "intelliSenseMode": "linux-gcc-x64" + } + ], + "version": 4, + "enableConfigurationSquiggles": true +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..207afe4 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "C/C++ Runner: Debug Session", + "type": "cppdbg", + "request": "launch", + "args": [], + "stopAtEntry": false, + "externalConsole": false, + "cwd": "/nas_projects/current/SplitFlapController/software/firmware_module/module_rev0/src", + "program": "/nas_projects/current/SplitFlapController/software/firmware_module/module_rev0/src/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..8e14467 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,62 @@ +{ + "C_Cpp_Runner.cCompilerPath": "gcc", + "C_Cpp_Runner.cppCompilerPath": "g++", + "C_Cpp_Runner.debuggerPath": "gdb", + "C_Cpp_Runner.cStandard": "c11", + "C_Cpp_Runner.cppStandard": "c++20", + "C_Cpp_Runner.msvcBatchPath": "", + "C_Cpp_Runner.useMsvc": false, + "C_Cpp_Runner.warnings": [ + "-Wall", + "-Wextra", + "-Wpedantic", + "-Wshadow", + "-Wformat=2", + "-Wcast-align", + "-Wconversion", + "-Wsign-conversion", + "-Wnull-dereference" + ], + "C_Cpp_Runner.msvcWarnings": [ + "/W4", + "/permissive-", + "/w14242", + "/w14287", + "/w14296", + "/w14311", + "/w14826", + "/w44062", + "/w44242", + "/w14905", + "/w14906", + "/w14263", + "/w44265", + "/w14928" + ], + "C_Cpp_Runner.enableWarnings": true, + "C_Cpp_Runner.warningsAsError": false, + "C_Cpp_Runner.compilerArgs": [], + "C_Cpp_Runner.linkerArgs": [], + "C_Cpp_Runner.includePaths": [ + "~/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/avr/include" + ], + "C_Cpp_Runner.includeSearch": [ + "*", + "**/*", + "~/.arduino15/packages/arduino/tools/avr-gcc/7.3.0-atmel3.6.1-arduino7/avr/include/**" + ], + "C_Cpp_Runner.excludeSearch": [ + "**/build", + "**/build/**", + "**/.*", + "**/.*/**", + "**/.vscode", + "**/.vscode/**" + ], + "C_Cpp_Runner.useAddressSanitizer": false, + "C_Cpp_Runner.useUndefinedSanitizer": false, + "C_Cpp_Runner.useLeakSanitizer": false, + "C_Cpp_Runner.showCompilationTime": false, + "C_Cpp_Runner.useLinkTimeOptimization": false, + "C_Cpp_Runner.msvcSecureNoWarnings": false +} \ No newline at end of file diff --git a/software/firmware_module/module_rev0/src/global.h b/software/firmware_module/module_rev0/src/global.h index 72f5d4f..583d6d9 100644 --- a/software/firmware_module/module_rev0/src/global.h +++ b/software/firmware_module/module_rev0/src/global.h @@ -12,7 +12,7 @@ #include #include #include - +#include // I/O Pin definition @@ -31,3 +31,28 @@ #define CONF_ADDR_OKAY 0x0004 #define CONF_ADDR_ADDR 0x0000 #define CONF_ADDR_OFFSET 0x0002 + +// Protocol definitions +#define PROTO_MAXPKGLEN 64 // maximum size of package in bytes + +// Commands +#define CMDB_SETVAL (uint8_t)0x10 +#define CMDB_SETVALR (uint8_t)0x11 +#define CMDB_EEPROMR (uint8_t)0xF0 +#define CMDB_EEPROMW (uint8_t)0xF1 +#define CMDB_GSTS (uint8_t)0xF8 +#define CMDB_PING (uint8_t)0xFE +#define CMDB_RESET (uint8_t)0x30 +#define CMDB_PWRON (uint8_t)0x21 +#define CMDB_RPWROFF (uint8_t)0x20 + +// Reply +#define CMDR_ERR_INVALID 0xEE +#define CMDR_ACK 0xAA +#define CMDR_PING 0xFF + +// Utility definitions +#define SHIFT_0B 0 +#define SHIFT_1B 8 +#define SHIFT_2B 16 +#define SHIFT_3B 24 \ No newline at end of file diff --git a/software/firmware_module/module_rev0/src/main.c b/software/firmware_module/module_rev0/src/main.c index 8c8c031..7ebf512 100644 --- a/software/firmware_module/module_rev0/src/main.c +++ b/software/firmware_module/module_rev0/src/main.c @@ -10,143 +10,173 @@ #include "mctrl.h" #include "rcount.h" #include "rs485.h" + uint16_t address = 0x0000; -int16_t calib_offset = 0x0000; +uint16_t calib_offset = 0x0000; -void eeprom_write_c(uint16_t address, uint8_t data) { - // disable interrupt - cli(); - while (EECR & (1 << EEWE)) - ; // wait until previous write is done - EEAR = address; - EEDR = data; - EECR |= (1 << EEMWE); // enable Master Write Enable - EECR |= (1 << EEWE); // write one - sei(); +void eeprom_write_c(uint16_t address, uint8_t data) +{ + // disable interrupt + cli(); + while (EECR & (1 << EEWE)) + ; // wait until previous write is done + EEAR = address; + EEDR = data; + EECR |= (1 << EEMWE); // enable Master Write Enable + EECR |= (1 << EEWE); // write one + sei(); } -uint8_t eeprom_read_c(uint16_t address) { - while (EECR & (1 << EEWE)) - ; // wait until previous write is done - EEAR = address; - EECR |= (1 << EERE); // read one - return EEDR; +uint8_t eeprom_read_c(uint16_t address) +{ + while (EECR & (1 << EEWE)) + ; // wait until previous write is done + EEAR = address; + EECR |= (1 << EERE); // read one + return EEDR; } -void initialSetup() { - wdt_disable(); - if (eeprom_read_c(CONF_ADDR_OKAY) == CONF_CONST_OKAY) { - uint8_t addrL = eeprom_read_c(CONF_ADDR_ADDR); - uint8_t addrH = eeprom_read_c(CONF_ADDR_ADDR + 1); - address = addrL | (addrH << 8); - uint8_t offsetL = eeprom_read_c(CONF_ADDR_OFFSET); - uint8_t offsetH = eeprom_read_c(CONF_ADDR_OFFSET + 1); - calib_offset = offsetL | (offsetH << 8); - } else { - eeprom_write_c(CONF_ADDR_ADDR, (uint8_t)0x00); - eeprom_write_c(CONF_ADDR_ADDR + 1, (uint8_t)0x00); - eeprom_write_c(CONF_ADDR_OFFSET, (uint8_t)0x00); - eeprom_write_c(CONF_ADDR_OFFSET + 1, (uint8_t)0x00); - eeprom_write_c(CONF_ADDR_OKAY, CONF_CONST_OKAY); - } -} - -void readCommand() { - char *payload = malloc(64); - uint8_t payload_len = sfbus_recv_frame(address, payload); - if (payload_len > 0) { - // read command byte - uint8_t opcode = *payload; - // parse commands - if (opcode == (uint8_t)0x10) { - // 0x1O = Set Digit - uint8_t targetDigit = *(payload + 1); - mctrl_set(targetDigit, 0); - } else if (opcode == (uint8_t)0x11) { - // 0x11 = Set Digit (full rotation) - uint8_t targetDigit = *(payload + 1); - mctrl_set(targetDigit, 1); - } else if (opcode == (uint8_t)0xF0) { - // 0xFO = READ EEPROM - uint8_t bytes = 5; - char *msg = malloc(bytes + 1); - *msg = 0xAA; - for (uint16_t i = 1; i < (uint16_t)bytes + 1; i++) { - *(msg + i) = eeprom_read_c(i - 1); - } - _delay_ms(2); - sfbus_send_frame(0xFFFF, msg, bytes + 1); - free(msg); - - } else if (opcode == (uint8_t)0xF1) { - // 0xF1 = WRITE EEPROM - eeprom_write_c(CONF_ADDR_OKAY, (char)0xFF); - for (uint16_t i = 0; i < 4; i++) { - eeprom_write_c(i, *(payload + 1 + i)); - } - eeprom_write_c(CONF_ADDR_OKAY, CONF_CONST_OKAY); - // respond with readout - uint8_t bytes = 5; - char *msg = malloc(bytes + 1); - *msg = 0xAA; - for (uint16_t i = 1; i < (uint16_t)bytes + 1; i++) { - *(msg + i) = eeprom_read_c(i - 1); - } - _delay_ms(2); - sfbus_send_frame(0xFFFF, msg, bytes + 1); - free(msg); - // now use new addr - uint8_t addrL = eeprom_read_c(CONF_ADDR_ADDR); - uint8_t addrH = eeprom_read_c(CONF_ADDR_ADDR + 1); - address = addrL | (addrH << 8); - } else if (opcode == (uint8_t)0xF8) { - // 0xF8 = Get Status - char *msg = malloc(7); - *msg = getSts(); - uint16_t voltage = getVoltage(); - *(msg + 2) = (voltage >> 0) & 0xFF; - *(msg + 1) = (voltage >> 8) & 0xFF; - uint32_t counter = rc_getCounter(); - *(msg + 6) = (counter >> 0) & 0xFF; - *(msg + 5) = (counter >> 8) & 0xFF; - *(msg + 4) = (counter >> 16) & 0xFF; - *(msg + 3) = (counter >> 24) & 0xFF; - _delay_ms(2); - sfbus_send_frame(0xFFFF, msg, 7); - free(msg); - } else if (opcode == (uint8_t)0xFE) { - // 0xFE = PING - char msg = 0xFF; - _delay_ms(2); - sfbus_send_frame(0xFFFF, &msg, 1); - } else if ((opcode & (uint8_t)0xFE) == (uint8_t)0x20) { - // 0x20 = poweroff; 0x21 is poweron - uint8_t state = opcode & (uint8_t)0x01; - mctrl_power(state); - - } else if (opcode == (uint8_t)0x30) { - // 0x30 = reset - do { - wdt_enable(WDTO_15MS); - for (;;) { - } - } while (0); - } else { - // invalid opcode - char msg = 0xEE; - _delay_ms(2); - sfbus_send_frame(0xFFFF, &msg, 1); +void initialSetup() +{ + wdt_disable(); + if (eeprom_read_c(CONF_ADDR_OKAY) == CONF_CONST_OKAY) + { + uint8_t addrL = eeprom_read_c(CONF_ADDR_ADDR); + uint8_t addrH = eeprom_read_c(CONF_ADDR_ADDR + 1); + address = addrL | (addrH << 8); + uint8_t offsetL = eeprom_read_c(CONF_ADDR_OFFSET); + uint8_t offsetH = eeprom_read_c(CONF_ADDR_OFFSET + 1); + calib_offset = (offsetL | (offsetH << 8)); + } + else + { + eeprom_write_c(CONF_ADDR_ADDR, (uint8_t)0x00); + eeprom_write_c(CONF_ADDR_ADDR + 1, (uint8_t)0x00); + eeprom_write_c(CONF_ADDR_OFFSET, (uint8_t)0x00); + eeprom_write_c(CONF_ADDR_OFFSET + 1, (uint8_t)0x00); + eeprom_write_c(CONF_ADDR_OKAY, CONF_CONST_OKAY); } - } - free(payload); } -int main() { - initialSetup(); - rs485_init(); - mctrl_init(); - - while (1 == 1) { - readCommand(); - } +void readCommand() +{ + char *payload = malloc(PROTO_MAXPKGLEN); + uint8_t payload_len = sfbus_recv_frame(address, payload); + if (payload_len > 0) + { + // read command byte + uint8_t opcode = *payload; + // parse commands + if (opcode == CMDB_SETVAL) + { + // 0x1O = Set Digit + uint8_t targetDigit = *(payload + 1); + mctrl_set(targetDigit, 0); + } + else if (opcode == CMDB_SETVALR) + { + // 0x11 = Set Digit (full rotation) + uint8_t targetDigit = *(payload + 1); + mctrl_set(targetDigit, 1); + } + else if (opcode == CMDB_EEPROMR) + { + // 0xFO = READ EEPROM + uint8_t bytes = 5; + char *msg = malloc(bytes + 1); + *msg = CMDR_ACK; + for (uint16_t i = 1; i < (uint16_t)bytes + 1; i++) + { + *(msg + i) = (char)eeprom_read_c(i - 1); + } + _delay_ms(2); + sfbus_send_frame(0xFFFF, msg, bytes + 1); + free(msg); + } + else if (opcode == CMDB_EEPROMW) + { + // 0xF1 = WRITE EEPROM + eeprom_write_c(CONF_ADDR_OKAY, (char)0xFF); + for (uint16_t i = 0; i < 4; i++) + { + eeprom_write_c(i, *(payload + 1 + i)); + } + eeprom_write_c(CONF_ADDR_OKAY, CONF_CONST_OKAY); + // respond with readout + uint8_t bytes = 5; + char *msg = malloc(bytes + 1); + *msg = CMDR_ACK; + for (uint16_t i = 1; i < (uint16_t)bytes + 1; i++) + { + *(msg + i) = (char)eeprom_read_c(i - 1); + } + _delay_ms(2); + sfbus_send_frame(0xFFFF, msg, bytes + 1); + free(msg); + // now use new addr + uint8_t addrL = eeprom_read_c(CONF_ADDR_ADDR); + uint8_t addrH = eeprom_read_c(CONF_ADDR_ADDR + 1); + address = addrL | (addrH << SHIFT_1B); + } + else if (opcode == CMDB_GSTS) + { + char *msg = malloc(7); + *msg = (char)getSts(); + uint16_t voltage = getVoltage(); + *(msg + 2) = (char)((voltage >> SHIFT_0B) & 0xFF); + *(msg + 1) = (char)((voltage >> SHIFT_1B) & 0xFF); + uint32_t counter = rc_getCounter(); + *(msg + 6) = (char)((counter >> SHIFT_0B) & 0xFF); + *(msg + 5) = (char)((counter >> SHIFT_1B) & 0xFF); + *(msg + 4) = (char)((counter >> SHIFT_2B) & 0xFF); + *(msg + 3) = (char)((counter >> SHIFT_3B) & 0xFF); + _delay_ms(2); + sfbus_send_frame(0xFFFF, msg, 7); + free(msg); + } + else if (opcode == CMDB_PING) + { + char msg = (char)CMDR_PING; + _delay_ms(2); + sfbus_send_frame(0xFFFF, &msg, 1); + } + else if (opcode == CMDB_RPWROFF) + { + mctrl_power(0); + } + else if (opcode == CMDB_PWRON) + { + mctrl_power(1); + } + else if (opcode == CMDB_RESET) + { + do + { + wdt_enable(WDTO_15MS); + for (;;) + { + } + } while (0); + } + else + { + // invalid opcode + char msg = CMDR_ERR_INVALID; + _delay_ms(2); + sfbus_send_frame(0xFFFF, &msg, 1); + } + } + free(payload); +} + +int main() +{ + initialSetup(); + rs485_init(); + mctrl_init(); + + while (1 == 1) + { + readCommand(); + } } diff --git a/software/firmware_module/module_rev0/src/mctrl.c b/software/firmware_module/module_rev0/src/mctrl.c index e2a0fa1..87bfd2c 100644 --- a/software/firmware_module/module_rev0/src/mctrl.c +++ b/software/firmware_module/module_rev0/src/mctrl.c @@ -17,11 +17,11 @@ uint8_t motor_steps[4] = { 0b00001000, }; -uint8_t step_index = 0; // cuurent index in motor_steps -uint8_t target_flap = 0; // target flap -uint16_t absolute_pos = 0; // absolute position in steps -uint16_t rel_offset = 1400; // offset of '0' flap relative to home -uint16_t steps_since_home = 0; // steps since last home signal +uint8_t step_index = 0; // cuurent index in motor_steps +uint8_t target_flap = 0; // target flap +uint16_t absolute_pos = 0; // absolute position in steps +uint16_t rel_offset = STEPS_OFFSET; // offset of '0' flap relative to home +uint16_t steps_since_home = 0; // steps since last home signal // homing util variables uint8_t homing = 0; // current homing step @@ -48,204 +48,254 @@ uint8_t currentFaultReadings = 0; // ticks with faulty readings (too many will // trip pwrdwn and sts_flag_fuse) // initialize motor controller -void mctrl_init() { - DDRC = 0x0F; // set all pins as outputs - PORTC = 0x00; // set all to LOW +void mctrl_init() +{ + DDRC = 0x0F; // set all pins as outputs + PORTC = 0x00; // set all to LOW - DDRD &= ~(1 << PD3); // PD3 is input - PORTD |= (1 << PD3); // PD3 pullup + DDRD &= ~(1 << PD3); // PD3 is input + PORTD |= (1 << PD3); // PD3 pullup - // setup adc - ADMUX = 0x07; // Aref, ADC7 - ADCSRA = - (1 << ADEN) | (1 << ADSC) | (1 << ADPS1); // Enable ADC, Start first - // reading No frerunning, 8MHz - while ((ADCSRA & (1 << ADSC)) > 0) - ; // wait until first reading is complete, - // to avoid error flag on first tick! + // setup adc + ADMUX = 0x07; // Aref, ADC7 + ADCSRA = (1 << ADEN) | (1 << ADSC) | (1 << ADPS1); // Enable ADC, Start first + // reading No frerunning, 8MHz + while ((ADCSRA & (1 << ADSC)) > 0) + { + }; + // wait until first reading is complete, + // to avoid error flag on first tick! - // setup timer for ISR - TCCR1A = 0; - TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // CTC und Prescaler 64 - OCR1A = 480; // 8.000.000 / 64 / 1000 für 1ms - OCR1A = 580; // 8.000.000 / 64 / 1000 für 1ms - - // OCR1A = 450; // 8.000.000 / 64 / - // 1000 für 1ms - TIMSK = 1 << OCIE1A; // Timerinterrupts aktivieren - homing = 1; - delta_err = malloc(ERROR_DATASETS * sizeof(uint16_t)); - _delay_ms(1000); - sei(); + // setup timer for ISR + TCCR1A = 0; + TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // CTC und Prescaler 64 + OCR1A = MISR_OCR1A; + TIMSK = 1 << OCIE1A; // Timerinterrupts aktivieren + homing = 1; + delta_err = malloc(ERROR_DATASETS * sizeof(uint16_t)); + _delay_ms(MDELAY_STARTUP); + sei(); } // call when critical fail. Powers down motor and sets flags -void failSafe() { - sts_flag_failsafe = 1; - PORTC = 0x00; +void failSafe() +{ + sts_flag_failsafe = 1; + PORTC = 0x00; } // read voltage non blocking (called every tick) -void readVoltage() { - currentVoltage = ADC; // read last measurement - ADMUX = 0x07; // select ADC7 - ADCSRA |= (1 << ADSC); // trigger next reading - if (currentVoltage < 128) { // if voltage is too low, fuse is probably broken - currentFaultReadings++; - if (currentFaultReadings > 20) { // too many fault readings trigger failSafe - sts_flag_fuse = 1; - failSafe(); +void readVoltage() +{ + currentVoltage = ADC; // read last measurement + ADMUX = 0x07; // select ADC7 + ADCSRA |= (1 << ADSC); // trigger next reading + if (currentVoltage < MVOLTAGE_LSTOP) + { // if voltage is too low, fuse is probably broken + currentFaultReadings++; + if (currentFaultReadings > MVOLTAGE_FAULTRD) + { // too many fault readings trigger failSafe + sts_flag_fuse = 1; + failSafe(); + } } - } } // MAIN service routine. Called by timer 1 -ISR(TIMER1_COMPA_vect) { - readVoltage(); // read and check voltage - if (sts_flag_pwrdwn == 1 || sts_flag_failsafe == 1) { - return; - } // if sts_flag_pwrdwn, STOP! - if (steps_since_home > - STEPS_PER_REV * 1.5) { // check if home is missing for too long - // home missing error. Wheel probably stuck or power fail - sts_flag_noHome = 1; - failSafe(); - } else if (homing == 1) { // Homing procedure 1. step: move out of home - if ((PIND & (1 << PD3)) > 0) { - homing = 2; - } else { - mctrl_step(); +ISR(TIMER1_COMPA_vect) +{ + readVoltage(); // read and check voltage + if (sts_flag_pwrdwn == 1 || sts_flag_failsafe == 1) + { + return; + } // if sts_flag_pwrdwn, STOP! + if (steps_since_home > STEPS_PER_REV * MHOME_TOLERANCE) + { // check if home is missing for too long + // home missing error. Wheel probably stuck or power fail + sts_flag_noHome = 1; + failSafe(); } - } else if (homing == 2) { // Homing procedure 2. step: find magnet - mctrl_step(); - if ((PIND & (1 << PD3)) == 0) { - homing = 3; - steps_since_home = 0; - absolute_pos = rel_offset; - incrementCounter(); - } - } else if (homing == 3) { // Homing procedure 3. step: find magnet - if (absolute_pos <= 0) { - homing = 0; - absolute_pos = rel_offset; - } - mctrl_step(); - absolute_pos--; - } else { // when no failsafe is triggered and homing is done - // calculate target position - uint16_t target_pos = (target_flap * STEPS_PER_FLAP) + rel_offset; - if (target_pos >= STEPS_PER_REV) { - target_pos -= STEPS_PER_REV; - } - if (absolute_pos != target_pos) { - // if target position is not reached, move motor - ticksSinceMove = 0; - mctrl_step(); - absolute_pos++; - if (absolute_pos >= STEPS_PER_REV) { - absolute_pos -= STEPS_PER_REV; - } - // detect home position - if ((PIND & (1 << PD3)) == 0) { - if (lastSens == 0) { - // new home transition - int16_t errorDelta = - (absolute_pos > (STEPS_PER_REV / 2) ? absolute_pos - STEPS_PER_REV - : absolute_pos); - sts_flag_errorTooBig = - (errorDelta > 30) || (errorDelta < -30) ? 1 : 0; - // storeErr(errorDelta); - absolute_pos = 0; - steps_since_home = 0; - // increment rotations counter - incrementCounter(); + else if (homing == 1) + { // Homing procedure 1. step: move out of home + if ((PIND & (1 << PD3)) > 0) + { + homing = 2; + } + else + { + mctrl_step(); } - lastSens = 1; - } else { - lastSens = 0; - } - } else { // if target position is reached - if (afterRotation < 55) { // if after rotation is set, apply it as new target - target_flap = afterRotation; - afterRotation = 255; - } else if (ticksSinceMove < 2) { // if motor has not been moved - sts_flag_busy = 0; - } else if (ticksSinceMove < 50) { // if motor has not been moved - ticksSinceMove++; - } else { // power off after 50 ticks - // PORTC = 0x00; // turn off stepper - } } - } - rc_tick(); // process counter tick, non-blocking + else if (homing == 2) + { // Homing procedure 2. step: find magnet + mctrl_step(); + if ((PIND & (1 << PD3)) == 0) + { + homing = 3; + steps_since_home = 0; + absolute_pos = rel_offset; + incrementCounter(); + } + } + else if (homing == 3) + { // Homing procedure 3. step: find magnet + if (absolute_pos <= 0) + { + homing = 0; + absolute_pos = rel_offset; + } + mctrl_step(); + absolute_pos--; + } + else + { // when no failsafe is triggered and homing is done + // calculate target position + uint16_t target_pos = (target_flap * STEPS_PER_FLAP) + rel_offset; + if (target_pos >= STEPS_PER_REV) + { + target_pos -= STEPS_PER_REV; + } + if (absolute_pos != target_pos) + { + // if target position is not reached, move motor + ticksSinceMove = 0; + mctrl_step(); + absolute_pos++; + if (absolute_pos >= STEPS_PER_REV) + { + absolute_pos -= STEPS_PER_REV; + } + // detect home position + if ((PIND & (1 << PD3)) == 0) + { + if (lastSens == 0) + { + // new home transition + int16_t errorDelta = + (int16_t)(absolute_pos > (STEPS_PER_REV / 2) ? absolute_pos - STEPS_PER_REV : absolute_pos); + sts_flag_errorTooBig = (errorDelta > MHOME_ERRDELTA) || (errorDelta < -MHOME_ERRDELTA) ? 1 : 0; + // storeErr(errorDelta); + absolute_pos = 0; + steps_since_home = 0; + // increment rotations counter + incrementCounter(); + } + lastSens = 1; + } + else + { + lastSens = 0; + } + } + else + { // if target position is reached + if (afterRotation < (STEPS_PER_FLAP + 5)) + { // if after rotation is set, apply it as new target + target_flap = afterRotation; + afterRotation = 255; + } + else if (ticksSinceMove < 2) + { // if motor has not been moved + sts_flag_busy = 0; + } + else if (ticksSinceMove < MPWRSVG_TICKSTOP) + { // if motor has not been moved + ticksSinceMove++; + } + else + { // power off after 50 ticks + // PORTC = 0x00; // turn off stepper + } + } + } + rc_tick(); // process counter tick, non-blocking } // TODO -void storeErr(int16_t error) { - int16_t *delta_err_tmp = malloc(ERROR_DATASETS * sizeof(uint16_t)); - memcpy(delta_err, delta_err_tmp + sizeof(uint16_t), - ((ERROR_DATASETS - 2) * sizeof(uint16_t))); - memcpy(&error, delta_err_tmp, sizeof(uint16_t)); - free(delta_err); - delta_err = delta_err_tmp; +void storeErr(int16_t error) +{ + int16_t *delta_err_tmp = malloc(ERROR_DATASETS * sizeof(uint16_t)); + memcpy(delta_err, delta_err_tmp + sizeof(uint16_t), ((ERROR_DATASETS - 2) * sizeof(uint16_t))); + memcpy(&error, delta_err_tmp, sizeof(uint16_t)); + free(delta_err); + delta_err = delta_err_tmp; } // TODO -void getErr(int16_t *error) { - memcpy(delta_err, error, (ERROR_DATASETS * sizeof(uint16_t))); +void getErr(int16_t *error) +{ + memcpy(delta_err, error, (ERROR_DATASETS * sizeof(uint16_t))); } // return status flag -uint8_t getSts() { - uint8_t status = sts_flag_errorTooBig; // bit 0: delta too big - status |= sts_flag_noHome << 1; // bit 1: no home found - status |= sts_flag_fuse << 2; // bit 2: fuse blown - status |= sts_flag_pwrdwn << 4; // bit 4: device powered down - status |= sts_flag_failsafe << 5; // bit 5: failsafe active - status |= sts_flag_busy << 6; // bit 6: failsafe active - if ((PIND & (1 << PD3)) == 0) { - status |= (1 << 3); - } - return status; +uint8_t getSts() +{ + uint8_t status = sts_flag_errorTooBig; // bit 0: delta too big + status |= sts_flag_noHome << 1; // bit 1: no home found + status |= sts_flag_fuse << 2; // bit 2: fuse blown + status |= sts_flag_pwrdwn << 4; // bit 4: device powered down + status |= sts_flag_failsafe << 5; // bit 5: failsafe active + status |= sts_flag_busy << 6; // bit 6: failsafe active + if ((PIND & (1 << PD3)) == 0) + { + status |= (1 << 3); + } + return status; } // return voltage -uint16_t getVoltage() { return currentVoltage; } +uint16_t getVoltage() +{ + return currentVoltage; +} // set target flap -void mctrl_set(uint8_t flap, uint8_t fullRotation) { - sts_flag_busy = 1; - if (fullRotation == 0) { - target_flap = flap; - // if (absolute_pos < STEPS_ADJ) { - // absolute_pos += STEPS_PER_REV; - // } - // absolute_pos -= STEPS_ADJ; - } else { - target_flap = (target_flap + (STEPS_PER_FLAP - 1)) % STEPS_PER_FLAP; - afterRotation = flap; - } +void mctrl_set(uint8_t flap, uint8_t fullRotation) +{ + sts_flag_busy = 1; + if (fullRotation == 0) + { + target_flap = flap; + // if (absolute_pos < STEPS_ADJ) { + // absolute_pos += STEPS_PER_REV; + // } + // absolute_pos -= STEPS_ADJ; + } + else + { + target_flap = (target_flap + (STEPS_PER_FLAP - 1)) % STEPS_PER_FLAP; + afterRotation = flap; + } } // trigger home procedure -void mctrl_home() { homing = 1; } +void mctrl_home() +{ + homing = 1; +} // trigger home procedure -void mctrl_power(uint8_t state) { - if (state == 0) { - sts_flag_pwrdwn = 1; - PORTC = 0x00; - }else{ - sts_flag_pwrdwn = 0; - PORTC = motor_steps[step_index]; - } +void mctrl_power(uint8_t state) +{ + if (state == 0) + { + sts_flag_pwrdwn = 1; + PORTC = 0x00; + } + else + { + sts_flag_pwrdwn = 0; + PORTC = motor_steps[step_index]; + } } // do stepper step (I/O) -void mctrl_step() { - step_index++; - steps_since_home++; - if (step_index > 3) { - step_index = 0; - } - PORTC = motor_steps[step_index]; +void mctrl_step() +{ + step_index++; + steps_since_home++; + if (step_index > 3) + { + step_index = 0; + } + PORTC = motor_steps[step_index]; } diff --git a/software/firmware_module/module_rev0/src/mctrl.h b/software/firmware_module/module_rev0/src/mctrl.h index bc9861c..e633370 100644 --- a/software/firmware_module/module_rev0/src/mctrl.h +++ b/software/firmware_module/module_rev0/src/mctrl.h @@ -12,13 +12,23 @@ #pragma once +#define STEPS_PER_REV 2025 // steps per revolution +#define STEPS_PER_FLAP 45 // steps per flap +#define STEPS_ADJ 0 // added per flap to compensate for motor power down +#define STEPS_OFFSET 1400 // ansolute offset between home and first flap +#define AMOUNTFLAPS 45 // amount of flaps installed in system -#define STEPS_PER_REV 2025 -#define STEPS_PER_FLAP 45 -#define STEPS_ADJ 0 // added per flap to compensate for motor power down -#define AMOUNTFLAPS 45 +#define ERROR_DATASETS 8 // length of error array -#define ERROR_DATASETS 8 +#define MDELAY_STARTUP 1000 // delay to wait after motor startup +#define MHOME_TOLERANCE 1.5 // tolerance for intial homing procedure +#define MHOME_ERRDELTA 30 // maximum deviation between expected home and actual home +#define MVOLTAGE_FAULTRD 20 // max. amount of fault readings before flag is set +#define MVOLTAGE_LSTOP 128 // lower voltage threshold for fuse detection +#define MPWRSVG_TICKSTOP 50 // inactive ticks before motor shutdown + +#define MISR_OCR1A 580 // tick timer (defines rotation speed) +// 450, 480 also possible ? #ifdef __cplusplus extern "C" { diff --git a/software/firmware_module/module_rev0/src/rcount.c b/software/firmware_module/module_rev0/src/rcount.c index 789831f..1975456 100644 --- a/software/firmware_module/module_rev0/src/rcount.c +++ b/software/firmware_module/module_rev0/src/rcount.c @@ -9,46 +9,59 @@ #include "rcount.h" -uint8_t rc_eeprom_write_c(uint16_t address, uint8_t data) { - // disable interrupt - if (EECR & (1 << EEWE)) { return 1; } - EEAR = address; - EEDR = data; - EECR |= (1 << EEMWE); // enable Master Write Enable - EECR |= (1 << EEWE); // write one - return 0; +uint8_t rc_eeprom_write_c(uint16_t address, uint8_t data) +{ + // disable interrupt + if (EECR & (1 << EEWE)) + { + return 1; + } + EEAR = address; + EEDR = data; + EECR |= (1 << EEMWE); // enable Master Write Enable + EECR |= (1 << EEWE); // write one + return 0; } -uint8_t rc_eeprom_read_c(uint16_t address) { - while (EECR & (1 << EEWE)) - ; // wait until previous write is done - EEAR = address; - EECR |= (1 << EERE); // read one - return EEDR; +uint8_t rc_eeprom_read_c(uint16_t address) +{ + while (EECR & (1 << EEWE)) + ; // wait until previous write is done + EEAR = address; + EECR |= (1 << EERE); // read one + return EEDR; } uint32_t counter = (uint32_t)0xFFFFFFFF; uint8_t counter_phase = 5; -void rc_tick() { - if (counter == (uint32_t)0xFFFFFFFF) { counter = rc_getCounter(); } - if (counter_phase < 5) { - cli(); - if (rc_eeprom_write_c(0x100 + counter_phase, ((counter >> (counter_phase * 8)) & 0xFF)) == 0) { - counter_phase++; +void rc_tick() +{ + if (counter == (uint32_t)0xFFFFFFFF) + { + counter = rc_getCounter(); + } + if (counter_phase < 5) + { + cli(); + if (rc_eeprom_write_c(0x100 + counter_phase, ((counter >> (counter_phase * 8)) & 0xFF)) == 0) + { + counter_phase++; + } + sei(); } - sei(); - } } -void incrementCounter() { - counter++; - counter_phase = 0; +void incrementCounter() +{ + counter++; + counter_phase = 0; } -uint32_t rc_getCounter() { - uint32_t counter = rc_eeprom_read_c(0x100); - counter |= ((uint32_t)rc_eeprom_read_c(0x101) << 8); - counter |= ((uint32_t)rc_eeprom_read_c(0x102) << 16); - counter |= ((uint32_t)rc_eeprom_read_c(0x103) << 24); - return counter; +uint32_t rc_getCounter() +{ + uint32_t counter = rc_eeprom_read_c(RC_BASEADDR); + counter |= ((uint32_t)rc_eeprom_read_c(RC_BASEADDR + 1) << SHIFT_1B); + counter |= ((uint32_t)rc_eeprom_read_c(RC_BASEADDR + 2) << SHIFT_2B); + counter |= ((uint32_t)rc_eeprom_read_c(RC_BASEADDR + 3) << SHIFT_3B); + return counter; } diff --git a/software/firmware_module/module_rev0/src/rcount.h b/software/firmware_module/module_rev0/src/rcount.h index d4e0d8e..6b848a0 100644 --- a/software/firmware_module/module_rev0/src/rcount.h +++ b/software/firmware_module/module_rev0/src/rcount.h @@ -8,6 +8,8 @@ #include "global.h" +#define RC_BASEADDR 0x100 + #ifdef __cplusplus extern "C" { #endif // __cplusplus